Refuse to add invalid attibute names.
[paraslash.git] / attribute.c
index e0a7392fdc99d86f6225c5ac43e1ab690e0bce50..e0e0bd867d6fc5e1de8259d21693800332798f38 100644 (file)
@@ -299,26 +299,34 @@ static int logical_and_attribute(struct osl_row *aft_row, void *attribute_ptr)
 }
 
 static int com_addatt_callback(const struct osl_object *query,
-               __a_unused struct osl_object *result)
+               struct osl_object *result)
 {
        char *p = query->data;
-       unsigned 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;
@@ -327,31 +335,46 @@ static int com_addatt_callback(const struct osl_object *query,
                        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++;
-               p += strlen(p) + 1;
        }
-       if (!atts_added)
-               return 1;
-       find_greatest_att_bitnum();
-       return reload_current_mood(); /* FIXME: returns an error */
+out:
+       if (ret < 0)
+               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;