Wed Aug 6 12:58:52 2008 UTC ()
Add RCSID.


(joerg)
diff -r1.1.2.1 -r1.1.2.2 pkgsrc/pkgtools/pkg_install/files/lib/remove.c

cvs diff -r1.1.2.1 -r1.1.2.2 pkgsrc/pkgtools/pkg_install/files/lib/remove.c (switch to unified diff)

--- pkgsrc/pkgtools/pkg_install/files/lib/remove.c 2008/08/05 22:56:24 1.1.2.1
+++ pkgsrc/pkgtools/pkg_install/files/lib/remove.c 2008/08/06 12:58:52 1.1.2.2
@@ -1,184 +1,196 @@ @@ -1,184 +1,196 @@
1/* $NetBSD: remove.c,v 1.1.2.1 2008/08/05 22:56:24 joerg Exp $ */ 1/* $NetBSD: remove.c,v 1.1.2.2 2008/08/06 12:58:52 joerg Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>. 4 * Copyright (c) 2008 Joerg Sonnenberger <joerg@NetBSD.org>.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 10 *
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in 14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the 15 * the documentation and/or other materials provided with the
16 * distribution. 16 * distribution.
17 * 17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
 32#if HAVE_CONFIG_H
 33#include "config.h"
 34#endif
 35
 36#include <nbcompat.h>
 37
 38#if HAVE_SYS_CDEFS_H
 39#include <sys/cdefs.h>
 40#endif
 41
 42__RCSID("$NetBSD: remove.c,v 1.1.2.2 2008/08/06 12:58:52 joerg Exp $");
 43
32#if HAVE_DIRENT_H 44#if HAVE_DIRENT_H
33#include <dirent.h> 45#include <dirent.h>
34#endif 46#endif
35#if HAVE_ERR_H 47#if HAVE_ERR_H
36#include <err.h> 48#include <err.h>
37#endif 49#endif
38#include <errno.h> 50#include <errno.h>
39#if HAVE_FCNTL_H 51#if HAVE_FCNTL_H
40#include <fcntl.h> 52#include <fcntl.h>
41#endif 53#endif
42#include <limits.h> 54#include <limits.h>
43#include <stdio.h> 55#include <stdio.h>
44#include <stdlib.h> 56#include <stdlib.h>
45#include <string.h> 57#include <string.h>
46#include <unistd.h> 58#include <unistd.h>
47 59
48#include "lib.h" 60#include "lib.h"
49 61
50static int 62static int
51safe_fchdir(int cwd) 63safe_fchdir(int cwd)
52{ 64{
53 int tmp_errno, rv; 65 int tmp_errno, rv;
54 66
55 tmp_errno = errno; 67 tmp_errno = errno;
56 rv = fchdir(cwd); 68 rv = fchdir(cwd);
57 errno = tmp_errno; 69 errno = tmp_errno;
58 70
59 return rv; 71 return rv;
60} 72}
61 73
62static int 74static int
63long_remove(const char **path_ptr, int missing_ok, int *did_chdir) 75long_remove(const char **path_ptr, int missing_ok, int *did_chdir)
64{ 76{
65 char tmp_path[PATH_MAX + 1]; 77 char tmp_path[PATH_MAX + 1];
66 const char *slash, *path; 78 const char *slash, *path;
67 size_t i, len; 79 size_t i, len;
68 int rv; 80 int rv;
69 81
70 path = *path_ptr; 82 path = *path_ptr;
71 len = strlen(path); 83 len = strlen(path);
72 *did_chdir = 0; 84 *did_chdir = 0;
73 85
74 while (len >= PATH_MAX) { 86 while (len >= PATH_MAX) {
75 slash = path; 87 slash = path;
76 for (i = PATH_MAX - 1; i > 0; --i) { 88 for (i = PATH_MAX - 1; i > 0; --i) {
77 if (path[i] == '/') 89 if (path[i] == '/')
78 break; 90 break;
79 } 91 }
80 if (i == 0) { 92 if (i == 0) {
81 errno = ENAMETOOLONG; 93 errno = ENAMETOOLONG;
82 return -1; /* Assumes PATH_MAX > NAME_MAX */ 94 return -1; /* Assumes PATH_MAX > NAME_MAX */
83 } 95 }
84 memcpy(tmp_path, path, i); 96 memcpy(tmp_path, path, i);
85 tmp_path[i] = '\0'; 97 tmp_path[i] = '\0';
86 if (chdir(tmp_path)) 98 if (chdir(tmp_path))
87 return -1; 99 return -1;
88 *did_chdir = 1; 100 *did_chdir = 1;
89 path += i + 1; 101 path += i + 1;
90 len -= i + 1; 102 len -= i + 1;
91 } 103 }
92 104
93 if (remove(path) == 0 || (errno == ENOENT && missing_ok)) 105 if (remove(path) == 0 || (errno == ENOENT && missing_ok))
94 rv = 0; 106 rv = 0;
95 else 107 else
96 rv = -1; 108 rv = -1;
97 109
98 *path_ptr = path; 110 *path_ptr = path;
99 111
100 return rv; 112 return rv;
101} 113}
102 114
103static int 115static int
104recursive_remove_internal(const char *path, int missing_ok, int cwd) 116recursive_remove_internal(const char *path, int missing_ok, int cwd)
105{ 117{
106 DIR *dir; 118 DIR *dir;
107 struct dirent *de; 119 struct dirent *de;
108 const char *sub_path; 120 const char *sub_path;
109 char *subdir; 121 char *subdir;
110 int did_chdir, rv; 122 int did_chdir, rv;
111 123
112 /* 124 /*
113 * If the argument is longer than PATH_MAX, long_remove 125 * If the argument is longer than PATH_MAX, long_remove
114 * will try to shorten it using chdir. So before returning, 126 * will try to shorten it using chdir. So before returning,
115 * make sure to fchdir back to the original cwd. 127 * make sure to fchdir back to the original cwd.
116 */ 128 */
117 sub_path = path; 129 sub_path = path;
118 if (long_remove(&sub_path, missing_ok, &did_chdir) == 0) 130 if (long_remove(&sub_path, missing_ok, &did_chdir) == 0)
119 rv = 0; 131 rv = 0;
120 else if (errno != ENOTEMPTY) /* Other errors are terminal. */ 132 else if (errno != ENOTEMPTY) /* Other errors are terminal. */
121 rv = -1; 133 rv = -1;
122 else 134 else
123 rv = 1; 135 rv = 1;
124 136
125 if (rv != 1) { 137 if (rv != 1) {
126 if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) 138 if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0)
127 rv = -1; 139 rv = -1;
128 return rv; 140 return rv;
129 } 141 }
130 142
131 if ((dir = opendir(sub_path)) == NULL) { 143 if ((dir = opendir(sub_path)) == NULL) {
132 if (errno == EMFILE) 144 if (errno == EMFILE)
133 warn("opendir failed"); 145 warn("opendir failed");
134 return -1; 146 return -1;
135 } 147 }
136 148
137 if (did_chdir && fchdir(cwd) == -1) 149 if (did_chdir && fchdir(cwd) == -1)
138 return -1; 150 return -1;
139 151
140 rv = 0; 152 rv = 0;
141 153
142 while ((de = readdir(dir)) != NULL) { 154 while ((de = readdir(dir)) != NULL) {
143 if (strcmp(de->d_name, ".") == 0) 155 if (strcmp(de->d_name, ".") == 0)
144 continue; 156 continue;
145 if (strcmp(de->d_name, "..") == 0) 157 if (strcmp(de->d_name, "..") == 0)
146 continue; 158 continue;
147 subdir = xasprintf("%s/%s", path, de->d_name); 159 subdir = xasprintf("%s/%s", path, de->d_name);
148 rv = recursive_remove_internal(subdir, 1, cwd); 160 rv = recursive_remove_internal(subdir, 1, cwd);
149 free(subdir); 161 free(subdir);
150 } 162 }
151 163
152 closedir(dir); 164 closedir(dir);
153 165
154 safe_fchdir(cwd); 166 safe_fchdir(cwd);
155 167
156 rv |= long_remove(&path, missing_ok, &did_chdir); 168 rv |= long_remove(&path, missing_ok, &did_chdir);
157 169
158 if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0) 170 if (did_chdir && safe_fchdir(cwd) == -1 && rv == 0)
159 rv = -1; 171 rv = -1;
160 172
161 return rv; 173 return rv;
162} 174}
163 175
164int 176int
165recursive_remove(const char *path, int missing_ok) 177recursive_remove(const char *path, int missing_ok)
166{ 178{
167 int orig_cwd, rv; 179 int orig_cwd, rv;
168 180
169 /* First try the easy case of regular file or empty directory. */ 181 /* First try the easy case of regular file or empty directory. */
170 if (remove(path) == 0 || (errno == ENOENT && missing_ok)) 182 if (remove(path) == 0 || (errno == ENOENT && missing_ok))
171 return 0; 183 return 0;
172 184
173 /* 185 /*
174 * If the path is too long, long_remove will use chdir to shorten it, 186 * If the path is too long, long_remove will use chdir to shorten it,
175 * so remember the current directory first. 187 * so remember the current directory first.
176 */ 188 */
177 if ((orig_cwd = open(".", O_RDONLY)) == -1) 189 if ((orig_cwd = open(".", O_RDONLY)) == -1)
178 return -1; 190 return -1;
179 191
180 rv = recursive_remove_internal(path, missing_ok, orig_cwd); 192 rv = recursive_remove_internal(path, missing_ok, orig_cwd);
181 193
182 close(orig_cwd); 194 close(orig_cwd);
183 return rv; 195 return rv;
184} 196}