Creating Factor Standalone Applications

I recently decided to complete my idea for a “smart” copy application which would use move operations instead of copy then delete whenever possible. The app would also be able to compare before copying and if the source file is identical to the destination no action is necessary.

Why would anyone want to do this instead of just the current tools available? Well, consider the following:

  • If you live on a fairly slow Internet connection as I do then copying over such a link becomes expensive in terms of time.
  • On a local LAN or even within the local file system on your computer it can come in handy when disk space is getting low and using traditional tools requires a copy before deleting which is the case when the permissions of the local folder are not set to permit moving.
  • Sometimes the dates get messed up and one file appears to be newer than another one even though they are really identical. Or names are different on identical files, think pictures and music.
  • Sometimes you just want information about the differences between two folders. Which items in folder A are missing from folder B. Which items are identical, or which items are in both folders.

Given these goals I set out to create a utility which would accomplish them as I recently had to pull in a hard drive and consolidate its contents. Since the content was huge, something on the order of 800MB and I only had 300MB on my local hard drive it was obvious I could not just make a simple copy nor did I want to as the drive in question contained dozens of folders whose content was similar as the owner did not use a version control system and simply made duplicate folders.

Thus is born the Factor code for fFolders which can be found on Git

 

Software Licensing

I recently had to research software license issues for the upcoming OpenPrograph project. Reading and discussing the issue with colleagues I have come to the decision for licensing my own code I will adopt the License Free concept which simply uses the existing copyright law. An excellent article on the subject can be found at http://thedjbway.b0llix.net/license_free.html which basically promotes the idea that existing copyright law protects your work.

In accordance with the article, my work will have the simple copyright statement, Copyright <YEAR> Dave Carlton, PolyMicro Systems. There is no license at all for work released under this model, just a plain simple statement of copyright which permits me to publish work while protecting my integrity and which allows you to use it. The U.S. Code has decades of legal precedence protecting works which are copyrighted. In fact, I agree with the premise that software license are basically unenforceable. So essentially it resolves to these statements in regards to your use of my work.

  • You may freely download the software
  • Once you download it, you legally own a copy of the work
  • You can patch it, modify it, compile it, and use your copy however you want
  • You can run the software with no obligation or implied contract
  • You can study the code and learn from it
  • You can develop patches to the code and distribute them however you please

What you cannot do is:

  • You cannot redistribute the software
  • You cannot redistribute modified versions of the software

This is what “copyright” is all about; the holder of the copyright is the only one who legally has the “right” to “copy” the work, unless and until the holder explicitly grants such rights to others. I am not a lawyer but a software developer and programmer. I dislike having to wade thru legal documents when my time can be better spent doing something actually constructive. This is my primary motivation for adopting the concept of License Free software. If you desire to do more with my work, just ask. It’s that simple, I most likely will consider your request favorably.

Software Users Rights

From the cr.yp.to site, in the United States, once you own a copy of a program, you can back it up, compile it, run it, and even modify it as necessary, without permission from the copyright holder. See 17 USC 117 for yourself. I’m not going to repeat the entire discourse here, if you want to know more see this page at the cr.yp.to site

Internet Readers Rights

Also from the cr.yp.to site, some people think that every Internet user is a copyright violator. Downloading a document means making a copy of it, they say; and copying generally isn’t legal without the author’s permission. They argue about whether making material available through FTP or HTTP or USENET grants some sort of “implied license” to download the material—or whether an author can demand payment for the reader’s copies.

Other people advocate a much simpler theory and is one to which I subscribe. When an author tells his FTP server or authorizes an account on a remote server to send a document to anyone who asks, the author is the one making copies. In legal jargon, the author’s command to the computer is the “proximate cause” of the copying. The reader is merely requesting a copy, not making it.

I don’t know which of these theories will succeed in court. I also don’t think you should have to care. So I promise I won’t sue you for copyright violation for downloading documents from my server or from accounts on remote servers.

Does it bother you that this should even be an issue? Check out Richard Stallman’s essay on The Right to Read. Precedents can be dangerous.

Specific Distribution Terms

This is for people who want to distribute copies of my software or derivative works. You don’t need to read this page if you simply want to use my software. You are free to download the software from my web server; you then own that copy of the software, and you are free to compile it and run it. You also don’t need to read this page if you simply want to set up a mirror of my web pages.

GitHub Pubic Repositories

All public repositories located under my personal page at GitHub are placed into the public domain.

BitBucket Public Repositories

All public repositories located on my person page at BitBucket are placed into the public domain.

Public Domain

The normal way to abandon a copyright is to make a clear written dedication of the work, an overt act, to the public domain. For example:

  • Most documents have a conventional location for a copyright notice (e.g., the bottom of page 1 of a scientific paper). You can write “Public domain” in this location rather than “Copyright 2005,” “Copyright 2006,” etc. This, by itself, clearly satisfies the “overt act” test.
  • You can write a subsequent document saying “I hereby place my paper `On The Origin Of Species’ into the public domain.” This, by itself, clearly satisfies the “overt act” test.
  • This web page suffices as an overt act of my placement of software into the public domain.

How do courts resolve disputes over public-domain status?

The Ninth Circuit Model Civil Jury Instructions, 2007 edition, Section 17.19, states a model for the text that courts give to juries:

17.19 COPYRIGHT – AFFIRMATIVE DEFENSE – ABANDONMENT

The defendant contends that a copyright does not exist in the plaintiff’s work because the plaintiff abandoned the copyright. The plaintiff cannot claim ownership of the copyright if it was abandoned. In order to show abandonment, the defendant has the burden of proving each of the following by a preponderance of the evidence:

1. the plaintiff intended to surrender [ownership] rights in the work; and

2. an act by the plaintiff evidencing that intent.

Mere inaction [, or publication without a copyright notice,] does not constitute abandonment of the copyright; however, [this may be a factor] [these may be factors] for you to consider in determining whether the plaintiff has abandoned the copyright.

If you find that the plaintiff has proved [his] [her] [its] claim[s] in accordance with Instruction[s] [insert cross reference to the pertinent instructions on the plaintiff's theory of infringement], your verdict should be for the plaintiff, unless you find that the defendant has proved each of the elements of this affirmative defense, in which event your verdict should be for the defendant.

See also Section 20.19 in the 2001 edition.

Links

Some useful links I found while researching.

http://sam.zoy.org/wtfpl/

http://www.opensource.org/licenses/category

http://www.ruby-forum.com/topic/61430

http://www.gnu.org/licenses/license-recommendations.html

http://khason.net/blog/open-source-licenses-comparison-table/

Working with mdimport

Working with mdimport and trying to build a spotlight importer for Factor I ran across some difficulty. After installing the first version which seemed to have loaded ok I wanted to make some changes. I thought the importer was loaded since using the -L and -A options indicated the importer was installed.

mdimport -L
2011-12-28 12:14:32.437 mdimport[14337:707] Paths: id(501) (
…
    "/System/Library/Spotlight/CoreMedia.mdimporter",
    "/Users/davec/Library/Spotlight/SymbolSpotlighter.mdimporter",
    "/Users/davec/Library/Spotlight/FactorSpotlight.mdimporter",
    "/System/Library/Spotlight/Chat.mdimporter",
    "/System/Library/Spotlight/iPhoto.mdimporter",
…
)
 mdimport -A
…
'kMDItemWhiteBalance'		'White balance'		'White balance setting of the camera when the picture was taken'		'whitebalance'
'objectfile_export_symbols'		'(null)'		'Symbols to be imported'		'(null)'
'objectfile_import_symbols'		'(null)'		'Symbols to be exported'		'(null)'
'objectfile_path'		'(null)'		'Path of object file'		'(null)'
'public_factor_definitions'		'Definitions created in Factor file'		'(null)'		'(null)'
'public_factor_uses'		'Vocabularies used by Factor file'		'(null)'		'(null)'

However, testing the importer using the -g option shows the importer was not being executed.

mdimport -d2 -g /Users/davec/Library/Spotlight/FactorSpotlight.mdimporter test.factor

2011-12-28 12:01:33.212 mdimport[13913:707] loading plugin at path '/Users/davec/Library/Spotlight/FactorSpotlight.mdimporter' for UTIs: public.factor-source public.source-code.
(Info) Import: magic_file returned "ASCII text" for path "/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor" of type "dyn.ah62d4rv4ge80q2pdsv11e"
(Info) Import: magic identified path "/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor" type "dyn.ah62d4rv4ge80q2pdsv11e" as text; using text importer
(Info) Import: Importing type 'dyn.ah62d4rv4ge80q2pdsv11e' using 'InternalPlainText' - diagnostic:0 - find suspect file using: sudo mdutil -t 12916995
2011-12-28 12:01:33.232 mdimport[13913:707] Imported '/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor' of type 'dyn.ah62d4rv4ge80q2pdsv11e' with no plugIn.
2011-12-28 12:01:33.233 mdimport[13913:707] Attributes: {
    "_kMDItemFinderLabel" = 0;
…
}

Note that the first line indicated the importer was loaded but the later lines indicate the plugin was not used. This was confirmed by running the mdimport command under gdb and setting breakpoints on each function in the main.c file.

gdb /usr.bin/mdimport

(gdb) r -d2 -g /Users/davec/Library/Spotlight/FactorSpotlight.mdimporter test.factor
Starting program: /usr/bin/mdimport -d2 -g /Users/davec/Library/Spotlight/FactorSpotlight.mdimporter test.factor
2011-12-28 12:05:00.912 mdimport[14026:1307] loading plugin at path '/Users/davec/Library/Spotlight/FactorSpotlight.mdimporter' for UTIs: public.factor-source public.source-code.
Reading symbols for shared libraries . done
Breakpoint 1 at 0x1000b729f: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/GetMetadataForFile.m, line 24.
Pending breakpoint 1 - "GetMetadataForFile" resolved
Breakpoint 2 at 0x1000b7330: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 101.
Pending breakpoint 2 - "AllocMetadataImporterPluginType" resolved
Breakpoint 3 at 0x1000b742c: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 128.
Pending breakpoint 3 - "DeallocMetadataImporterPluginType" resolved
Breakpoint 4 at 0x1000b7508: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 145.
Pending breakpoint 4 - "MetadataImporterQueryInterface" resolved
Breakpoint 5 at 0x1000b7768: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 181.
Pending breakpoint 5 - "MetadataImporterPluginAddRef" resolved
Breakpoint 6 at 0x1000b778c: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 193.
Pending breakpoint 6 - "MetadataImporterPluginRelease" resolved
Breakpoint 7 at 0x1000b786a: file /Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/main.c, line 215.
Pending breakpoint 7 - "MetadataImporterPluginFactory" resolved
(Info) Import: magic_file returned "ASCII text" for path "/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor" of type "dyn.ah62d4rv4ge80q2pdsv11e"
(Info) Import: magic identified path "/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor" type "dyn.ah62d4rv4ge80q2pdsv11e" as text; using text importer
(Info) Import: Importing type 'dyn.ah62d4rv4ge80q2pdsv11e' using 'InternalPlainText' - diagnostic:0 - find suspect file using: sudo mdutil -t 12916995
2011-12-28 12:05:00.957 mdimport[14026:1307] Imported '/Users/davec/Dropbox/Public/factor/FactorFinder/FactorSpotlight/test.factor' of type 'dyn.ah62d4rv4ge80q2pdsv11e' with no plugIn.
2011-12-28 12:05:00.959 mdimport[14026:1307] Attributes: {
....

Again, the importer was loaded as indicated by the breakpoints being resolved but never hit.

So there must be something about the Info.plist or schema.xml file that causes it to be rejected although running

mdcheckschema schema.xml
1
mdcheckschema schema.xml

results in no errors being reported.

I started examining another spotlight importer SymbolSpotlight which was running fine and returning results correctly and was able to set breakpoints using mdimport as a run time executable for the plugin in Xcode 4.

Factor Info.plist

FactorSpotlight.png

SymbolSpotlight Info.plist

SynbolSpotlight Info.plist.png

Both plists look correct, I can’t see any problems here.