annotate lib/unlink.c @ 16358:a712776b11ce

maint: spelling fixes
author Paul Eggert <eggert@cs.ucla.edu>
date Sun, 05 Feb 2012 13:42:03 -0800
parents 8250f2777afc
children e542fd46ad6f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
1 /* Work around unlink bugs.
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
2
16201
8250f2777afc maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents: 14393
diff changeset
3 Copyright (C) 2009-2012 Free Software Foundation, Inc.
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
4
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
5 This program is free software: you can redistribute it and/or modify
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
6 it under the terms of the GNU General Public License as published by
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
7 the Free Software Foundation; either version 3 of the License, or
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
8 (at your option) any later version.
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
9
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
10 This program is distributed in the hope that it will be useful,
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
13 GNU General Public License for more details.
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
14
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
15 You should have received a copy of the GNU General Public License
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
17
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
18 #include <config.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
19
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
20 #include <unistd.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
21
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
22 #include <errno.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
23 #include <stdlib.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
24 #include <string.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
25 #include <sys/stat.h>
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
26
14393
9f47f8c334f2 dirname: move m4/dos.m4 functionality into lib/dosname.h
Paul Eggert <eggert@cs.ucla.edu>
parents: 14079
diff changeset
27 #include "dosname.h"
9f47f8c334f2 dirname: move m4/dos.m4 functionality into lib/dosname.h
Paul Eggert <eggert@cs.ucla.edu>
parents: 14079
diff changeset
28
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
29 #undef unlink
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
30
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
31 /* Remove file NAME.
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
32 Return 0 if successful, -1 if not. */
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
33
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
34 int
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
35 rpl_unlink (char const *name)
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
36 {
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
37 /* Work around Solaris 9 bug where unlink("file/") succeeds. */
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
38 size_t len = strlen (name);
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
39 int result = 0;
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
40 if (len && ISSLASH (name[len - 1]))
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
41 {
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
42 /* We can't unlink(2) something if it doesn't exist. If it does
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
43 exist, then it resolved to a directory, due to the trailing
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
44 slash, and POSIX requires that the unlink attempt to remove
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
45 that directory (which would leave the symlink dangling).
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
46 Unfortunately, Solaris 9 is one of the platforms where the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
47 root user can unlink directories, and we don't want to
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
48 cripple this behavior on real directories, even if it is
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
49 seldom needed (at any rate, it's nicer to let coreutils'
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
50 unlink(1) give the correct errno for non-root users). But we
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
51 don't know whether name was an actual directory, or a symlink
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
52 to a directory; and due to the bug of ignoring trailing
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
53 slash, Solaris 9 would end up successfully unlinking the
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
54 symlink instead of the directory. Technically, we could use
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
55 realpath to find the canonical directory name to attempt
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
56 deletion on. But that is a lot of work for a corner case; so
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
57 we instead just use an lstat on the shortened name, and
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
58 reject symlinks with trailing slashes. The root user of
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
59 unlink(1) will just have to live with the rule that they
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
60 can't delete a directory via a symlink. */
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
61 struct stat st;
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
62 result = lstat (name, &st);
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
63 if (result == 0)
12421
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
64 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
65 /* Trailing NUL will overwrite the trailing slash. */
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
66 char *short_name = malloc (len);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
67 if (!short_name)
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
68 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
69 errno = EPERM;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
70 return -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
71 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
72 memcpy (short_name, name, len);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
73 while (len && ISSLASH (short_name[len - 1]))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
74 short_name[--len] = '\0';
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
75 if (len && (lstat (short_name, &st) || S_ISLNK (st.st_mode)))
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
76 {
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
77 free (short_name);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
78 errno = EPERM;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
79 return -1;
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
80 }
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
81 free (short_name);
e8d2c6fc33ad Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents: 12040
diff changeset
82 }
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
83 }
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
84 if (!result)
13016
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
85 {
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
86 #if UNLINK_PARENT_BUG
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
87 if (len >= 2 && name[len - 1] == '.' && name[len - 2] == '.'
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
88 && (len == 2 || ISSLASH (name[len - 3])))
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
89 {
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
90 errno = EISDIR; /* could also use EPERM */
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
91 return -1;
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
92 }
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
93 #endif
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
94 result = unlink (name);
e627775450ed Work around unlink() bug on MacOS X 10.5.6.
Bruno Haible <bruno@clisp.org>
parents: 12559
diff changeset
95 }
12040
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
96 return result;
e8108d5c7ca7 unlink: new module, for Solaris 9 bug
Eric Blake <ebb9@byu.net>
parents:
diff changeset
97 }