+ if (ret >= 0 || is_errno(-ret, ENOENT))
+ return 1;
+ return ret;
+}
+
+static int aft_create(const char *dir)
+{
+ audio_file_table_desc.dir = dir;
+ return osl_create_table(&audio_file_table_desc);
+}
+
+static int clear_attribute(struct osl_row *row, void *data)
+{
+ struct rmatt_event_data *red = data;
+ struct afs_info afsi;
+ struct osl_object obj;
+ int ret = get_afsi_object_of_row(row, &obj);
+ uint64_t mask = ~(1ULL << red->bitnum);
+
+ if (ret < 0)
+ return ret;
+ ret = load_afsi(&afsi, &obj);
+ if (ret < 0)
+ return ret;
+ afsi.attributes &= mask;
+ save_afsi(&afsi, &obj);
+ return 1;
+}
+
+static int aft_event_handler(enum afs_events event, struct para_buffer *pb,
+ void *data)
+{
+ switch(event) {
+ case ATTRIBUTE_REMOVE: {
+ const struct rmatt_event_data *red = data;
+ para_printf(pb, "clearing attribute %s (bit %u) from all "
+ "entries in the audio file table\n", red->name,
+ red->bitnum);
+ return audio_file_loop(data, clear_attribute);
+ }
+ default:
+ return 1;
+ }
+}
+
+void aft_init(struct afs_table *t)
+{
+ t->name = audio_file_table_desc.name;
+ t->open = aft_open;
+ t->close = aft_close;
+ t->create = aft_create;
+ t->event_handler = aft_event_handler;