return -E_AFT_SYNTAX;
if (!(flags & ~CPSI_FLAG_VERBOSE)) /* no copy flags given */
flags = ~(unsigned)CPSI_FLAG_VERBOSE | flags;
- ret = send_option_arg_callback_request(&options, cc->argc - i,
+ return send_option_arg_callback_request(&options, cc->argc - i,
cc->argv + i, com_cpsi_callback, afs_cb_result_handler, cc);
- cad.add_mask |= (1UL << bitnum);
+}
+
+struct change_atts_data {
+ uint64_t add_mask, del_mask;
+ struct afs_callback_arg *aca;
+};
+
+static int change_atts(__a_unused struct osl_table *table,
+ struct osl_row *row, __a_unused const char *name, void *data)
+{
+ int ret;
+ struct osl_object obj;
+ struct afs_info old_afsi, new_afsi;
+ struct afsi_change_event_data aced = {
+ .aft_row = row,
+ .old_afsi = &old_afsi
+ };
+ struct change_atts_data *cad = data;
+
+ ret = get_afsi_object_of_row(row, &obj);
+ if (ret < 0)
+ return ret;
+ ret = load_afsi(&old_afsi, &obj);
+ if (ret < 0)
+ return ret;
+ new_afsi = old_afsi;
+ new_afsi.attributes |= cad->add_mask;
+ new_afsi.attributes &= ~cad->del_mask;
+ save_afsi(&new_afsi, &obj); /* in-place update */
+ return afs_event(AFSI_CHANGE, &cad->aca->pbout, &aced);
+}
+
+static int com_setatt_callback(struct afs_callback_arg *aca)
+{
+ char *p;
+ int ret;
+ size_t len;
+ struct change_atts_data cad = {.aca = aca};
+ struct pattern_match_data pmd = {
+ .table = audio_file_table,
+ .loop_col_num = AFTCOL_HASH,
+ .match_col_num = AFTCOL_PATH,
+ .pm_flags = PM_SKIP_EMPTY_NAME,
+ .data = &cad,
+ .action = change_atts
+ };
+
+ for (
+ p = aca->query.data;
+ p < (char *)aca->query.data + aca->query.size;
+ p += len + 1
+ ) {
+ char c;
+ unsigned char bitnum;
++ uint64_t one = 1;
+
+ len = strlen(p);
+ ret = -E_ATTR_SYNTAX;
+ if (len == 0)
+ goto out;
+ c = p[len - 1];
+ if (c != '+' && c != '-')
+ break;
+ p[len - 1] = '\0';
+ ret = get_attribute_bitnum_by_name(p, &bitnum);
+ if (ret < 0) {
+ para_printf(&aca->pbout, "attribute not found: %s\n", p);
+ goto out;
+ }
+ if (c == '+')
- cad.del_mask |= (1UL << bitnum);
++ cad.add_mask |= (one << bitnum);
+ else
++ cad.del_mask |= (one << bitnum);
+ }
+ 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;
+ ret = for_each_matching_row(&pmd);
if (ret < 0)
- send_strerror(cc, -ret);
+ goto out;
+ if (pmd.num_matches == 0)
+ ret = -E_NO_MATCH;
+out:
return ret;
}