X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=aft.c;h=b358c96cd9afd23bfa7f043c8add8bbf8b4bfade;hb=HEAD;hp=4fb60f91687e96a67e0169a1d3eeecf97f272bd1;hpb=82a64c65b1876da766fe7f7d418387868b111d09;p=paraslash.git diff --git a/aft.c b/aft.c index 4fb60f91..f1aca7fb 100644 --- a/aft.c +++ b/aft.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -913,7 +914,7 @@ static int print_list_item(struct ls_data *d, struct ls_options *opts, goto out; write_image_items(b, afsi); write_lyrics_items(b, afsi); - hash_to_asc(d->hash, asc_hash); + hash2_to_asc(d->hash, asc_hash); WRITE_STATUS_ITEM(b, SI_hash, "%s\n", asc_hash); WRITE_STATUS_ITEM(b, SI_bitrate, "%dkbit/s\n", afhi->bitrate); WRITE_STATUS_ITEM(b, SI_format, "%s\n", @@ -1067,8 +1068,8 @@ again: if (ret < 0) return ret; if (!d->hash) - d->hash = alloc(HASH_SIZE); - memcpy(d->hash, tmp_hash, HASH_SIZE); + d->hash = alloc(HASH2_SIZE); + memcpy(d->hash, tmp_hash, HASH2_SIZE); free(d->path); ret = get_audio_file_path_of_row(current_aft_row, &d->path); if (ret < 0) @@ -1102,7 +1103,7 @@ again: if (ret < 0) goto out; hash2_function(map.data, map.size, file_hash); - ret = hash_compare(file_hash, d->hash); + ret = hash2_compare(file_hash, d->hash); para_munmap(map.data, map.size); if (ret) { ret = -E_HASH_MISMATCH; @@ -1361,28 +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; } @@ -1390,20 +1430,14 @@ static int com_ls_callback(struct afs_callback_arg *aca) 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); @@ -1651,7 +1685,7 @@ static int com_add_callback(struct afs_callback_arg *aca) r_v = SERVER_CMD_OPT_RESULT(ADD, VERBOSE, aca->lpr); hash = (unsigned char *)buf + CAB_HASH_OFFSET; - hash_to_asc(hash, asc); + hash2_to_asc(hash, asc); objs[AFTCOL_HASH].data = buf + CAB_HASH_OFFSET; objs[AFTCOL_HASH].size = HASH2_SIZE; @@ -1722,7 +1756,7 @@ static int com_add_callback(struct afs_callback_arg *aca) ret = get_hash_of_row(pb, &old_hash); if (ret < 0) goto out; - hash_to_asc(old_hash, old_asc); + hash2_to_asc(old_hash, old_asc); if (lls_opt_given(r_v)) para_printf(&aca->pbout, "file change: %s -> %s\n", old_asc, asc); @@ -1906,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;