static struct directory * directory_make_child_checked(struct directory *parent, const char *path) { struct directory *directory; char *base; struct stat st; struct song *conflicting; directory = directory_get_child(parent, path); if (directory != NULL) return directory; base = g_path_get_basename(path); if (stat_directory_child(parent, base, &st) < 0 || inodeFoundInParent(parent, st.st_ino, st.st_dev)) { g_free(base); return NULL; } /* if we're adding directory paths, make sure to delete filenames with potentially the same name */ conflicting = songvec_find(&parent->songs, base); if (conflicting) delete_song(parent, conflicting); g_free(base); directory = directory_new_child(parent, path); directory_set_stat(directory, &st); return directory; }
struct directory * directory_lookup_directory(struct directory *directory, const char *uri) { struct directory *cur = directory; struct directory *found = NULL; char *duplicated; char *locate; assert(uri != NULL); if (isRootDirectory(uri)) return directory; duplicated = g_strdup(uri); locate = strchr(duplicated, '/'); while (1) { if (locate) *locate = '\0'; if (!(found = directory_get_child(cur, duplicated))) break; assert(cur == found->parent); cur = found; if (!locate) break; *locate = '/'; locate = strchr(locate + 1, '/'); } g_free(duplicated); return found; }
static struct directory * directory_load_subdir(FILE *fp, struct directory *parent, const char *name, GString *buffer, GError **error_r) { struct directory *directory; const char *line; bool success; if (directory_get_child(parent, name) != NULL) { g_set_error(error_r, directory_quark(), 0, "Duplicate subdirectory '%s'", name); return NULL; } if (directory_is_root(parent)) { directory = directory_new(name, parent); } else { char *path = g_strconcat(directory_get_path(parent), "/", name, NULL); directory = directory_new(path, parent); g_free(path); } line = read_text_line(fp, buffer); if (line == NULL) { g_set_error(error_r, directory_quark(), 0, "Unexpected end of file"); directory_free(directory); return NULL; } if (g_str_has_prefix(line, DIRECTORY_MTIME)) { directory->mtime = g_ascii_strtoull(line + sizeof(DIRECTORY_MTIME) - 1, NULL, 10); line = read_text_line(fp, buffer); if (line == NULL) { g_set_error(error_r, directory_quark(), 0, "Unexpected end of file"); directory_free(directory); return NULL; } } if (!g_str_has_prefix(line, DIRECTORY_BEGIN)) { g_set_error(error_r, directory_quark(), 0, "Malformed line: %s", line); directory_free(directory); return NULL; } success = directory_load(fp, directory, buffer, error_r); if (!success) { directory_free(directory); return NULL; } return directory; }
static void delete_name_in(struct directory *parent, const char *name) { struct directory *directory = directory_get_child(parent, name); struct song *song = songvec_find(&parent->songs, name); if (directory != NULL) { delete_directory(directory); modified = true; } if (song != NULL) { delete_song(parent, song); modified = true; } }
static struct directory * make_subdir(struct directory *parent, const char *name) { struct directory *directory; directory = directory_get_child(parent, name); if (directory == NULL) { char *path; if (directory_is_root(parent)) path = NULL; else name = path = g_strconcat(directory_get_path(parent), "/", name, NULL); directory = directory_new_child(parent, name); g_free(path); } return directory; }
/** * Create the specified directory object if it does not exist already * or if the #stat object indicates that it has been modified since * the last update. Returns NULL when it exists already and is * unmodified. * * The caller must lock the database. */ static struct directory * make_directory_if_modified(struct directory *parent, const char *name, const struct stat *st) { struct directory *directory = directory_get_child(parent, name); // directory exists already if (directory != NULL) { if (directory->mtime == st->st_mtime && !walk_discard) { /* not modified */ db_unlock(); return NULL; } delete_directory(directory); modified = true; } directory = directory_make_child(parent, name); directory->mtime = st->st_mtime; return directory; }