server: Convert com_setatt() to lopsub.
authorAndre Noll <maan@tuebingen.mpg.de>
Fri, 2 Oct 2015 21:22:01 +0000 (21:22 +0000)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Mar 2017 09:02:28 +0000 (11:02 +0200)
Introduces ->input_skip for struct pattern_match data. The setatt
command uses this to strip the attribute modifies off the unnamed
arguments in the lopsub parse result. The remaining arguments are
the patterns which are to be matched against each file in the audio
file table.

afs.c
afs.cmd
afs.h
aft.c
m4/lls/server_cmd.suite.m4

diff --git a/afs.c b/afs.c
index 21035cd..92c58cc 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -401,7 +401,7 @@ static int action_if_pattern_matches(struct osl_row *row, void *data)
                }
        }
        p = pattern_txt;
-       i = 0;
+       i = pmd->input_skip;
        for (;;) {
                if (pmd->lpr) {
                        if (i >= lls_num_inputs(pmd->lpr))
diff --git a/afs.cmd b/afs.cmd
index 5a3615b..2b9e4f8 100644 (file)
--- a/afs.cmd
+++ b/afs.cmd
@@ -52,18 +52,6 @@ H:   b: by bit rate
 H:   d: by duration
 H:   a: by audio format
 ---
-N: setatt
-P: AFS_READ | AFS_WRITE
-D: Set attribute(s) for all files matching a pattern.
-U: setatt attribute{+|-}... pattern
-H: Set ('+') or unset ('-') the given attributes for all audio files matching
-H: pattern.  Example:
-H:
-H:         setatt rock+ punk+ pop- '*foo.mp3'
-H:
-H: sets the 'rock' and the 'punk' attribute and unsets the 'pop'
-H: attribute of all files ending with 'foo.mp3'.
----
 N: addatt
 P: AFS_READ | AFS_WRITE
 D: Add new attribute(s).
diff --git a/afs.h b/afs.h
index c73eb73..3d13aea 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -149,6 +149,8 @@ struct pattern_match_data {
        struct lls_parse_result *lpr;
        /** Null-terminated array of patterns. */
        struct osl_object patterns;
+       /** Do not try to match the first inputs of lpr */
+       unsigned input_skip;
        /** Data pointer passed to the action function. */
        void *data;
        /** Gets increased by one for each match. */
diff --git a/aft.c b/aft.c
index 628f98f..f186408 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -2401,9 +2401,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 +2412,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 +2449,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)
 {
index b10f355..b113934 100644 (file)
@@ -193,6 +193,20 @@ aux_info_prefix = Permissions:
 
        [/description]
 
+[subcommand setatt]
+       purpose = set or unset attributes
+       synopsis = attribute{+|-}... pattern...
+       aux_info = AFS_READ | AFS_WRITE
+       [description]
+               Set ('+') or unset ('-') the given attributes for all audio files
+               matching the given pattern. Example:
+
+                       setatt rock+ punk+ pop- '*foo.mp3'
+
+               sets the 'rock' and the 'punk' attribute and unsets the 'pop' attribute
+               of all files ending with 'foo.mp3'.
+       [/description]
+
 [subcommand si]
        purpose = print server info
        aux_info = NO_PERMISSION_REQUIRED