return 1;
}
+/**
+ * Flags used by the lsatt command.
+ *
+ * \param \sa com_lsatt().
+ */
enum lsatt_flags {
/** Whether "-a" was given for the lsatt command. */
- LSATT_FLAG_ALPHA = 1,
+ LSATT_FLAG_SORT_BY_ID = 1,
/** Whether "-l" was given for the lsatt command. */
LSATT_FLAG_LONG = 2,
+ /** Reverse sort order. */
LSATT_FLAG_REVERSE = 4
};
ret = osl_get_object(table, row, ATTCOL_BITNUM, &bitnum_obj);
if (ret < 0) {
para_printf(&laad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
- return 1;
+ return ret;
}
para_printf(&laad->pb, "%u\t%s\n", *(unsigned char*)bitnum_obj.data,
name);
struct osl_object *result)
{
struct lsatt_action_data laad = {.flags = *(unsigned *) query->data};
- int ret;
struct pattern_match_data pmd = {
.table = attribute_table,
.loop_col_num = ATTCOL_BITNUM,
.data = &laad,
.action = print_attribute
};
+ int ret;
- if (laad.flags & LSATT_FLAG_ALPHA)
+ if (laad.flags & LSATT_FLAG_SORT_BY_ID)
pmd.loop_col_num = ATTCOL_NAME;
if (laad.flags & LSATT_FLAG_REVERSE)
pmd.pm_flags |= PM_REVERSE_LOOP;
if (ret < 0)
para_printf(&laad.pb, "%s\n", PARA_STRERROR(-ret));
if (!laad.pb.buf)
- para_printf(&laad.pb, "no match\n");
+ return 0;
result->data = laad.pb.buf;
result->size = laad.pb.size;
return 1;
i++;
break;
}
- if (!strcmp(arg, "-a")) {
- flags |= LSATT_FLAG_ALPHA;
+ if (!strcmp(arg, "-i")) {
+ flags |= LSATT_FLAG_SORT_BY_ID;
continue;
}
if (!strcmp(arg, "-l")) {
}
static int com_addatt_callback(const struct osl_object *query,
- __a_unused struct osl_object *result)
+ struct osl_object *result)
{
char *p = query->data;
- uint64_t atts_added = 0;
- int ret;
+ int ret = 1;
+ struct para_buffer pb = {.size = 0};
+ size_t len;
- while (p < (char *)query->data + query->size) {
+ for (p = query->data; p < (char *)query->data + query->size; p += len + 1) {
struct osl_object objs[NUM_ATT_COLUMNS];
struct osl_row *row;
unsigned char bitnum;
+ len = strlen(p);
+ if (!len || p[len - 1] == '-' || p[len - 1] == '+') {
+ para_printf(&pb, "invalid attribute name: %s\n", p);
+ continue;
+ }
objs[ATTCOL_BITNUM].size = 1;
objs[ATTCOL_NAME].data = p;
- objs[ATTCOL_NAME].size = strlen(p) + 1;
+ objs[ATTCOL_NAME].size = len + 1;
ret = osl_get_row(attribute_table, ATTCOL_NAME,
&objs[ATTCOL_NAME], &row); /* expected to fail */
- if (ret >= 0)
- return -E_ATTR_EXISTS;
+ if (ret >= 0) {
+ para_printf(&pb, "attribute %s already exists\n", p);
+ continue;
+ }
if (ret != -E_RB_KEY_NOT_FOUND) /* error */
- return ret;
+ goto out;
/* find smallest non-used attribute */
for (bitnum = 0; bitnum < 64; bitnum++) {
objs[ATTCOL_BITNUM].data = &bitnum;
if (ret == -E_RB_KEY_NOT_FOUND)
break; /* this bitnum is unused, use it */
if (ret < 0) /* error */
- return ret;
+ goto out;
/* this bit is already in use, try next bit */
}
- if (bitnum == 64)
- return -E_ATTR_TABLE_FULL;
+ if (bitnum == 64) {
+ para_printf(&pb, "attribute table full\n");
+ goto out;
+ }
ret = osl_add_row(attribute_table, objs);
if (ret < 0)
- return ret;
+ goto out;
greatest_att_bitnum = PARA_MAX(greatest_att_bitnum, bitnum);
- atts_added |= 1 << bitnum;
- p += strlen(p) + 1;
}
- if (!atts_added)
- return 1;
- atts_added = ~atts_added;
- ret = audio_file_loop(&atts_added, logical_and_attribute);
+out:
if (ret < 0)
- return ret;
- find_greatest_att_bitnum();
- return reload_current_mood(); /* FIXME: mood_reload() returns an error */
+ para_printf(&pb, "%s: %s\n", p, PARA_STRERROR(-ret));
+ result->data = pb.buf;
+ result->size = pb.size;
+ return result->data? 0 : 1;
}
-int com_addatt(__a_unused int fd, int argc, char * const * const argv)
+int com_addatt(int fd, int argc, char * const * const argv)
{
+ struct osl_object result;
+ int ret;
+
if (argc < 2)
return -E_ATTR_SYNTAX;
- return send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
- NULL);
+ ret = send_standard_callback_request(argc - 1, argv + 1, com_addatt_callback,
+ &result);
+ if (!ret)
+ return 1;
+ if (ret < 0)
+ return ret;
+ if (!result.data || !result.size)
+ return 1;
+ ret = send_va_buffer(fd, "%s", (char *) result.data);
+ free(result.data);
+ return ret;
}
+
struct remove_attribute_action_data {
struct para_buffer pb;
int num_removed;
+ uint64_t mask_of_removed_atts;
};
static int remove_attribute(struct osl_table *table, struct osl_row *row,
const char *name, void *data)
{
struct remove_attribute_action_data *raad = data;
- int ret = osl_del_row(table, row);
- if (ret < 0)
+ unsigned char bitnum;
+ int ret;
+
+ ret = get_attribute_bitnum_by_name(name, &bitnum);
+ if (ret < 0) {
para_printf(&raad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
- else {
- para_printf(&raad->pb, "removed %s\n", name);
- raad->num_removed++;
+ return 1;
}
+ ret = osl_del_row(table, row);
+ if (ret < 0) {
+ para_printf(&raad->pb, "%s: %s\n", name, PARA_STRERROR(-ret));
+ return 1;
+ }
+ para_printf(&raad->pb, "removed %s\n", name);
+ raad->num_removed++;
+ raad->mask_of_removed_atts |= (1 << bitnum);
return 1;
}
if (ret < 0)
para_printf(&raad.pb, "%s\n", PARA_STRERROR(-ret));
if (raad.num_removed) {
+ uint64_t and_mask = ~raad.mask_of_removed_atts;
+ ret = audio_file_loop(&and_mask, logical_and_attribute);
+ if (ret < 0)
+ para_printf(&raad.pb, "%s\n", PARA_STRERROR(-ret));
find_greatest_att_bitnum();
ret = reload_current_mood();
if (ret < 0)
return ret;
}
attribute_table = NULL;
- if (ret == -E_NOENT)
+ if (ret >= 0 || is_errno(-ret, ENOENT))
return 1;
return ret;
}