Mercurial > hg > octave-lojdl > gnulib-hg
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 |
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 } |