aboutsummaryrefslogtreecommitdiffstats
path: root/src/fcopy/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fcopy/main.c')
-rw-r--r--src/fcopy/main.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index 01633be59..d863b537b 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -172,6 +172,47 @@ static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
172 } 172 }
173} 173}
174 174
175static char *proc_pid_to_self(const char *target)
176{
177 char *use_target = 0;
178 char *proc_pid = 0;
179
180 if (!(use_target = canonicalize_file_name(target)))
181 goto done;
182
183 // target is under /proc/<PID>?
184 static const char proc[] = "/proc/";
185 if (strncmp(use_target, proc, sizeof proc - 1))
186 goto done;
187
188 int digit = use_target[sizeof proc - 1];
189 if (digit < '1' || digit > '9')
190 goto done;
191
192 // check where /proc/self points to
193 static const char proc_self[] = "/proc/self";
194 if (!(proc_pid = canonicalize_file_name(proc_self)))
195 goto done;
196
197 // redirect /proc/PID/xxx -> /proc/self/XXX
198 size_t pfix = strlen(proc_pid);
199 if (strncmp(use_target, proc_pid, pfix))
200 goto done;
201
202 if (use_target[pfix] != 0 && use_target[pfix] != '/')
203 goto done;
204
205 char *tmp;
206 if (asprintf(&tmp, "%s%s", proc_self, use_target + pfix) != -1) {
207 if (arg_debug)
208 fprintf(stderr, "SYMLINK %s\n --> %s\n", use_target, tmp);
209 free(use_target), use_target = tmp;
210 }
211
212done:
213 free(proc_pid);
214 return use_target;
215}
175 216
176void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { 217void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) {
177 (void) mode; 218 (void) mode;
@@ -183,7 +224,7 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid,
183 if (lstat(linkpath, &s) == 0) 224 if (lstat(linkpath, &s) == 0)
184 return; 225 return;
185 226
186 char *rp = realpath(target, NULL); 227 char *rp = proc_pid_to_self(target);
187 if (rp) { 228 if (rp) {
188 if (symlink(rp, linkpath) == -1) { 229 if (symlink(rp, linkpath) == -1) {
189 free(rp); 230 free(rp);
@@ -227,16 +268,14 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
227 first = 0; 268 first = 0;
228 else if (!arg_quiet) 269 else if (!arg_quiet)
229 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname); 270 fprintf(stderr, "Warning fcopy: skipping %s, file already present\n", infname);
230 free(outfname); 271 goto out;
231 return 0;
232 } 272 }
233 273
234 // extract mode and ownership 274 // extract mode and ownership
235 if (stat(infname, &s) != 0) { 275 if (stat(infname, &s) != 0) {
236 if (!arg_quiet) 276 if (!arg_quiet)
237 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname); 277 fprintf(stderr, "Warning fcopy: skipping %s, cannot find inode\n", infname);
238 free(outfname); 278 goto out;
239 return 0;
240 } 279 }
241 uid_t uid = s.st_uid; 280 uid_t uid = s.st_uid;
242 gid_t gid = s.st_gid; 281 gid_t gid = s.st_gid;
@@ -246,8 +285,7 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
246 if ((s.st_size + size_cnt) > copy_limit) { 285 if ((s.st_size + size_cnt) > copy_limit) {
247 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024); 286 fprintf(stderr, "Error fcopy: size limit of %lu MB reached\n", (copy_limit / 1024) / 1024);
248 size_limit_reached = 1; 287 size_limit_reached = 1;
249 free(outfname); 288 goto out;
250 return 0;
251 } 289 }
252 290
253 file_cnt++; 291 file_cnt++;
@@ -262,7 +300,8 @@ static int fs_copydir(const char *infname, const struct stat *st, int ftype, str
262 else if (ftype == FTW_SL) { 300 else if (ftype == FTW_SL) {
263 copy_link(infname, outfname, mode, uid, gid); 301 copy_link(infname, outfname, mode, uid, gid);
264 } 302 }
265 303out:
304 free(outfname);
266 return(0); 305 return(0);
267} 306}
268 307
@@ -295,6 +334,7 @@ static char *check(const char *src) {
295 return rsrc; // normal exit from the function 334 return rsrc; // normal exit from the function
296 335
297errexit: 336errexit:
337 free(rsrc);
298 fprintf(stderr, "Error fcopy: invalid file %s\n", src); 338 fprintf(stderr, "Error fcopy: invalid file %s\n", src);
299 exit(1); 339 exit(1);
300} 340}