diff options
Diffstat (limited to 'src/fcopy/main.c')
-rw-r--r-- | src/fcopy/main.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 01633be59..a41df52a1 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 | ||
175 | static 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 | |||
212 | done: | ||
213 | free(proc_pid); | ||
214 | return use_target; | ||
215 | } | ||
175 | 216 | ||
176 | void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { | 217 | void 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); |