+/*
+ * Adds the directory of 'path' and 'type' to the afm_db object 'afdb'.
+ * Returns 0 in case of success.
+ * Returns -1 and set errno in case of error
+ * Possible errno values: ENOMEM, ENAMETOOLONG
+ */
+static int add_dir(struct afm_db *afdb, const char *path, enum dir_type type)
+{
+ struct afm_db_dir *dir;
+ size_t len;
+
+ assert(afdb);
+
+ /* check size */
+ len = strlen(path);
+ if (len >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ /* avoiding duplications */
+ dir = afdb->dirhead;
+ while(dir != NULL && (strcmp(dir->path, path) || dir->type != type))
+ dir = dir ->next;
+ if (dir != NULL)
+ return 0;
+
+ /* allocates the structure */
+ dir = malloc(strlen(path) + sizeof * dir);
+ if (dir == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* add it at tail */
+ dir->next = NULL;
+ dir->type = type;
+ strcpy(dir->path, path);
+ if (afdb->dirtail == NULL)
+ afdb->dirhead = dir;
+ else
+ afdb->dirtail->next = dir;
+ afdb->dirtail = dir;
+ return 0;
+}
+
+/*
+ * Creates an afm_db object and returns it with one reference added.
+ * Return NULL with errno = ENOMEM if memory exhausted.
+ */
+struct afm_db *afm_db_create()
+{
+ struct afm_db *afdb = malloc(sizeof * afdb);
+ if (afdb == NULL)
+ errno = ENOMEM;
+ else {
+ afdb->refcount = 1;
+ afdb->dirhead = NULL;
+ afdb->dirtail = NULL;
+ afdb->applications.pubarr = NULL;
+ afdb->applications.direct = NULL;
+ afdb->applications.byapp = NULL;
+ }
+ return afdb;
+}
+
+/*
+ * Adds a reference to an existing afm_db.
+ */
+void afm_db_addref(struct afm_db *afdb)
+{
+ assert(afdb);
+ afdb->refcount++;
+}
+
+/*
+ * Removes a reference to an existing afm_db object.
+ * Removes the objet if there no more reference to it.
+ */
+void afm_db_unref(struct afm_db *afdb)
+{
+ struct afm_db_dir *dir;
+
+ assert(afdb);
+ if (!--afdb->refcount) {
+ /* no more reference, clean the memory used by the object */
+ apps_put(&afdb->applications);
+ while (afdb->dirhead != NULL) {
+ dir = afdb->dirhead;
+ afdb->dirhead = dir->next;
+ free(dir);
+ }
+ free(afdb);
+ }
+}
+
+/*
+ * Adds the root directory of 'path' to the afm_db object 'afdb'.
+ * Be aware that no check is done on the directory of 'path' that will
+ * only be used within calls to the function 'afm_db_update_applications'.
+ * Returns 0 in case of success.
+ * Returns -1 and set errno in case of error
+ * Possible errno values: ENOMEM, ENAMETOOLONG
+ */
+int afm_db_add_root(struct afm_db *afdb, const char *path)
+{
+ return add_dir(afdb, path, type_root);
+}
+
+/*
+ * Adds the application directory of 'path' to the afm_db object 'afdb'.
+ * Be aware that no check is done on the directory of 'path' that will
+ * only be used within calls to the function 'afm_db_update_applications'.
+ * Returns 0 in case of success.
+ * Returns -1 and set errno in case of error
+ * Possible errno values: ENOMEM, ENAMETOOLONG
+ */
+int afm_db_add_application(struct afm_db *afdb, const char *path)
+{
+ return add_dir(afdb, path, type_app);
+}
+
+/*
+ * Regenerate the list of applications of the afm_bd object 'afdb'.
+ * Returns 0 in case of success.
+ * Returns -1 and set errno in case of error
+ */