]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - aft.c
server: Convert com_rm() to lopsub.
[paraslash.git] / aft.c
diff --git a/aft.c b/aft.c
index 628f98fbeebef702d0cbccb104e2eac28053994d..7141e3fa91f5fa8a1afeb0bd9fb460401d54f9ef 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -2133,24 +2133,14 @@ int com_touch(struct command_context *cc)
                cc->argv + i, com_touch_callback, afs_cb_result_handler, cc);
 }
 
-/** Flags for com_rm(). */
-enum rm_flags {
-       /** -v */
-       RM_FLAG_VERBOSE = 1,
-       /** -f */
-       RM_FLAG_FORCE = 2,
-       /** -p */
-       RM_FLAG_FNM_PATHNAME = 4
-};
-
 static int remove_audio_file(__a_unused struct osl_table *table,
                struct osl_row *row, const char *name, void *data)
 {
        struct afs_callback_arg *aca = data;
-       uint32_t flags =*(uint32_t *)aca->query.data;
+       bool v_given = SERVER_CMD_OPT_GIVEN(RM, VERBOSE, aca->lpr);
        int ret;
 
-       if (flags & RM_FLAG_VERBOSE)
+       if (v_given)
                para_printf(&aca->pbout, "removing %s\n", name);
        ret = afs_event(AUDIO_FILE_REMOVE, &aca->pbout, row);
        if (ret < 0)
@@ -2163,95 +2153,63 @@ static int remove_audio_file(__a_unused struct osl_table *table,
 
 static int com_rm_callback(struct afs_callback_arg *aca)
 {
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(RM);
        int ret;
-       uint32_t flags = *(uint32_t *)aca->query.data;
        struct pattern_match_data pmd = {
                .table = audio_file_table,
                .loop_col_num = AFTCOL_HASH,
                .match_col_num = AFTCOL_PATH,
-               .patterns = {.data = (char *)aca->query.data + sizeof(uint32_t),
-                       .size = aca->query.size - sizeof(uint32_t)},
                .data = aca,
                .action = remove_audio_file
        };
-       if (flags & RM_FLAG_FNM_PATHNAME)
+       bool v_given, p_given, f_given;
+
+       ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr);
+       assert(ret >= 0);
+       pmd.lpr = aca->lpr;
+       v_given = SERVER_CMD_OPT_GIVEN(RM, VERBOSE, aca->lpr);
+       p_given = SERVER_CMD_OPT_GIVEN(RM, PATHNAME_MATCH, aca->lpr);
+       f_given = SERVER_CMD_OPT_GIVEN(RM, FORCE, aca->lpr);
+
+       if (p_given)
                pmd.fnmatch_flags |= FNM_PATHNAME;
        ret = for_each_matching_row(&pmd);
        if (ret < 0)
                goto out;
        if (pmd.num_matches == 0) {
-               if (!(flags & RM_FLAG_FORCE))
+               if (!f_given)
                        ret = -E_NO_MATCH;
-       } else if (flags & RM_FLAG_VERBOSE)
+       } else if (v_given)
                para_printf(&aca->pbout, "removed %u file(s)\n",
                        pmd.num_matches);
 out:
+       lls_free_parse_result(aca->lpr, cmd);
        return ret;
 }
 
 /* TODO options: -r (recursive) */
-int com_rm(struct command_context *cc)
+static int com_rm(struct command_context *cc, struct lls_parse_result *lpr)
 {
-       uint32_t flags = 0;
-       struct osl_object query = {.data = &flags, .size = sizeof(flags)};
-       int i;
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(RM);
+       char *errctx;
+       int ret;
 
-       for (i = 1; i < cc->argc; i++) {
-               const char *arg = cc->argv[i];
-               if (arg[0] != '-')
-                       break;
-               if (!strcmp(arg, "--")) {
-                       i++;
-                       break;
-               }
-               if (!strcmp(arg, "-f")) {
-                       flags |= RM_FLAG_FORCE;
-                       continue;
-               }
-               if (!strcmp(arg, "-p")) {
-                       flags |= RM_FLAG_FNM_PATHNAME;
-                       continue;
-               }
-               if (!strcmp(arg, "-v")) {
-                       flags |= RM_FLAG_VERBOSE;
-                       continue;
-               }
-               break;
+       ret = lls(lls_check_arg_count(lpr, 1, INT_MAX, &errctx));
+       if (ret < 0) {
+               send_errctx(cc, errctx);
+               return ret;
        }
-       if (i >= cc->argc)
-               return -E_AFT_SYNTAX;
-       return send_option_arg_callback_request(&query, cc->argc - i,
-               cc->argv + i, com_rm_callback, afs_cb_result_handler, cc);
+       return send_lls_callback_request(com_rm_callback, cmd, lpr, cc);
 }
-
-/**
- * Flags used by the cpsi command.
- *
- * \sa com_cpsi().
- */
-enum cpsi_flags {
-       /** Whether the lyrics id should be copied. */
-       CPSI_FLAG_COPY_LYRICS_ID = 1,
-       /** Whether the image id should be copied. */
-       CPSI_FLAG_COPY_IMAGE_ID = 2,
-       /** Whether the lastplayed time should be copied. */
-       CPSI_FLAG_COPY_LASTPLAYED = 4,
-       /** Whether the numplayed count should be copied. */
-       CPSI_FLAG_COPY_NUMPLAYED = 8,
-       /** Whether the attributes should be copied. */
-       CPSI_FLAG_COPY_ATTRIBUTES = 16,
-       /** Activates verbose mode. */
-       CPSI_FLAG_VERBOSE = 32,
-};
+EXPORT_SERVER_CMD_HANDLER(rm);
 
 /** Data passed to the action handler of com_cpsi(). */
 struct cpsi_action_data {
-       /** command line flags (see \ref cpsi_flags). */
-       unsigned flags;
        /** Values are copied from here. */
        struct afs_info source_afsi;
        /** What was passed to com_cpsi_callback(). */
        struct afs_callback_arg *aca;
+       bool copy_all;
 };
 
 static int copy_selector_info(__a_unused struct osl_table *table,
@@ -2262,24 +2220,32 @@ static int copy_selector_info(__a_unused struct osl_table *table,
        int ret;
        struct afs_info old_afsi, target_afsi;
        struct afsi_change_event_data aced;
+       bool a_given, y_given, i_given, l_given, n_given, v_given;
+
+       a_given = SERVER_CMD_OPT_GIVEN(CPSI, ATTRIBUTE_BITMAP, cad->aca->lpr);
+       y_given = SERVER_CMD_OPT_GIVEN(CPSI, LYRICS_ID, cad->aca->lpr);
+       i_given = SERVER_CMD_OPT_GIVEN(CPSI, IMAGE_ID, cad->aca->lpr);
+       l_given = SERVER_CMD_OPT_GIVEN(CPSI, LASTPLAYED, cad->aca->lpr);
+       n_given = SERVER_CMD_OPT_GIVEN(CPSI, NUMPLAYED, cad->aca->lpr);
+       v_given = SERVER_CMD_OPT_GIVEN(CPSI, VERBOSE, cad->aca->lpr);
 
        ret = get_afsi_object_of_row(row, &target_afsi_obj);
        if (ret < 0)
                return ret;
        load_afsi(&target_afsi, &target_afsi_obj);
        old_afsi = target_afsi;
-       if (cad->flags & CPSI_FLAG_COPY_LYRICS_ID)
+       if (cad->copy_all || y_given)
                target_afsi.lyrics_id = cad->source_afsi.lyrics_id;
-       if (cad->flags & CPSI_FLAG_COPY_IMAGE_ID)
+       if (cad->copy_all || i_given)
                target_afsi.image_id = cad->source_afsi.image_id;
-       if (cad->flags & CPSI_FLAG_COPY_LASTPLAYED)
+       if (cad->copy_all || l_given)
                target_afsi.last_played = cad->source_afsi.last_played;
-       if (cad->flags & CPSI_FLAG_COPY_NUMPLAYED)
+       if (cad->copy_all || n_given)
                target_afsi.num_played = cad->source_afsi.num_played;
-       if (cad->flags & CPSI_FLAG_COPY_ATTRIBUTES)
+       if (cad->copy_all || a_given)
                target_afsi.attributes = cad->source_afsi.attributes;
        save_afsi(&target_afsi, &target_afsi_obj); /* in-place update */
-       if (cad->flags & CPSI_FLAG_VERBOSE)
+       if (v_given)
                para_printf(&cad->aca->pbout, "copied afsi to %s\n", name);
        aced.aft_row = row;
        aced.old_afsi = &old_afsi;
@@ -2288,86 +2254,60 @@ static int copy_selector_info(__a_unused struct osl_table *table,
 
 static int com_cpsi_callback(struct afs_callback_arg *aca)
 {
-       struct cpsi_action_data cad = {
-               .flags = *(unsigned *)aca->query.data,
-               .aca = aca
-       };
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(CPSI);
+       bool a_given, y_given, i_given, l_given, n_given, v_given;
+       struct cpsi_action_data cad = {.aca = aca};
        int ret;
-       char *source_path = (char *)aca->query.data + sizeof(cad.flags);
        struct pattern_match_data pmd = {
                .table = audio_file_table,
                .loop_col_num = AFTCOL_HASH,
                .match_col_num = AFTCOL_PATH,
-               .patterns = {.data = source_path + strlen(source_path) + 1,
-                       .size = aca->query.size - sizeof(cad.flags)
-                               - strlen(source_path) - 1},
+               .input_skip = 1, /* skip first argument (source file) */
                .data = &cad,
                .action = copy_selector_info
        };
 
-       ret = get_afsi_of_path(source_path, &cad.source_afsi);
+       ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr);
+       assert(ret >= 0);
+       pmd.lpr = aca->lpr;
+
+       a_given = SERVER_CMD_OPT_GIVEN(CPSI, ATTRIBUTE_BITMAP, aca->lpr);
+       y_given = SERVER_CMD_OPT_GIVEN(CPSI, LYRICS_ID, aca->lpr);
+       i_given = SERVER_CMD_OPT_GIVEN(CPSI, IMAGE_ID, aca->lpr);
+       l_given = SERVER_CMD_OPT_GIVEN(CPSI, LASTPLAYED, aca->lpr);
+       n_given = SERVER_CMD_OPT_GIVEN(CPSI, NUMPLAYED, aca->lpr);
+       v_given = SERVER_CMD_OPT_GIVEN(CPSI, VERBOSE, aca->lpr);
+       cad.copy_all = !a_given && !y_given && !i_given && !l_given && !n_given;
+
+       ret = get_afsi_of_path(lls_input(0, aca->lpr), &cad.source_afsi);
        if (ret < 0)
                goto out;
        ret = for_each_matching_row(&pmd);
        if (ret < 0)
                goto out;
        if (pmd.num_matches > 0) {
-               if (cad.flags & CPSI_FLAG_VERBOSE)
+               if (v_given)
                        para_printf(&aca->pbout, "updated afsi of %u file(s)\n",
                                pmd.num_matches);
        } else
                ret = -E_NO_MATCH;
 out:
+       lls_free_parse_result(aca->lpr, cmd);
        return ret;
 }
 
-int com_cpsi(struct command_context *cc)
+static int com_cpsi(struct command_context *cc, struct lls_parse_result *lpr)
 {
-       unsigned flags = 0;
-       int i;
-       struct osl_object options = {.data = &flags, .size = sizeof(flags)};
-
-       for (i = 1; i < cc->argc; i++) {
-               const char *arg = cc->argv[i];
-               if (arg[0] != '-')
-                       break;
-               if (!strcmp(arg, "--")) {
-                       i++;
-                       break;
-               }
-               if (!strcmp(arg, "-y")) {
-                       flags |= CPSI_FLAG_COPY_LYRICS_ID;
-                       continue;
-               }
-               if (!strcmp(arg, "-i")) {
-                       flags |= CPSI_FLAG_COPY_IMAGE_ID;
-                       continue;
-               }
-               if (!strcmp(arg, "-l")) {
-                       flags |= CPSI_FLAG_COPY_LASTPLAYED;
-                       continue;
-               }
-               if (!strcmp(arg, "-n")) {
-                       flags |= CPSI_FLAG_COPY_NUMPLAYED;
-                       continue;
-               }
-               if (!strcmp(arg, "-a")) {
-                       flags |= CPSI_FLAG_COPY_ATTRIBUTES;
-                       continue;
-               }
-               if (!strcmp(arg, "-v")) {
-                       flags |= CPSI_FLAG_VERBOSE;
-                       continue;
-               }
-               break;
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(CPSI);
+       char *errctx;
+       int ret = lls(lls_check_arg_count(lpr, 2, INT_MAX, &errctx));
+       if (ret < 0) {
+               send_errctx(cc, errctx);
+               return ret;
        }
-       if (i + 1 >= cc->argc) /* need at least source file and pattern */
-               return -E_AFT_SYNTAX;
-       if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
-               flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
-       return send_option_arg_callback_request(&options, cc->argc - i,
-               cc->argv + i, com_cpsi_callback, afs_cb_result_handler, cc);
+       return send_lls_callback_request(com_cpsi_callback, cmd, lpr, cc);
 }
+EXPORT_SERVER_CMD_HANDLER(cpsi);
 
 struct change_atts_data {
        uint64_t add_mask, del_mask;
@@ -2401,9 +2341,8 @@ static int change_atts(__a_unused struct osl_table *table,
 
 static int com_setatt_callback(struct afs_callback_arg *aca)
 {
-       char *p;
-       int ret;
-       size_t len;
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SETATT);
+       int i, ret;
        struct change_atts_data cad = {.aca = aca};
        struct pattern_match_data pmd = {
                .table = audio_file_table,
@@ -2413,27 +2352,36 @@ static int com_setatt_callback(struct afs_callback_arg *aca)
                .data = &cad,
                .action = change_atts
        };
+       unsigned num_inputs;
+
+       ret = lls_deserialize_parse_result(aca->query.data, cmd, &aca->lpr);
+       assert(ret >= 0);
+       pmd.lpr = aca->lpr;
 
-       for (
-               p = aca->query.data;
-               p < (char *)aca->query.data + aca->query.size;
-               p += len + 1
-       ) {
-               char c;
+       num_inputs = lls_num_inputs(aca->lpr);
+       for (i = 0; i < num_inputs; i++) {
                unsigned char bitnum;
                uint64_t one = 1;
+               const char *arg = lls_input(i, aca->lpr);
+               char c, *p;
+               size_t len = strlen(arg);
 
-               len = strlen(p);
                ret = -E_ATTR_SYNTAX;
                if (len == 0)
                        goto out;
-               c = p[len - 1];
-               if (c != '+' && c != '-')
-                       break;
+               c = arg[len - 1];
+               if (c != '+' && c != '-') {
+                       if (cad.add_mask == 0 && cad.del_mask == 0)
+                               goto out; /* no attribute modifier given */
+                       goto set_atts;
+               }
+               p = para_malloc(len);
+               memcpy(p, arg, len - 1);
                p[len - 1] = '\0';
                ret = get_attribute_bitnum_by_name(p, &bitnum);
+               free(p);
                if (ret < 0) {
-                       para_printf(&aca->pbout, "attribute not found: %s\n", p);
+                       para_printf(&aca->pbout, "invalid argument: %s\n", arg);
                        goto out;
                }
                if (c == '+')
@@ -2441,29 +2389,32 @@ static int com_setatt_callback(struct afs_callback_arg *aca)
                else
                        cad.del_mask |= (one << bitnum);
        }
+       /* no pattern given */
        ret = -E_ATTR_SYNTAX;
-       if (!cad.add_mask && !cad.del_mask)
-               goto out;
-       pmd.patterns.data = p;
-       if (p >= (char *)aca->query.data + aca->query.size)
-               goto out;
-       pmd.patterns.size = (char *)aca->query.data + aca->query.size - p;
+       goto out;
+set_atts:
+       pmd.input_skip = i;
        ret = for_each_matching_row(&pmd);
-       if (ret < 0)
-               goto out;
-       if (pmd.num_matches == 0)
+       if (ret >= 0 && pmd.num_matches == 0)
                ret = -E_NO_MATCH;
 out:
+       lls_free_parse_result(aca->lpr, cmd);
        return ret;
 }
 
-int com_setatt(struct command_context *cc)
+static int com_setatt(struct command_context *cc, struct lls_parse_result *lpr)
 {
-       if (cc->argc < 3)
-               return -E_ATTR_SYNTAX;
-       return send_standard_callback_request(cc->argc - 1, cc->argv + 1,
-               com_setatt_callback, afs_cb_result_handler, cc);
+       const struct lls_command *cmd = SERVER_CMD_CMD_PTR(SETATT);
+       char *errctx;
+       int ret = lls(lls_check_arg_count(lpr, 2, INT_MAX, &errctx));
+
+       if (ret < 0) {
+               send_errctx(cc, errctx);
+               return ret;
+       }
+       return send_lls_callback_request(com_setatt_callback, cmd, lpr, cc);
 }
+EXPORT_SERVER_CMD_HANDLER(setatt);
 
 static int afs_stat_callback(struct afs_callback_arg *aca)
 {