GPtrArray * spl_load(const char *utf8path, GError **error_r) { FILE *file; GPtrArray *list; char *path_fs; if (spl_map(error_r) == NULL) return NULL; path_fs = spl_map_to_fs(utf8path, error_r); if (path_fs == NULL) return NULL; file = fopen(path_fs, "r"); g_free(path_fs); if (file == NULL) { playlist_errno(error_r); return NULL; } list = g_ptr_array_new(); GString *buffer = g_string_sized_new(1024); char *s; while ((s = read_text_line(file, buffer)) != NULL) { if (*s == 0 || *s == PLAYLIST_COMMENT) continue; if (g_path_is_absolute(s)) { char *t = fs_charset_to_utf8(s); if (t == NULL) continue; s = g_strconcat("file://", t, NULL); g_free(t); } else if (!uri_has_scheme(s)) { char *path_utf8; path_utf8 = map_fs_to_utf8(s); if (path_utf8 == NULL) continue; s = path_utf8; } else { s = fs_charset_to_utf8(s); if (s == NULL) continue; } g_ptr_array_add(list, s); if (list->len >= playlist_max_length) break; } fclose(file); return list; }
static struct stored_playlist_info * load_playlist_info(const char *parent_path_fs, const char *name_fs) { size_t name_length = strlen(name_fs); char *path_fs, *name, *name_utf8; int ret; struct stat st; struct stored_playlist_info *playlist; if (name_length < sizeof(PLAYLIST_FILE_SUFFIX) || memchr(name_fs, '\n', name_length) != NULL) return NULL; if (!g_str_has_suffix(name_fs, PLAYLIST_FILE_SUFFIX)) return NULL; path_fs = g_build_filename(parent_path_fs, name_fs, NULL); ret = stat(path_fs, &st); g_free(path_fs); if (ret < 0 || !S_ISREG(st.st_mode)) return NULL; name = g_strndup(name_fs, name_length + 1 - sizeof(PLAYLIST_FILE_SUFFIX)); name_utf8 = fs_charset_to_utf8(name); g_free(name); if (name_utf8 == NULL) return NULL; playlist = g_new(struct stored_playlist_info, 1); playlist->name = name_utf8; playlist->mtime = st.st_mtime; return playlist; }
static void mpd_inotify_callback(int wd, unsigned mask, G_GNUC_UNUSED const char *name, G_GNUC_UNUSED void *ctx) { struct watch_directory *directory; char *uri_fs; /*g_debug("wd=%d mask=0x%x name='%s'", wd, mask, name);*/ directory = tree_find_watch_directory(wd); if (directory == NULL) return; uri_fs = watch_directory_get_uri_fs(directory); if ((mask & (IN_DELETE_SELF|IN_MOVE_SELF)) != 0) { g_free(uri_fs); remove_watch_directory(directory); return; } if ((mask & (IN_ATTRIB|IN_CREATE|IN_MOVE)) != 0 && (mask & IN_ISDIR) != 0) { /* a sub directory was changed: register those in inotify */ const char *root = mapper_get_music_directory_fs(); const char *path_fs; char *allocated = NULL; if (uri_fs != NULL) path_fs = allocated = g_strconcat(root, "/", uri_fs, NULL); else path_fs = root; recursive_watch_subdirectories(directory, path_fs, watch_directory_depth(directory)); g_free(allocated); } if ((mask & (IN_CLOSE_WRITE|IN_MOVE|IN_DELETE)) != 0 || /* at the maximum depth, we watch out for newly created directories */ (watch_directory_depth(directory) == inotify_max_depth && (mask & (IN_CREATE|IN_ISDIR)) == (IN_CREATE|IN_ISDIR))) { /* a file was changed, or a directory was moved/deleted: queue a database update */ char *uri_utf8 = uri_fs != NULL ? fs_charset_to_utf8(uri_fs) : g_strdup(""); if (uri_utf8 != NULL) /* this function will take care of freeing uri_utf8 */ mpd_inotify_enqueue(uri_utf8); } g_free(uri_fs); }
char * map_fs_to_utf8(const char *path_fs) { if (music_dir != NULL && strncmp(path_fs, music_dir, music_dir_length) == 0 && G_IS_DIR_SEPARATOR(path_fs[music_dir_length])) /* remove musicDir prefix */ path_fs += music_dir_length + 1; else if (G_IS_DIR_SEPARATOR(path_fs[0])) /* not within musicDir */ return NULL; while (path_fs[0] == G_DIR_SEPARATOR) ++path_fs; return fs_charset_to_utf8(path_fs); }
static struct song * apply_song_metadata(struct song *dest, const struct song *src) { struct song *tmp; assert(dest != NULL); assert(src != NULL); if (src->tag == NULL && src->start_ms == 0 && src->end_ms == 0) return dest; if (song_in_database(dest)) { char *path_fs = map_song_fs(dest); if (path_fs == NULL) return dest; char *path_utf8 = fs_charset_to_utf8(path_fs); if (path_utf8 != NULL) g_free(path_fs); else path_utf8 = path_fs; tmp = song_file_new(path_utf8, NULL); g_free(path_utf8); merge_song_metadata(tmp, dest, src); } else { tmp = song_file_new(dest->uri, NULL); merge_song_metadata(tmp, dest, src); } if (dest->tag != NULL && dest->tag->time > 0 && src->start_ms > 0 && src->end_ms == 0 && src->start_ms / 1000 < (unsigned)dest->tag->time) /* the range is open-ended, and the playlist plugin did not know the total length of the song file (e.g. last track on a CUE file); fix it up here */ tmp->tag->time = dest->tag->time - src->start_ms / 1000; song_free(dest); return tmp; }
static bool updateDirectory(struct directory *directory, const struct stat *st) { DIR *dir; struct dirent *ent; char *path_fs, *exclude_path_fs; GSList *exclude_list; assert(S_ISDIR(st->st_mode)); directory_set_stat(directory, st); path_fs = map_directory_fs(directory); if (path_fs == NULL) return false; dir = opendir(path_fs); if (!dir) { g_warning("Failed to open directory %s: %s", path_fs, g_strerror(errno)); g_free(path_fs); return false; } exclude_path_fs = g_build_filename(path_fs, ".mpdignore", NULL); exclude_list = exclude_list_load(exclude_path_fs); g_free(exclude_path_fs); g_free(path_fs); if (exclude_list != NULL) remove_excluded_from_directory(directory, exclude_list); removeDeletedFromDirectory(directory); while ((ent = readdir(dir))) { char *utf8; struct stat st2; if (skip_path(ent->d_name) || exclude_list_check(exclude_list, ent->d_name)) continue; utf8 = fs_charset_to_utf8(ent->d_name); if (utf8 == NULL) continue; if (skip_symlink(directory, utf8)) { delete_name_in(directory, utf8); g_free(utf8); continue; } if (stat_directory_child(directory, utf8, &st2) == 0) updateInDirectory(directory, utf8, &st2); else delete_name_in(directory, utf8); g_free(utf8); } exclude_list_free(exclude_list); closedir(dir); directory->mtime = st->st_mtime; return true; }