X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=aft.c;h=412d19aa076235a7c663f943cce7a1fcec184a0c;hb=fd5f94274de04e4dfed9bea8aadac661262d7cca;hp=f01f1868e60b1592c9bde8f0d371234edd60d23a;hpb=c4bfb18b78b3935b8dbf68f70b219cfb2a192979;p=paraslash.git diff --git a/aft.c b/aft.c index f01f1868..412d19aa 100644 --- a/aft.c +++ b/aft.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007-2012 Andre Noll + * Copyright (C) 2007-2013 Andre Noll * * Licensed under the GPL v2. For licencing details see COPYING. */ @@ -280,7 +280,7 @@ static struct osl_table_description audio_file_table_desc = { .column_descriptions = aft_cols }; -/* We don't want * dot or dot-dot anywhere. */ +/* We don't want dot or dot-dot anywhere. */ static int verify_dotfile(const char *rest) { /* @@ -1694,7 +1694,7 @@ static void com_add_callback(int fd, const struct osl_object *query) uint16_t afhi_offset, chunks_offset; hash = (unsigned char *)buf + CAB_HASH_OFFSET; - hash_to_asc(hash, asc);; + hash_to_asc(hash, asc); objs[AFTCOL_HASH].data = buf + CAB_HASH_OFFSET; objs[AFTCOL_HASH].size = HASH_SIZE; @@ -2502,6 +2502,72 @@ int com_cpsi(struct command_context *cc) return ret; } +static void com_setatt_callback(__a_unused int fd, const struct osl_object *query) +{ + char *p; + uint64_t add_mask = 0, del_mask = 0; + int ret; + size_t len; + struct osl_object obj; + + for (p = query->data; p < (char *)query->data + query->size; p += len + 1) { + char c; + unsigned char bitnum; + + len = strlen(p); + ret = -E_ATTR_SYNTAX; + if (!*p) + 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) + goto out; + if (c == '+') + add_mask |= (1UL << bitnum); + else + del_mask |= (1UL << bitnum); + } + ret = -E_ATTR_SYNTAX; + if (!add_mask && !del_mask) + goto out; + PARA_DEBUG_LOG("masks: %llx:%llx\n",(long long unsigned)add_mask, + (long long unsigned)del_mask); + for (; p < (char *)query->data + query->size; p += len + 1) { /* TODO: fnmatch */ + struct afs_info old_afsi, new_afsi; + struct afsi_change_event_data aced = {.old_afsi = &old_afsi}; + + len = strlen(p); + ret = aft_get_row_of_path(p, &aced.aft_row); + if (ret < 0) + goto out; + ret = get_afsi_object_of_row(aced.aft_row, &obj); + if (ret < 0) + goto out; + ret = load_afsi(&old_afsi, &obj); + if (ret < 0) + goto out; + new_afsi = old_afsi; + new_afsi.attributes |= add_mask; + new_afsi.attributes &= ~del_mask; + save_afsi(&new_afsi, &obj); /* in-place update */ + afs_event(AFSI_CHANGE, NULL, &aced); + } +out: + if (ret < 0) + PARA_NOTICE_LOG("%s\n", para_strerror(-ret)); +} + +int com_setatt(struct command_context *cc) +{ + if (cc->argc < 3) + return -E_ATTR_SYNTAX; + return send_standard_callback_request(cc->argc - 1, cc->argv + 1, + com_setatt_callback, NULL, NULL); +} + static void afs_stat_callback(int fd, const struct osl_object *query) { int *parser_friendly = query->data;