2 * Copyright (C) 2003-2010 The Music Player Daemon Project
3 * http://www.musicpd.org
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "directory_save.h"
22 #include "directory.h"
24 #include "text_file.h"
25 #include "song_save.h"
30 #define DIRECTORY_MTIME "mtime: "
31 #define DIRECTORY_BEGIN "begin: "
32 #define DIRECTORY_END "end: "
35 * The quark used for GError.domain.
40 return g_quark_from_static_string("directory");
44 directory_save(FILE *fp
, struct directory
*directory
)
46 struct dirvec
*children
= &directory
->children
;
49 if (!directory_is_root(directory
)) {
50 fprintf(fp
, DIRECTORY_MTIME
"%lu\n",
51 (unsigned long)directory
->mtime
);
53 fprintf(fp
, "%s%s\n", DIRECTORY_BEGIN
,
54 directory_get_path(directory
));
57 for (i
= 0; i
< children
->nr
; ++i
) {
58 struct directory
*cur
= children
->base
[i
];
59 char *base
= g_path_get_basename(cur
->path
);
61 fprintf(fp
, DIRECTORY_DIR
"%s\n", base
);
64 directory_save(fp
, cur
);
70 songvec_save(fp
, &directory
->songs
);
72 if (!directory_is_root(directory
))
73 fprintf(fp
, DIRECTORY_END
"%s\n",
74 directory_get_path(directory
));
77 static struct directory
*
78 directory_load_subdir(FILE *fp
, struct directory
*parent
, const char *name
,
79 GString
*buffer
, GError
**error_r
)
81 struct directory
*directory
;
85 if (directory_get_child(parent
, name
) != NULL
) {
86 g_set_error(error_r
, directory_quark(), 0,
87 "Duplicate subdirectory '%s'", name
);
91 if (directory_is_root(parent
)) {
92 directory
= directory_new(name
, parent
);
94 char *path
= g_strconcat(directory_get_path(parent
), "/",
96 directory
= directory_new(path
, parent
);
100 line
= read_text_line(fp
, buffer
);
102 g_set_error(error_r
, directory_quark(), 0,
103 "Unexpected end of file");
104 directory_free(directory
);
108 if (g_str_has_prefix(line
, DIRECTORY_MTIME
)) {
110 g_ascii_strtoull(line
+ sizeof(DIRECTORY_MTIME
) - 1,
113 line
= read_text_line(fp
, buffer
);
115 g_set_error(error_r
, directory_quark(), 0,
116 "Unexpected end of file");
117 directory_free(directory
);
122 if (!g_str_has_prefix(line
, DIRECTORY_BEGIN
)) {
123 g_set_error(error_r
, directory_quark(), 0,
124 "Malformed line: %s", line
);
125 directory_free(directory
);
129 success
= directory_load(fp
, directory
, buffer
, error_r
);
131 directory_free(directory
);
139 directory_load(FILE *fp
, struct directory
*directory
,
140 GString
*buffer
, GError
**error
)
144 while ((line
= read_text_line(fp
, buffer
)) != NULL
&&
145 !g_str_has_prefix(line
, DIRECTORY_END
)) {
146 if (g_str_has_prefix(line
, DIRECTORY_DIR
)) {
147 struct directory
*subdir
=
148 directory_load_subdir(fp
, directory
,
149 line
+ sizeof(DIRECTORY_DIR
) - 1,
154 dirvec_add(&directory
->children
, subdir
);
155 } else if (g_str_has_prefix(line
, SONG_BEGIN
)) {
156 const char *name
= line
+ sizeof(SONG_BEGIN
) - 1;
159 if (songvec_find(&directory
->songs
, name
) != NULL
) {
160 g_set_error(error
, directory_quark(), 0,
161 "Duplicate song '%s'", name
);
165 song
= song_load(fp
, directory
, name
,
170 songvec_add(&directory
->songs
, song
);
172 g_set_error(error
, directory_quark(), 0,
173 "Malformed line: %s", line
);