aboutsummaryrefslogtreecommitdiffstats
path: root/src/fcopy
diff options
context:
space:
mode:
Diffstat (limited to 'src/fcopy')
-rw-r--r--src/fcopy/main.c43
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
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);