Skip to content
This repository was archived by the owner on Feb 8, 2021. It is now read-only.

Commit b4dae32

Browse files
committed
hyper_mkdir_follow_link drop depth
When walking .., go back one level of path unless it is root. Signed-off-by: Peng Tao <bergwolf@gmail.com>
1 parent 2175595 commit b4dae32

File tree

1 file changed

+26
-19
lines changed

1 file changed

+26
-19
lines changed

src/util.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -329,16 +329,20 @@ static char *hyper_resolve_link(char *path)
329329
* @path: target directory. It is always relative to @root even if it starts with /.
330330
* @mode: directory mode.
331331
* @link_max: max number of symlinks to follow.
332-
* @depth: number of components resolved.
333332
*
334333
* Upon success, @parent is changed to point to resolved path name.
335334
*/
336335
static int hyper_mkdir_follow_link(char *root, char *parent, char *path,
337-
mode_t mode, int *link_max, int *depth)
336+
mode_t mode, int *link_max)
338337
{
339338
char *comp, *prev, *link, *dummy, *npath, *delim = "/";
340339
struct stat st;
341340

341+
if (strncmp(root, parent, strlen(root)) != 0) {
342+
errno = EINVAL;
343+
return -1;
344+
}
345+
342346
npath = strdup(path);
343347
if (npath == NULL)
344348
goto out;
@@ -351,24 +355,30 @@ static int hyper_mkdir_follow_link(char *root, char *parent, char *path,
351355
if (!strcmp(comp, "."))
352356
continue;
353357

358+
if (!strcmp(comp, "..")) {
359+
/* *NOTE* this works iff:
360+
* 1. parent is initialized as root when entering for the first time.
361+
* 2. comp is never appended to parent with trailing '/'.
362+
* 3. comp is always appended to parent with *one* prefix '/'.
363+
*/
364+
char *p = strrchr(parent, '/');
365+
if (p == NULL) {
366+
/* no comp appended, do nothing */
367+
} else if (p - parent >= strlen(root)) {
368+
/* go back one level */
369+
*p = '\0';
370+
}
371+
/* no need to check parent directory */
372+
continue;
373+
}
374+
354375
if (strlen(parent) + strlen(comp) + 1 >= 512) {
355376
errno = ENAMETOOLONG;
356377
goto out;
357378
}
358379
prev = &parent[strlen(parent)];
359380
strcat(parent, "/");
360381
strcat(parent, comp);
361-
if (!strcmp(comp, "..")) {
362-
if (--(*depth) <= 0) {
363-
/* points to root */
364-
sprintf(parent, "%s", root);
365-
*depth = 0;
366-
}
367-
/* no need to check parent directory */
368-
continue;
369-
} else {
370-
(*depth)++;
371-
}
372382

373383
if (lstat(parent, &st) >= 0) {
374384
if (S_ISDIR(st.st_mode)) {
@@ -383,12 +393,10 @@ static int hyper_mkdir_follow_link(char *root, char *parent, char *path,
383393
goto out;
384394
if (link[0] == '/') {
385395
sprintf(parent, "%s", root);
386-
*depth = 0;
387396
} else {
388397
*prev = '\0'; /* drop current comp */
389-
(*depth)--;
390398
}
391-
if (hyper_mkdir_follow_link(root, parent, link, mode, link_max, depth) < 0) {
399+
if (hyper_mkdir_follow_link(root, parent, link, mode, link_max) < 0) {
392400
free(link);
393401
goto out;
394402
}
@@ -411,7 +419,6 @@ static int hyper_mkdir_follow_link(char *root, char *parent, char *path,
411419
errno = 0;
412420
out:
413421
free(npath);
414-
printf("parent is %s errno %d\n", parent, errno);
415422
return errno ? -1 : 0;
416423
}
417424

@@ -426,10 +433,10 @@ static int hyper_mkdir_follow_link(char *root, char *parent, char *path,
426433
char *hyper_mkdir_at(char *root, char *path, mode_t mode)
427434
{
428435
char result[512];
429-
int depth = 0, max_link = 40;
436+
int max_link = 40;
430437

431438
sprintf(result, "%s", root);
432-
if (hyper_mkdir_follow_link(root, result, path, mode, &max_link, &depth) < 0)
439+
if (hyper_mkdir_follow_link(root, result, path, mode, &max_link) < 0)
433440
return NULL;
434441

435442
return strdup(result);

0 commit comments

Comments
 (0)