bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: confusing error message from ln


From: Paul Eggert
Subject: Re: confusing error message from ln
Date: Wed, 16 Nov 2005 14:38:15 -0800
User-agent: Gnus/5.1007 (Gnus v5.10.7) Emacs/21.4 (gnu/linux)

I installed the following in an attempt to address the issues brought
up in this thread, along with some other problems I noticed when
comparing GNU ln's to FreeBSD ln's behavior.

2005-11-16  Paul Eggert  <address@hidden>

        * NEWS: Improve quality of ln's diagnostics.
        * doc/coreutils.texi (ln invocation): ln -v now outputs lines only for
        successful links.
        * src/ln.c (do_link, usage): Likewise.
        (do_link): Don't use alloca on a buffer of unbounded size.

Index: NEWS
===================================================================
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.345
diff -p -u -r1.345 NEWS
--- NEWS        15 Nov 2005 18:03:26 -0000      1.345
+++ NEWS        16 Nov 2005 22:31:24 -0000
@@ -4,6 +4,10 @@ GNU coreutils NEWS                      
 
 ** Changes in behavior
 
+  ln now uses different (and we hope clearer) diagnostics when it fails.
+  ln -v now acts more like FreeBSD, so it generates output only when
+  successful and the output is easier to parse.
+
   ls now defaults to --time-style='locale', not --time-style='posix-long-iso'.
   However, the 'locale' time style now behaves like 'posix-long-iso'
   if your locale settings appear to be messed up.  This change
Index: doc/coreutils.texi
===================================================================
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.294
diff -p -u -r1.294 coreutils.texi
--- doc/coreutils.texi  8 Nov 2005 20:59:19 -0000       1.294
+++ doc/coreutils.texi  16 Nov 2005 22:31:30 -0000
@@ -7773,7 +7773,7 @@ an error message on systems that do not 
 @itemx --verbose
 @opindex -v
 @opindex --verbose
-Print the name of each file before linking it.
+Print the name of each file after linking it successfully.
 
 @end table
 
Index: src/ln.c
===================================================================
RCS file: /fetish/cu/src/ln.c,v
retrieving revision 1.154
diff -p -u -r1.154 ln.c
--- src/ln.c    5 Nov 2005 09:34:57 -0000       1.154
+++ src/ln.c    16 Nov 2005 22:31:36 -0000
@@ -138,6 +138,8 @@ do_link (const char *source, const char 
   struct stat dest_stats;
   char *dest_backup = NULL;
   bool lstat_ok = false;
+  bool source_is_dir = false;
+  bool ok;
 
   /* Use stat here instead of lstat.
      On SVR4, link does not follow symlinks, so this check disallows
@@ -159,11 +161,15 @@ do_link (const char *source, const char 
                 quote (source));
        }
 
-      if (!hard_dir_link && S_ISDIR (source_stats.st_mode))
+      if (S_ISDIR (source_stats.st_mode))
        {
-         error (0, 0, _("%s: hard link not allowed for directory"),
-                quote (source));
-         return false;
+         source_is_dir = true;
+         if (! hard_dir_link)
+           {
+             error (0, 0, _("%s: hard link not allowed for directory"),
+                    quote (source));
+             return false;
+           }
        }
     }
 
@@ -220,37 +226,22 @@ do_link (const char *source, const char 
 
       if (backup_type != no_backups)
        {
-         char *tmp_backup = find_backup_file_name (dest, backup_type);
-         size_t buf_len = strlen (tmp_backup) + 1;
-         dest_backup = alloca (buf_len);
-         memcpy (dest_backup, tmp_backup, buf_len);
-         free (tmp_backup);
-         if (rename (dest, dest_backup))
+         dest_backup = find_backup_file_name (dest, backup_type);
+         if (rename (dest, dest_backup) != 0)
            {
-             if (errno != ENOENT)
+             int rename_errno = errno;
+             free (dest_backup);
+             dest_backup = NULL;
+             if (rename_errno != ENOENT)
                {
-                 error (0, errno, _("cannot backup %s"), quote (dest));
+                 error (0, rename_errno, _("cannot backup %s"), quote (dest));
                  return false;
                }
-             else
-               dest_backup = NULL;
            }
        }
     }
 
-  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 (dest_backup)
-       printf (_(" (backup: %s)"), quote (dest_backup));
-      putchar ('\n');
-    }
-
-  if ((*linkfunc) (source, dest) == 0)
-    return true;
+  ok = (linkfunc (source, dest) == 0);
 
   /* If the attempt to create a link failed and we are removing or
      backing up destinations, unlink the destination and try again.
@@ -270,30 +261,52 @@ do_link (const char *source, const char 
      If we didn't remove DEST in that case, the subsequent LINKFUNC
      call would fail.  */
 
-  if (errno == EEXIST && (remove_existing_files || dest_backup))
+  if (!ok && errno == EEXIST && (remove_existing_files || dest_backup))
     {
       if (unlink (dest) != 0)
        {
          error (0, errno, _("cannot remove %s"), quote (dest));
+         free (dest_backup);
          return false;
        }
 
-      if (linkfunc (source, dest) == 0)
-       return true;
+      ok = (linkfunc (source, dest) == 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 (ok)
     {
-      if (rename (dest_backup, dest))
-       error (0, errno, _("cannot un-backup %s"), quote (dest));
+      if (verbose)
+       {
+         if (dest_backup)
+           printf ("%s ~ ", quote (dest_backup));
+         printf ("%s %c> %s\n", quote_n (0, dest), (symbolic_link ? '-' : '='),
+                 quote_n (1, source));
+       }
+    }
+  else
+    {
+      error (0, errno,
+            (symbolic_link
+             ? (errno != ENAMETOOLONG && *source
+                ? _("creating symbolic link %s")
+                : _("creating symbolic link %s -> %s"))
+             : (errno == EMLINK && !source_is_dir
+                ? _("creating hard link to %.0s%s")
+                : (errno == EDQUOT || errno == EEXIST || errno == ENOSPC
+                   || errno == EROFS)
+                ? _("creating hard link %s")
+                : _("creating hard link %s => %s"))),
+            quote_n (0, dest), quote_n (1, source));
+
+      if (dest_backup)
+       {
+         if (rename (dest_backup, dest) != 0)
+           error (0, errno, _("cannot un-backup %s"), quote (dest));
+       }
     }
-  return false;
+
+  free (dest_backup);
+  return ok;
 }
 
 void
@@ -341,7 +354,7 @@ Mandatory arguments to long options are 
   -t, --target-directory=DIRECTORY  specify the DIRECTORY in which to create\n\
                                 the links\n\
   -T, --no-target-directory   treat LINK_NAME as a normal file\n\
-  -v, --verbose               print name of each file before linking\n\
+  -v, --verbose               print name of each linked file\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]