Howdy, The following hack implements the --firm/-m option for ln so that it will create firm links. Now, most GNU/Linux people won't be familiar with the concept, and I'm not really sure how to explain it either. The best example I can think of that explains the difference between symlinks and firmlinks is the following:
hurd:/home/ams/coreutils/coreutils/src# ./ln -s /ams/foo symlink hurd:/home/ams/coreutils/coreutils/src# ./ln -m /ams/foo firmlink hurd:/home/ams/coreutils/coreutils/src# cd symlink hurd:/home/ams/coreutils/coreutils/src/symlink# ls .. foo hurd.obj lost+found oskit.obj sub-hurd hurd:/home/ams/coreutils/coreutils/src/symlink# cd ../firmlink hurd:/home/ams/coreutils/coreutils/src/firmlink# ls .. CVS Makefile Makefile.am [..snip...] hurd:/home/ams/coreutils/coreutils/src/firmlink# ls hurd:/home/ams/coreutils/coreutils/src/firmlink# ls /ams/foo hurd:/home/ams/coreutils/coreutils/src/firmlink# touch foo hurd:/home/ams/coreutils/coreutils/src/firmlink# ls -l total 0 -rw-r--r-- 1 root root 0 Jan 25 02:48 foo hurd:/home/ams/coreutils/coreutils/src/firmlink# ls -l /ams/foo total 0 -rw-r--r-- 1 root root 0 Jan 25 02:48 foo hurd:/home/ams/coreutils/coreutils/src/firmlink# As you see, a firmlink is more or less a "real" link, and doesn't exhibit the sometimes awkward behaviour of symbolic links (`ls ..' is one such example). Note that I didn't bother in creating a NEWS entry, or updating the manual. This is mostly a hack that I just wanted to share and get some comments about. For example, firmlink() should be moved into libc, _HURD_FIRMLINK should be defined in <hurd/paths.h>, propor autoconf checks should be created so that ln will compile on system that don't support firmlinks, etc. 2004-01-24 Alfred M. Szmidt <[EMAIL PROTECTED]> Added new option for `ln', --firm. * src/ln.c (firm_link): New variable. (long_options): Support new option `--firm'. (_HURD_FIRMLINK): New macro. (hurd_fail, firmlink): New functions. (do_link, usage, main): Support new option `--firm'. (do_link): Allow the creation of firmlinks for directories. *** src/ln.c.~1.132.~ Sat Oct 18 03:05:47 2003 --- src/ln.c Sun Jan 25 02:32:05 2004 *************** *** 96,107 **** enum backup_type backup_type; /* A pointer to the function used to make links. This will point to either ! `link' or `symlink'. */ static int (*linkfunc) (); /* If nonzero, make symbolic links; otherwise, make hard links. */ static int symbolic_link; /* If nonzero, ask the user before removing existing files. */ static int interactive; --- 96,110 ---- enum backup_type backup_type; /* A pointer to the function used to make links. This will point to either ! `link', `symlink' or `firmlink'. */ static int (*linkfunc) (); /* If nonzero, make symbolic links; otherwise, make hard links. */ static int symbolic_link; + /* If nonzero, make firm links; otherwise make hard links. */ + static int firm_link; + /* If nonzero, ask the user before removing existing files. */ static int interactive; *************** *** 133,138 **** --- 136,142 ---- {"suffix", required_argument, NULL, 'S'}, {"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION}, {"symbolic", no_argument, NULL, 's'}, + {"firm", no_argument, NULL, 'm'}, {"verbose", no_argument, NULL, 'v'}, {"version-control", required_argument, NULL, 'V'}, /* Deprecated. FIXME. */ {GETOPT_HELP_OPTION_DECL}, *************** *** 140,145 **** --- 144,234 ---- {NULL, 0, NULL, 0} }; + /* Snatched from glibc; and modified for firm links and some sort of + stand-aloneness. Should really be moved back into libc as a real + call. */ + + #include <string.h> + #include <unistd.h> + #include <hurd.h> + #include <hurd/paths.h> + #include <fcntl.h> + + #define _HURD_FIRMLINK _HURD "firmlink" + + int + hurd_fail (error_t err) + { + switch (err) + { + case EMACH_SEND_INVALID_DEST: + case EMIG_SERVER_DIED: + /* The server has disappeared! */ + err = EIEIO; + break; + + case KERN_NO_SPACE: + err = ENOMEM; + break; + + case KERN_INVALID_ARGUMENT: + err = EINVAL; + break; + + case 0: + return 0; + + default: + break; + } + + errno = err; + return -1; + } + + int + firmlink (const char *from, const char *to) + { + error_t err; + file_t dir, node; + char *name; + const size_t len = strlen (from) + 1; + char buf[sizeof (_HURD_FIRMLINK) + len]; + mode_t umask = getumask (); + + /* A firmlink is a file whose translator is "/hurd/firmlink\0target\0". */ + + memcpy (buf, _HURD_FIRMLINK, sizeof (_HURD_FIRMLINK)); + memcpy (&buf[sizeof (_HURD_FIRMLINK)], from, len); + + dir = file_name_split (to, &name); + if (dir == MACH_PORT_NULL) + return -1; + + /* Create a new, unlinked node in the target directory. */ + err = dir_mkfile (dir, O_WRITE, 0777 & ~umask, &node); + + if (! err) + /* Set the node's translator to make it a firmlink. */ + err = file_set_translator (node, + FS_TRANS_EXCL|FS_TRANS_SET, + FS_TRANS_EXCL|FS_TRANS_SET, 0, + buf, sizeof (_HURD_FIRMLINK) + len, + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); + + if (! err) + /* Link the node, now a valid link, into the target directory. */ + err = dir_link (dir, node, name, 1); + + mach_port_deallocate (mach_task_self (), dir); + mach_port_deallocate (mach_task_self (), node); + + if (err) + return hurd_fail (err); + return 0; + } + + /* Make a link DEST to the (usually) existing file SOURCE. Symbolic links to nonexistent files are allowed. If DEST is a directory, put the link to SOURCE in that directory. *************** *** 174,180 **** quote (source)); } ! if (!hard_dir_link && S_ISDIR (source_stats.st_mode)) { error (0, 0, _("%s: hard link not allowed for directory"), quote (source)); --- 263,269 ---- quote (source)); } ! if (!firm_link && !hard_dir_link && S_ISDIR (source_stats.st_mode)) { error (0, 0, _("%s: hard link not allowed for directory"), quote (source)); *************** *** 306,331 **** if (verbose) { ! printf ((symbolic_link ! ? _("create symbolic link %s to %s") ! : _("create hard link %s to %s")), ! quote_n (0, dest), quote_n (1, source)); if (backup_succeeded) printf (_(" (backup: %s)"), quote (dest_backup)); putchar ('\n'); } ! if ((*linkfunc) (source, dest) == 0) { return 0; } ! ! error (0, errno, ! (symbolic_link ! ? _("creating symbolic link %s to %s") ! : _("creating hard link %s to %s")), ! quote_n (0, dest), quote_n (1, source)); ! if (dest_backup) { if (rename (dest_backup, dest)) --- 395,432 ---- if (verbose) { ! if (symbolic_link) ! printf (_("create symbolic link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); ! else if (firm_link) ! printf (_("create firm link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); ! else ! printf (_("create hard link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); if (backup_succeeded) printf (_(" (backup: %s)"), quote (dest_backup)); putchar ('\n'); } ! if ((*linkfunc) (source, dest) == 0) { return 0; } ! ! if (symbolic_link) ! error (0, errno, ! _("creating symbolic link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); ! else if (firm_link) ! error (0, errno, ! _("creating firm link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); ! else ! error (0, errno, ! _("creating hard link %s to %s"), ! quote_n (0, dest), quote_n (1, source)); ! if (dest_backup) { if (rename (dest_backup, dest)) *************** *** 354,360 **** created in the current directory. When using the second form with more\n\ than one TARGET, the last argument must be a directory; create links\n\ in DIRECTORY to each TARGET. Create hard links by default, symbolic\n\ ! links with --symbolic. When creating hard links, each TARGET must exist.\n\ \n\ "), stdout); fputs (_("\ --- 455,462 ---- created in the current directory. When using the second form with more\n\ than one TARGET, the last argument must be a directory; create links\n\ in DIRECTORY to each TARGET. Create hard links by default, symbolic\n\ ! links with --symbolic and firm links with --firm. When creating hard\n\ ! links, each TARGET must exist.\n\ \n\ "), stdout); fputs (_("\ *************** *** 375,380 **** --- 477,485 ---- -s, --symbolic make symbolic links instead of hard links\n\ "), stdout); fputs (_("\ + -m, --firm make firm links instead of hard links\n \ + "), stdout); + fputs (_("\ -S, --suffix=SUFFIX override the usual backup suffix\n\ --target-directory=DIRECTORY specify the DIRECTORY in which to create\n\ the links\n\ *************** *** 430,436 **** = hard_dir_link = 0; errors = 0; ! while ((c = getopt_long (argc, argv, "bdfinsvFS:V:", long_options, NULL)) != -1) { switch (c) --- 535,541 ---- = hard_dir_link = 0; errors = 0; ! while ((c = getopt_long (argc, argv, "bdfinmsvFS:V:", long_options, NULL)) != -1) { switch (c) *************** *** 473,478 **** --- 578,591 ---- _("symbolic links are not supported on this system")); #endif break; + case 'm': + #if 1 + firm_link = 1; + #else + error (EXIT_FAILURE, 0, + _("firm links are not supported on this system")); + #endif + break; case TARGET_DIRECTORY_OPTION: target_directory = optarg; break; *************** *** 522,527 **** --- 635,642 ---- if (symbolic_link) linkfunc = symlink; + else if (firm_link) + linkfunc = firmlink; else linkfunc = link; _______________________________________________ Bug-hurd mailing list [EMAIL PROTECTED] http://mail.gnu.org/mailman/listinfo/bug-hurd