From f3623744f5b28e0df91323cf5069f1932df7848d Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 24 Dec 2014 03:07:48 +0000 Subject: [PATCH] aft: Store resolved paths when adding files. Currently the add command performs some sanity checks on the given paths, but stores them unmodified in the audio file table if they pass the checks. This commit removes the checks in favor of a call to realpath(3) to get the canonicalized absolute pathname to be stored in the audio file table. The new code relies on POSIX.1-2008 semantics. That is, it calls realpath() with second argument NULL to let the function allocate a suitably sized buffer. This should not be a problem, since the old POSIX.1-2001 version is broken by design, and all moderately recent systems support the new semantics. This change breaks t0004 which expects the ls -p command to print the same paths that were used earlier to add audio files, which is no longer true. We fix the test by simply running ls without the -p option. --- aft.c | 87 ++++++++++++++--------------------------------- t/t0004-server.sh | 9 ++--- 2 files changed, 31 insertions(+), 65 deletions(-) diff --git a/aft.c b/aft.c index 59be56eb..fb0d4fd2 100644 --- a/aft.c +++ b/aft.c @@ -293,60 +293,36 @@ static struct osl_table_description audio_file_table_desc = { .column_descriptions = aft_cols }; -/* We don't want dot or dot-dot anywhere. */ -static int verify_dotfile(const char *rest) -{ - /* - * The first character was '.', but that has already been discarded, we - * now test the rest. - */ - switch (*rest) { - case '\0': case '/': /* /foo/. and /foo/./bar are not ok */ - return -1; - case '.': /* path start with /foo/.. */ - if (rest[1] == '\0' || rest[1] == '/') - return -1; /* /foo/.. or /foo/../bar are not ok */ - /* /foo/..bar is ok */ - } - return 1; -} - /* - * We fundamentally don't like some paths: We don't want double slashes or - * slashes at the end that can make pathnames ambiguous. + * Produce a canonicalized absolute pathname. + * + * Returns one if the resolved path a directory, zero if it is a regular file, + * negative on errors. */ static int verify_path(const char *orig_path, char **resolved_path) { - char c; - size_t len; - char *path; + int ret; + char *path = NULL; + struct stat statbuf; if (*orig_path != '/') /* we only accept absolute paths */ - return -E_BAD_PATH; - len = strlen(orig_path); - *resolved_path = para_strdup(orig_path); - path = *resolved_path; - while (len > 1 && path[--len] == '/') - path[len] = '\0'; /* remove slash at the end */ - c = *path++; - while (c) { - if (c == '/') { - c = *path++; - switch (c) { - case '/': /* double slash */ - goto bad_path; - case '.': - if (verify_dotfile(path) < 0) - goto bad_path; - default: - continue; - } - } - c = *path++; - } - return 1; -bad_path: - free(*resolved_path); + goto fail; + path = realpath(orig_path, NULL); + if (!path) + goto fail; + if (stat(path, &statbuf) < 0) + goto fail; + if (S_ISREG(statbuf.st_mode)) + ret = 0; + else if (S_ISDIR(statbuf.st_mode)) + ret = 1; + else + goto fail; + *resolved_path = path; + return ret; +fail: + *resolved_path = NULL; + free(path); return -E_BAD_PATH; } @@ -1981,7 +1957,6 @@ int com_add(struct command_context *cc) { int i, ret; struct private_add_data pad = {.cc = cc, .flags = 0}; - struct stat statbuf; for (i = 1; i < cc->argc; i++) { const char *arg = cc->argv[i]; @@ -2020,20 +1995,10 @@ int com_add(struct command_context *cc) return ret; continue; } - ret = stat(path, &statbuf); - if (ret < 0) { - ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, - "failed to stat %s (%s)\n", path, - strerror(errno)); - free(path); - if (ret < 0) - return ret; - continue; - } - if (S_ISDIR(statbuf.st_mode)) + if (ret == 1) /* directory */ ret = for_each_file_in_dir(path, add_one_audio_file, &pad); - else + else /* regular file */ ret = add_one_audio_file(path, &pad); if (ret < 0) { send_sb_va(&cc->scc, SBD_OUTPUT, "%s: %s\n", path, diff --git a/t/t0004-server.sh b/t/t0004-server.sh index 04d6cd60..a14a04e9 100755 --- a/t/t0004-server.sh +++ b/t/t0004-server.sh @@ -21,7 +21,8 @@ pubkey=$privkey.pub serverlog=server.log get_audio_file_paths ogg -oggs="$result" +declare -a oggs=($result) +declare -a oggs_base=(${oggs[@]##*/}) declare -a commands=() cmdline=() required_objects=() good=() bad=() i=0 @@ -38,14 +39,14 @@ bad[$i]='!^successfully' let i++ commands[$i]="add_ogg" required_objects[$i]='ogg_afh' -cmdline[$i]="add $oggs" +cmdline[$i]="add ${oggs[@]}" bad[$i]='.' let i++ commands[$i]="ls_ogg" required_objects[$i]='ogg_afh' -cmdline[$i]="ls -lv -p $oggs" -good[$i]='^path:' +cmdline[$i]="ls -lv ${oggs_base[@]}" +good[$i]='^basename:' let i++ commands[$i]="term" -- 2.39.2