1 /* the Music Player Daemon (MPD)
2 * Copyright (C) 2003-2007 by Warren Dukes (warren.dukes@gmail.com)
3 * This project's homepage is: 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.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include <sys/types.h>
35 #ifdef HAVE_LANGINFO_CODESET
42 static const char *playlistDir
;
43 static char *fsCharset
;
45 static char *pathConvCharset(char *to
, char *from
, char *str
, char *ret
)
49 return setCharSetConversion(to
, from
) ? NULL
: convStrDup(str
);
52 char *fsCharsetToUtf8(char *str
)
56 ret
= pathConvCharset("UTF-8", fsCharset
, str
, ret
);
58 if (ret
&& !validUtf8String(ret
)) {
66 char *utf8ToFsCharset(char *str
)
70 ret
= pathConvCharset(fsCharset
, "UTF-8", str
, ret
);
78 void setFsCharset(char *charset
)
85 fsCharset
= xstrdup(charset
);
87 DEBUG("setFsCharset: fs charset is: %s\n", fsCharset
);
89 if (setCharSetConversion("UTF-8", fsCharset
) != 0) {
90 WARNING("fs charset conversion problem: "
91 "not able to convert from \"%s\" to \"%s\"\n",
95 if (setCharSetConversion(fsCharset
, "UTF-8") != 0) {
96 WARNING("fs charset conversion problem: "
97 "not able to convert from \"%s\" to \"%s\"\n",
104 WARNING("setting fs charset to ISO-8859-1!\n");
105 fsCharset
= xstrdup("ISO-8859-1");
109 char *getFsCharset(void)
114 static char *appendSlash(char **path
)
117 int len
= strlen(temp
);
119 if (temp
[len
- 1] != '/') {
120 temp
= xmalloc(len
+ 2);
121 memset(temp
, 0, len
+ 2);
122 memcpy(temp
, *path
, len
);
133 ConfigParam
*musicParam
= parseConfigFilePath(CONF_MUSIC_DIR
, 1);
134 ConfigParam
*playlistParam
= parseConfigFilePath(CONF_PLAYLIST_DIR
, 1);
135 ConfigParam
*fsCharsetParam
= getConfigParam(CONF_FS_CHARSET
);
137 char *charset
= NULL
;
138 char *originalLocale
;
141 musicDir
= appendSlash(&(musicParam
->value
));
142 playlistDir
= appendSlash(&(playlistParam
->value
));
144 if ((dir
= opendir(playlistDir
)) == NULL
) {
145 FATAL("cannot open %s \"%s\" (config line %i): %s\n",
146 CONF_PLAYLIST_DIR
, playlistParam
->value
,
147 playlistParam
->line
, strerror(errno
));
151 if ((dir
= opendir(musicDir
)) == NULL
) {
152 FATAL("cannot open %s \"%s\" (config line %i): %s\n",
153 CONF_MUSIC_DIR
, musicParam
->value
,
154 musicParam
->line
, strerror(errno
));
158 if (fsCharsetParam
) {
159 charset
= xstrdup(fsCharsetParam
->value
);
162 #ifdef HAVE_LANGINFO_CODESET
163 else if ((originalLocale
= setlocale(LC_CTYPE
, NULL
))) {
166 originalLocale
= xstrdup(originalLocale
);
168 if (!(currentLocale
= setlocale(LC_CTYPE
, ""))) {
169 WARNING("problems setting current locale with "
172 if (strcmp(currentLocale
, "C") == 0 ||
173 strcmp(currentLocale
, "POSIX") == 0) {
174 WARNING("current locale is \"%s\"\n",
176 } else if ((temp
= nl_langinfo(CODESET
))) {
177 charset
= xstrdup(temp
);
180 ("problems getting charset for locale\n");
181 if (!setlocale(LC_CTYPE
, originalLocale
)) {
183 ("problems resetting locale with setlocale()\n");
187 free(originalLocale
);
189 WARNING("problems getting locale with setlocale()\n");
194 setFsCharset(charset
);
197 WARNING("setting filesystem charset to ISO-8859-1\n");
198 setFsCharset("ISO-8859-1");
202 void finishPaths(void)
208 static char *pfx_path(const char *path
, const char *pfx
, const size_t pfx_len
)
210 static char ret
[MAXPATHLEN
+1];
211 size_t rp_len
= strlen(path
);
213 /* check for the likely condition first: */
214 if (mpd_likely((pfx_len
+ rp_len
) < MAXPATHLEN
)) {
215 memcpy(ret
, pfx
, pfx_len
);
216 memcpy(ret
+ pfx_len
, path
, rp_len
+ 1);
220 /* unlikely, return an empty string because truncating would
221 * also be wrong... break early and break loudly (the system
222 * headers are likely screwed, not mpd) */
223 ERROR("Cannot prefix '%s' to '%s', max: %d", pfx
, path
, MAXPATHLEN
);
228 char *rmp2amp(char *relativePath
)
230 size_t pfx_len
= strlen(musicDir
);
231 return pfx_path(relativePath
, musicDir
, pfx_len
);
234 char *rpp2app(char *relativePath
)
236 size_t pfx_len
= strlen(playlistDir
);
237 return pfx_path(relativePath
, playlistDir
, pfx_len
);
240 /* this is actually like strlcpy (OpenBSD), but we don't actually want to
241 * blindly use it everywhere, only for paths that are OK to truncate (for
242 * error reporting and such */
243 void pathcpy_trunc(char *dest
, const char *src
)
245 size_t len
= strlen(src
);
247 if (mpd_unlikely(len
> MAXPATHLEN
))
249 memcpy(dest
, src
, len
);
253 char *parentPath(char *path
)
255 static char parentPath
[MAXPATHLEN
+1];
258 pathcpy_trunc(parentPath
, path
);
259 c
= strrchr(parentPath
,'/');
262 parentPath
[0] = '\0';
264 while ((parentPath
<= c
) && *(--c
) == '/') /* nothing */
272 char *sanitizePathDup(char *path
)
274 int len
= strlen(path
) + 1;
275 char *ret
= xmalloc(len
);
282 /* eliminate more than one '/' in a row, like "///" */
287 /* we don't want to have hidden directories, or '.' or
292 while (*path
&& *path
!= '/') {
302 if (len
&& ret
[len
- 1] == '/') {
307 DEBUG("sanitized: %s\n", ret
);
309 return xrealloc(ret
, len
+ 1);