From: Andre Noll Date: Sat, 28 Oct 2023 17:20:14 +0000 (+0200) Subject: Merge topic branch t/ls-L into master X-Git-Tag: v0.7.3~10 X-Git-Url: http://git.tuebingen.mpg.de/?a=commitdiff_plain;h=624910afb851cf78669be188214b0332d5d5ee12;hp=-c;p=paraslash.git Merge topic branch t/ls-L into master A single patch which implements the new --limit option for the ls server command. The confict in aft.c was trivial to fix. * refs/heads/t/ls-L: server: Implement ls --limit. --- 624910afb851cf78669be188214b0332d5d5ee12 diff --combined NEWS.md index aa515e5a,598db71f..5430790b --- a/NEWS.md +++ b/NEWS.md @@@ -1,27 -1,6 +1,29 @@@ NEWS ==== +---------------------------------------------- +0.7.3 (to be announced) "weighted correctness" +---------------------------------------------- + +- Old style PEM keys are now deprecated. They still work but their + use results in a run-time warning. The removal of PEM key support is + scheduled for paraslash-0.8.0. +- Version 1.0 of the openssl library has been deprecated. A warning + is printed at compile-time on systems which have this outdated version + because it will no longer be supported once paraslash-0.8.0 comes out. +- A spring cleanup for the senescent code in fd.c. +- The --admissible option of the ls command now takes an optional + argument. When invoked like --admissible=m/foo, only files which are + admissible with respect to mood foo are listed. +- The select server command is now quiet by default, The new --verbose + option can be used to show information about the newly loaded mood + or playlist. ++- The ls server command gained the --limit option to force a limit ++ on the number of files listed. + +Downloads: +[tarball](./releases/paraslash-git.tar.xz) + ------------------------------------- 0.7.2 (2023-03-08) "optical friction" ------------------------------------- diff --combined aft.c index 4ea8641b,ff75361d..f1aca7fb --- a/aft.c +++ b/aft.c @@@ -6,7 -6,6 +6,7 @@@ #include #include #include +#include #include #include @@@ -1362,65 -1361,30 +1362,67 @@@ err return ret; } +static int mop_loop(const char *arg, struct afs_callback_arg *aca, + struct ls_options *opts) +{ + int ret; + char *msg; + + if (!arg || strcmp(arg, ".") == 0) + return score_loop(prepare_ls_row, NULL, opts); + if (!strncmp(arg, "m/", 2)) { + struct mood_instance *m; + ret = mood_load(arg + 2, &m, &msg); + if (ret < 0) + afs_error(aca, "%s", msg); + free(msg); + if (ret < 0) + return ret; + ret = mood_loop(m, prepare_ls_row, opts); + mood_unload(m); + return ret; + } + if (!strncmp(arg, "p/", 2)) { + struct playlist_instance *pi; + ret = playlist_load(arg + 2, &pi, &msg); + if (ret < 0) + afs_error(aca, "%s", msg); + free(msg); + if (ret < 0) + return ret; + ret = playlist_loop(pi, prepare_ls_row, opts); + playlist_unload(pi); + return ret; + } + afs_error(aca, "bad mood/playlist specifier: %s\n", arg); + return -ERRNO_TO_PARA_ERROR(EINVAL); +} + static int com_ls_callback(struct afs_callback_arg *aca) { const struct lls_command *cmd = SERVER_CMD_CMD_PTR(LS); struct ls_options *opts = aca->query.data; - int i = 0, ret; + int ret; time_t current_time; - const struct lls_opt_result *r_r; + const struct lls_opt_result *r_r, *r_a; + uint32_t limit, k, n; ret = lls_deserialize_parse_result( (char *)aca->query.data + sizeof(*opts), cmd, &opts->lpr); assert(ret >= 0); r_r = SERVER_CMD_OPT_RESULT(LS, REVERSE, opts->lpr); - + r_a = SERVER_CMD_OPT_RESULT(LS, ADMISSIBLE, opts->lpr); aca->pbout.flags = (opts->mode == LS_MODE_PARSER)? PBF_SIZE_PREFIX : 0; - if (admissible_only(opts)) - ret = score_loop(prepare_ls_row, opts); - else + if (admissible_only(opts)) { + const char *arg = lls_string_val(0, r_a); + ret = mop_loop(arg, aca, opts); + } else ret = osl(osl_rbtree_loop(audio_file_table, AFTCOL_PATH, opts, prepare_ls_row)); if (ret < 0) goto out; - if (opts->num_matching_paths == 0) { + n = opts->num_matching_paths; + if (n == 0) { ret = lls_num_inputs(opts->lpr) > 0? -E_NO_MATCH : 0; goto out; } @@@ -1428,20 -1392,14 +1430,14 @@@ if (ret < 0) goto out; time(¤t_time); - if (lls_opt_given(r_r)) - for (i = opts->num_matching_paths - 1; i >= 0; i--) { - ret = print_list_item(opts->data_ptr[i], opts, - &aca->pbout, current_time); - if (ret < 0) - goto out; - } - else - for (i = 0; i < opts->num_matching_paths; i++) { - ret = print_list_item(opts->data_ptr[i], opts, - &aca->pbout, current_time); - if (ret < 0) - goto out; - } + limit = SERVER_CMD_UINT32_VAL(LS, LIMIT, opts->lpr); + for (k = 0; k < n && (limit == 0 || k < limit); k++) { + uint32_t idx = lls_opt_given(r_r)? n - 1 - k : k; + ret = print_list_item(opts->data_ptr[idx], opts, &aca->pbout, + current_time); + if (ret < 0) + goto out; + } out: lls_free_parse_result(opts->lpr, cmd); free(opts->data); @@@ -1944,53 -1902,6 +1940,53 @@@ out_free return send_ret; } +/* + * Call back once for each regular file below a directory. + * + * Traverse the given directory recursively and call the supplied callback for + * each regular file encountered. The first argument to the callback will be + * the path to the regular file and the second argument will be the data + * pointer. All file types except regular files and directories are ignored. In + * particular, symlinks are not followed. Subdirectories are ignored silently + * if the calling process has insufficient access permissions. + */ +static int for_each_file_in_dir(const char *dirname, + int (*func)(const char *, void *), void *data) +{ + int ret; + DIR *dir; + struct dirent *entry; + + dir = opendir(dirname); + if (!dir) + return errno == EACCES? 1 : -ERRNO_TO_PARA_ERROR(errno); + /* scan cwd recursively */ + while ((entry = readdir(dir))) { + char *tmp; + struct stat s; + + if (!strcmp(entry->d_name, ".")) + continue; + if (!strcmp(entry->d_name, "..")) + continue; + tmp = make_message("%s/%s", dirname, entry->d_name); + ret = 0; + if (lstat(tmp, &s) != -1) { + if (S_ISREG(s.st_mode)) + ret = func(tmp, data); + else if (S_ISDIR(s.st_mode)) + ret = for_each_file_in_dir(tmp, func, data); + } + free(tmp); + if (ret < 0) + goto out; + } + ret = 1; +out: + closedir(dir); + return ret; +} + static int com_add(struct command_context *cc, struct lls_parse_result *lpr) { int i, ret; diff --combined m4/lls/server_cmd.suite.m4 index 5b5c59ad,cafdbccf..02afaabb --- a/m4/lls/server_cmd.suite.m4 +++ b/m4/lls/server_cmd.suite.m4 @@@ -222,6 -222,16 +222,16 @@@ m4_include(`com_ll.m4' also given), chunk time and chunk offsets. [/help] + [option limit] + short_opt = L + summary = list at most this many files + arg_type = uint32 + arg_info = required_arg + typestr = num + [help] + An argument of zero means "unlimited". This is also the default which + applies if the option is not given. + [/help] [option basename] short_opt = b summary = list and match basenames only @@@ -233,19 -243,9 +243,19 @@@ [option admissible] short_opt = a summary = list only admissible files + arg_type = string + arg_info = optional_arg + typestr = specifier/name + default_val = . [help] - List only files which are admissible with respect to the current mood - or playlist. + If the optional argument is supplied, it must be of the form "p/foo" + or "m/bar" (which refer to the playlist named "foo" and the mood named + "bar", respectively). The command then restricts its output to the set + of files which are admissible with respect to the thusly identified + mood or playlist. + + If no argument is given, or if the argument is the special value ".", + the current mood or playlist is assumed. [/help] [option reverse] short_opt = r @@@ -417,9 -417,6 +427,9 @@@ activates the mood named 'foo'. [/description] + [option verbose] + short_opt = v + summary = print information about the loaded mood or playlist [subcommand sender] purpose = control paraslash senders