Commit b79f6b88 authored by Eric Wong's avatar Eric Wong

Merge branches/ew r7104

thread-safety work in preparation for rewrite to use pthreads Expect no regressions against trunk (r7078), possibly minor performance improvements in update (due to fewer heap allocations), but increased stack usage. Applied the following patches: * maxpath_str for reentrancy (temporary fix, reverted) * path: start working on thread-safe variants of these methods * Re-entrancy work on path/character-set conversions * directory.c: exploreDirectory() use reentrant functions here * directory/update: more use of reentrant functions + cleanups * string_toupper: a strdup-less version of strDupToUpper * get_song_url: a static-variable-free version of getSongUrl() * Use reentrant/thread-safe get_song_url everywhere * replace rmp2amp with the reentrant version, rmp2amp_r * Get rid of the non-reentrant/non-thread-safe rpp2app, too. * buffer2array: assert strdup() returns a usable value in unit tests * replace utf8ToFsCharset and fsCharsetToUtf8 with thread-safe variants * fix storing playlists w/o absolute paths * parent_path(), a reentrant version of parentPath() * parentPath => parent_path for reentrancy and thread-safety * allow "make test" to automatically run embedded unit tests * remove convStrDup() and maxpath_str() * use MPD_PATH_MAX everywhere instead of MAXPATHLEN * path: get rid of appendSlash, pfx_path and just use pfx_dir * get_song_url: fix the ability to play songs in the top-level music_directory git-svn-id: https://svn.musicpd.org/mpd/trunk@7106 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 0d26248a
...@@ -5,5 +5,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE) ...@@ -5,5 +5,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README UPGRADING doc_DATA = README UPGRADING
EXTRA_DIST = COPYING $(doc_DATA) EXTRA_DIST = COPYING $(doc_DATA)
sparse-check: sparse-check test:
$(MAKE) -C src $@ $(MAKE) -C src $@
.PHONY: sparse-check test
...@@ -151,3 +151,15 @@ sparse-check: ...@@ -151,3 +151,15 @@ sparse-check:
$(SPARSE) -I. $(mpd_CFLAGS) $(SPARSE_FLAGS) $(srcdir)/$$i || exit; \ $(SPARSE) -I. $(mpd_CFLAGS) $(SPARSE_FLAGS) $(srcdir)/$$i || exit; \
done done
TEST_CFLAGS = -DUNIT_TEST
TEST_FILES := $(shell grep UNIT_TEST $(mpd_SOURCES) | \
awk -F: '{print $$1}' | uniq)
test: $(addprefix test-, $(subst .c,,$(TEST_FILES)))
test-%: %.c
$(CC) $(CFLAGS) $(TEST_CFLAGS) -o $@ $<
@./$@
@echo $@: OK
.PHONY: sparse-check test
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#define AUDIO_DEVICE_STATE "audio_device_state:" #define AUDIO_DEVICE_STATE "audio_device_state:"
#define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */ #define AUDIO_DEVICE_STATE_LEN 19 /* strlen(AUDIO_DEVICE_STATE) */
#define AUDIO_BUFFER_SIZE 2*MAXPATHLEN #define AUDIO_BUFFER_SIZE 2*MPD_PATH_MAX
static AudioFormat audio_format; static AudioFormat audio_format;
......
...@@ -79,48 +79,56 @@ int main() ...@@ -79,48 +79,56 @@ int main()
int max; int max;
b = strdup("lsinfo \"/some/dir/name \\\"test\\\"\""); b = strdup("lsinfo \"/some/dir/name \\\"test\\\"\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("/some/dir/name \"test\"", a[1]) ); assert( !strcmp("/some/dir/name \"test\"", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"/some/dir/name \\\"test\\\" something else\""); b = strdup("lsinfo \"/some/dir/name \\\"test\\\" something else\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("/some/dir/name \"test\" something else", a[1]) ); assert( !strcmp("/some/dir/name \"test\" something else", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"/some/dir\\\\name\""); b = strdup("lsinfo \"/some/dir\\\\name\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("/some/dir\\name", a[1]) ); assert( !strcmp("/some/dir\\name", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"/some/dir name\""); b = strdup("lsinfo \"/some/dir name\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("/some/dir name", a[1]) ); assert( !strcmp("/some/dir name", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"\\\"/some/dir\\\"\""); b = strdup("lsinfo \"\\\"/some/dir\\\"\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("\"/some/dir\"", a[1]) ); assert( !strcmp("\"/some/dir\"", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"\\\"/some/dir\\\" x\""); b = strdup("lsinfo \"\\\"/some/dir\\\" x\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("\"/some/dir\" x", a[1]) ); assert( !strcmp("\"/some/dir\" x", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"single quote\\'d from php magicquotes\""); b = strdup("lsinfo \"single quote\\'d from php magicquotes\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("single quote\'d from php magicquotes", a[1]) ); assert( !strcmp("single quote\'d from php magicquotes", a[1]) );
assert( !a[2] ); assert( !a[2] );
b = strdup("lsinfo \"double quote\\\"d from php magicquotes\""); b = strdup("lsinfo \"double quote\\\"d from php magicquotes\"");
assert(b);
max = buffer2array(b, a, 4); max = buffer2array(b, a, 4);
assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("lsinfo", a[0]) );
assert( !strcmp("double quote\"d from php magicquotes", a[1]) ); assert( !strcmp("double quote\"d from php magicquotes", a[1]) );
......
...@@ -95,26 +95,25 @@ int setCharSetConversion(char *to, char *from) ...@@ -95,26 +95,25 @@ int setCharSetConversion(char *to, char *from)
return -1; return -1;
} }
char *convStrDup(char *string) char *char_conv_str(char *dest, char *string)
{ {
if (!char_conv_to) if (!char_conv_to)
return NULL; return NULL;
if (char_conv_same) if (char_conv_same)
return xstrdup(string); return strcpy(dest, string);
#ifdef HAVE_ICONV #ifdef HAVE_ICONV
if (char_conv_use_iconv) { if (char_conv_use_iconv) {
/* not optimized: */
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
size_t inleft = strlen(string); size_t inleft = strlen(string);
char *ret;
size_t outleft; size_t outleft;
size_t retlen = 0; size_t retlen = 0;
size_t err; size_t err;
char *bufferPtr; char *bufferPtr;
ret = xmalloc(1); dest[0] = '\0';
ret[0] = '\0';
while (inleft) { while (inleft) {
bufferPtr = buffer; bufferPtr = buffer;
...@@ -124,27 +123,22 @@ char *convStrDup(char *string) ...@@ -124,27 +123,22 @@ char *convStrDup(char *string)
&outleft); &outleft);
if (outleft == BUFFER_SIZE if (outleft == BUFFER_SIZE
|| (err == -1L && errno != E2BIG)) { || (err == -1L && errno != E2BIG)) {
free(ret);
return NULL; return NULL;
} }
memcpy(dest + retlen, buffer, BUFFER_SIZE - outleft);
ret = xrealloc(ret, retlen + BUFFER_SIZE - outleft + 1);
memcpy(ret + retlen, buffer, BUFFER_SIZE - outleft);
retlen += BUFFER_SIZE - outleft; retlen += BUFFER_SIZE - outleft;
ret[retlen] = '\0'; dest[retlen] = '\0';
} }
return ret; return dest;
} }
#endif #endif
switch (char_conv_latin1ToUtf8) { switch (char_conv_latin1ToUtf8) {
case 1: case 1:
return latin1StrToUtf8Dup(string); return latin1_to_utf8(dest, string);
break;
case -1: case -1:
return utf8StrToLatin1Dup(string); return utf8_to_latin1(dest, string);
break;
} }
return NULL; return NULL;
......
...@@ -23,6 +23,6 @@ ...@@ -23,6 +23,6 @@
int setCharSetConversion(char *to, char *from); int setCharSetConversion(char *to, char *from);
char *convStrDup(char *string); char *char_conv_str(char *dest, char *string);
#endif #endif
...@@ -32,8 +32,9 @@ ...@@ -32,8 +32,9 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <errno.h> #include <errno.h>
#include "path.h"
#define MAX_STRING_SIZE MAXPATHLEN+80 #define MAX_STRING_SIZE MPD_PATH_MAX+80
#define CONF_COMMENT '#' #define CONF_COMMENT '#'
#define CONF_BLOCK_BEGIN "{" #define CONF_BLOCK_BEGIN "{"
......
...@@ -280,29 +280,28 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -280,29 +280,28 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
int ret; int ret;
InputStream inStream; InputStream inStream;
InputPlugin *plugin = NULL; InputPlugin *plugin = NULL;
char *path; char path_max_tmp[MPD_PATH_MAX];
if (isRemoteUrl(pc->utf8url)) /* not actually sure why we convert between latin/UTF8 for URLs */
path = utf8StrToLatin1Dup(pc->utf8url); if (isRemoteUrl(pc->utf8url)) {
else if (!utf8_to_latin1(path_max_tmp, pc->utf8url)) {
path = xstrdup(rmp2amp(utf8ToFsCharset(pc->utf8url)));
if (!path) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->start = 0; dc->start = 0;
return; return;
} }
} else
rmp2amp_r(path_max_tmp,
utf8_to_fs_charset(path_max_tmp, pc->utf8url));
copyMpdTagToOutputBuffer(cb, NULL); copyMpdTagToOutputBuffer(cb, NULL);
pathcpy_trunc(dc->utf8url, pc->utf8url); pathcpy_trunc(dc->utf8url, pc->utf8url);
if (openInputStream(&inStream, path) < 0) { if (openInputStream(&inStream, path_max_tmp) < 0) {
dc->error = DECODE_ERROR_FILE; dc->error = DECODE_ERROR_FILE;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->start = 0; dc->start = 0;
free(path);
return; return;
} }
...@@ -321,7 +320,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -321,7 +320,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
if (dc->stop) { if (dc->stop) {
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
dc->stop = 0; dc->stop = 0;
free(path);
return; return;
} }
...@@ -392,7 +390,8 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -392,7 +390,8 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
if (plugin->fileDecodeFunc) { if (plugin->fileDecodeFunc) {
closeInputStream(&inStream); closeInputStream(&inStream);
ret = plugin->fileDecodeFunc(cb, dc, path); ret = plugin->fileDecodeFunc(cb, dc,
path_max_tmp);
break; break;
} else if (plugin->streamDecodeFunc) { } else if (plugin->streamDecodeFunc) {
ret = plugin->streamDecodeFunc(cb, dc, &inStream); ret = plugin->streamDecodeFunc(cb, dc, &inStream);
...@@ -412,8 +411,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, ...@@ -412,8 +411,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb,
dc->stop = 0; dc->stop = 0;
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
} }
free(path);
} }
static int decoderInit(PlayerControl * pc, OutputBuffer * cb, static int decoderInit(PlayerControl * pc, OutputBuffer * cb,
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define DECODE_H #define DECODE_H
#include "../config.h" #include "../config.h"
#include "path.h"
#include "tag.h" #include "tag.h"
#include "mpd_types.h" #include "mpd_types.h"
...@@ -51,7 +52,7 @@ typedef struct _DecoderControl { ...@@ -51,7 +52,7 @@ typedef struct _DecoderControl {
volatile mpd_sint8 cycleLogFiles; volatile mpd_sint8 cycleLogFiles;
volatile double seekWhere; volatile double seekWhere;
AudioFormat audioFormat; AudioFormat audioFormat;
char utf8url[MAXPATHLEN + 1]; char utf8url[MPD_PATH_MAX];
volatile float totalTime; volatile float totalTime;
} DecoderControl; } DecoderControl;
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "path.h"
#include "locate.h" #include "locate.h"
#include "utils.h" #include "utils.h"
#define LOCATE_TAG_FILE_KEY "file" #define LOCATE_TAG_FILE_KEY "file"
...@@ -127,14 +127,14 @@ static int strstrSearchTag(Song * song, int type, char *str) ...@@ -127,14 +127,14 @@ static int strstrSearchTag(Song * song, int type, char *str)
int ret = 0; int ret = 0;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
dup = strDupToUpper(getSongUrl(song)); char path_max_tmp[MPD_PATH_MAX];
if (strstr(dup, str))
string_toupper(get_song_url(path_max_tmp, song));
if (strstr(path_max_tmp, str))
ret = 1; ret = 1;
free(dup); if (ret == 1 || type == LOCATE_TAG_FILE_TYPE)
if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) {
return ret; return ret;
} }
}
if (!song->tag) if (!song->tag)
return 0; return 0;
...@@ -173,7 +173,8 @@ static int tagItemFoundAndMatches(Song * song, int type, char *str) ...@@ -173,7 +173,8 @@ static int tagItemFoundAndMatches(Song * song, int type, char *str)
int i; int i;
if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) {
if (0 == strcmp(str, getSongUrl(song))) char path_max_tmp[MPD_PATH_MAX];
if (0 == strcmp(str, get_song_url(path_max_tmp, song)))
return 1; return 1;
if (type == LOCATE_TAG_FILE_TYPE) if (type == LOCATE_TAG_FILE_TYPE)
return 0; return 0;
......
...@@ -108,22 +108,24 @@ int lsPlaylists(int fd, char *utf8path) ...@@ -108,22 +108,24 @@ int lsPlaylists(int fd, char *utf8path)
struct dirent *ent; struct dirent *ent;
char *dup; char *dup;
char *utf8; char *utf8;
char s[MAXPATHLEN + 1]; char s[MPD_PATH_MAX];
char path_max_tmp[MPD_PATH_MAX];
List *list = NULL; List *list = NULL;
ListNode *node = NULL; ListNode *node = NULL;
char *path = utf8ToFsCharset(utf8path); char *actualPath = rpp2app_r(path_max_tmp,
char *actualPath = rpp2app(path); utf8_to_fs_charset(path_max_tmp,
utf8path));
int actlen = strlen(actualPath) + 1; int actlen = strlen(actualPath) + 1;
int maxlen = MAXPATHLEN - actlen; int maxlen = MPD_PATH_MAX - actlen;
int suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1; int suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1;
int suff; int suff;
if (actlen > MAXPATHLEN - 1 || (dir = opendir(actualPath)) == NULL) { if (actlen > MPD_PATH_MAX - 1 || (dir = opendir(actualPath)) == NULL) {
return 0; return 0;
} }
s[MAXPATHLEN] = '\0'; s[MPD_PATH_MAX - 1] = '\0';
/* this is safe, notice actlen > MAXPATHLEN-1 above */ /* this is safe, notice actlen > MPD_PATH_MAX-1 above */
strcpy(s, actualPath); strcpy(s, actualPath);
strcat(s, "/"); strcat(s, "/");
...@@ -138,16 +140,18 @@ int lsPlaylists(int fd, char *utf8path) ...@@ -138,16 +140,18 @@ int lsPlaylists(int fd, char *utf8path)
memcpy(s + actlen, ent->d_name, len); memcpy(s + actlen, ent->d_name, len);
if (stat(s, &st) == 0) { if (stat(s, &st) == 0) {
if (S_ISREG(st.st_mode)) { if (S_ISREG(st.st_mode)) {
char path_max_tmp[MPD_PATH_MAX];
if (list == NULL) if (list == NULL)
list = makeList(NULL, 1); list = makeList(NULL, 1);
dup[suff] = '\0'; dup[suff] = '\0';
if ((utf8 = fsCharsetToUtf8(dup))) { utf8 = fs_charset_to_utf8(path_max_tmp,
dup);
if (utf8)
insertInList(list, utf8, NULL); insertInList(list, utf8, NULL);
} }
} }
} }
} }
}
closedir(dir); closedir(dir);
...@@ -181,16 +185,17 @@ int lsPlaylists(int fd, char *utf8path) ...@@ -181,16 +185,17 @@ int lsPlaylists(int fd, char *utf8path)
int myStat(char *utf8file, struct stat *st) int myStat(char *utf8file, struct stat *st)
{ {
char *file = utf8ToFsCharset(utf8file); char path_max_tmp[MPD_PATH_MAX];
char *file = utf8_to_fs_charset(path_max_tmp, utf8file);
char *actualFile = file; char *actualFile = file;
if (actualFile[0] != '/') if (actualFile[0] != '/')
actualFile = rmp2amp(file); actualFile = rmp2amp_r(path_max_tmp, file);
return stat(actualFile, st); return stat(actualFile, st);
} }
static int isFile(char *utf8file, time_t * mtime) int isFile(char *utf8file, time_t * mtime)
{ {
struct stat st; struct stat st;
......
...@@ -49,4 +49,6 @@ InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next); ...@@ -49,4 +49,6 @@ InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next);
int printRemoteUrlHandlers(int fd); int printRemoteUrlHandlers(int fd);
int isFile(char *utf8file, time_t * mtime);
#endif #endif
...@@ -208,10 +208,10 @@ static void parseOptions(int argc, char **argv, Options * options) ...@@ -208,10 +208,10 @@ static void parseOptions(int argc, char **argv, Options * options)
} else if (argcLeft == 1) { } else if (argcLeft == 1) {
struct stat st; struct stat st;
char *homedir = getenv("HOME"); char *homedir = getenv("HOME");
char userfile[MAXPATHLEN + 1] = ""; char userfile[MPD_PATH_MAX] = "";
if (homedir && (strlen(homedir) + if (homedir && (strlen(homedir) +
strlen(USER_CONFIG_FILE_LOCATION)) < strlen(USER_CONFIG_FILE_LOCATION)) <
MAXPATHLEN) { MPD_PATH_MAX) {
strcpy(userfile, homedir); strcpy(userfile, homedir);
strcat(userfile, USER_CONFIG_FILE_LOCATION); strcat(userfile, USER_CONFIG_FILE_LOCATION);
} }
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#define BUFFER_LENGTH MAXPATHLEN+1024 #define BUFFER_LENGTH MPD_PATH_MAX+1024
static void blockingWrite(const int fd, const char *string, size_t len) static void blockingWrite(const int fd, const char *string, size_t len)
{ {
......
...@@ -40,39 +40,25 @@ ...@@ -40,39 +40,25 @@
const char *musicDir; const char *musicDir;
static const char *playlistDir; static const char *playlistDir;
static size_t music_dir_len;
static size_t playlist_dir_len;
static char *fsCharset; static char *fsCharset;
static char *pathConvCharset(char *to, char *from, char *str, char *ret) static char *path_conv_charset(char *dest, char *to, char *from, char *str)
{ {
if (ret) return setCharSetConversion(to, from) ? NULL : char_conv_str(dest, str);
free(ret);
return setCharSetConversion(to, from) ? NULL : convStrDup(str);
} }
char *fsCharsetToUtf8(char *str) char *fs_charset_to_utf8(char *dst, char *str)
{ {
static char *ret; char *ret = path_conv_charset(dst, "UTF-8", fsCharset, str);
return (ret && !validUtf8String(ret)) ? NULL : ret;
ret = pathConvCharset("UTF-8", fsCharset, str, ret);
if (ret && !validUtf8String(ret)) {
free(ret);
ret = NULL;
}
return ret;
} }
char *utf8ToFsCharset(char *str) char *utf8_to_fs_charset(char *dst, char *str)
{ {
static char *ret; char *ret = path_conv_charset(dst, fsCharset, "UTF-8", str);
return ret ? ret : strcpy(dst, str);
ret = pathConvCharset(fsCharset, "UTF-8", str, ret);
if (!ret)
ret = xstrdup(str);
return ret;
} }
void setFsCharset(char *charset) void setFsCharset(char *charset)
...@@ -111,23 +97,6 @@ char *getFsCharset(void) ...@@ -111,23 +97,6 @@ char *getFsCharset(void)
return fsCharset; return fsCharset;
} }
static char *appendSlash(char **path)
{
char *temp = *path;
int len = strlen(temp);
if (temp[len - 1] != '/') {
temp = xmalloc(len + 2);
memset(temp, 0, len + 2);
memcpy(temp, *path, len);
temp[len] = '/';
free(*path);
*path = temp;
}
return temp;
}
void initPaths(void) void initPaths(void)
{ {
ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1); ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1);
...@@ -138,8 +107,11 @@ void initPaths(void) ...@@ -138,8 +107,11 @@ void initPaths(void)
char *originalLocale; char *originalLocale;
DIR *dir; DIR *dir;
musicDir = appendSlash(&(musicParam->value)); musicDir = xstrdup(musicParam->value);
playlistDir = appendSlash(&(playlistParam->value)); playlistDir = xstrdup(playlistParam->value);
music_dir_len = strlen(musicDir);
playlist_dir_len = strlen(playlistDir);
if ((dir = opendir(playlistDir)) == NULL) { if ((dir = opendir(playlistDir)) == NULL) {
FATAL("cannot open %s \"%s\" (config line %i): %s\n", FATAL("cannot open %s \"%s\" (config line %i): %s\n",
...@@ -205,36 +177,35 @@ void finishPaths(void) ...@@ -205,36 +177,35 @@ void finishPaths(void)
fsCharset = NULL; fsCharset = NULL;
} }
static char *pfx_path(const char *path, const char *pfx, const size_t pfx_len) char *pfx_dir(char *dst,
const char *path, const size_t path_len,
const char *pfx, const size_t pfx_len)
{ {
static char ret[MAXPATHLEN+1]; if (mpd_unlikely((pfx_len + path_len + 1) >= MPD_PATH_MAX))
size_t rp_len = strlen(path); FATAL("Cannot prefix '%s' to '%s', PATH_MAX: %d\n",
pfx, path, MPD_PATH_MAX);
/* check for the likely condition first: */
if (mpd_likely((pfx_len + rp_len) < MAXPATHLEN)) { /* memmove allows dst == path */
memcpy(ret, pfx, pfx_len); memmove(dst + pfx_len + 1, path, path_len + 1);
memcpy(ret + pfx_len, path, rp_len + 1); memcpy(dst, pfx, pfx_len);
return ret; dst[pfx_len] = '/';
}
/* unlikely, return an empty string because truncating would /* this is weird, but directory.c can use it more safely/efficiently */
* also be wrong... break early and break loudly (the system return (dst + pfx_len + 1);
* headers are likely screwed, not mpd) */
ERROR("Cannot prefix '%s' to '%s', max: %d\n", pfx, path, MAXPATHLEN);
ret[0] = '\0';
return ret;
} }
char *rmp2amp(char *relativePath) char *rmp2amp_r(char *dst, const char *rel_path)
{ {
size_t pfx_len = strlen(musicDir); pfx_dir(dst, rel_path, strlen(rel_path),
return pfx_path(relativePath, musicDir, pfx_len); (const char *)musicDir, music_dir_len);
return dst;
} }
char *rpp2app(char *relativePath) char *rpp2app_r(char *dst, const char *rel_path)
{ {
size_t pfx_len = strlen(playlistDir); pfx_dir(dst, rel_path, strlen(rel_path),
return pfx_path(relativePath, playlistDir, pfx_len); (const char *)playlistDir, playlist_dir_len);
return dst;
} }
/* this is actually like strlcpy (OpenBSD), but we don't actually want to /* this is actually like strlcpy (OpenBSD), but we don't actually want to
...@@ -244,29 +215,28 @@ void pathcpy_trunc(char *dest, const char *src) ...@@ -244,29 +215,28 @@ void pathcpy_trunc(char *dest, const char *src)
{ {
size_t len = strlen(src); size_t len = strlen(src);
if (mpd_unlikely(len > MAXPATHLEN)) if (mpd_unlikely(len >= MPD_PATH_MAX))
len = MAXPATHLEN; len = MPD_PATH_MAX - 1;
memcpy(dest, src, len); memcpy(dest, src, len);
dest[len] = '\0'; dest[len] = '\0';
} }
char *parentPath(char *path) char *parent_path(char *path_max_tmp, const char *path)
{ {
static char parentPath[MAXPATHLEN+1];
char *c; char *c;
pathcpy_trunc(parentPath, path); pathcpy_trunc(path_max_tmp, path);
c = strrchr(parentPath,'/'); c = strrchr(path_max_tmp,'/');
if (c == NULL) if (c == NULL)
parentPath[0] = '\0'; path_max_tmp[0] = '\0';
else { else {
while ((parentPath <= c) && *(--c) == '/') /* nothing */ while ((path_max_tmp <= c) && *(--c) == '/') /* nothing */
; ;
c[1] = '\0'; c[1] = '\0';
} }
return parentPath; return path_max_tmp;
} }
char *sanitizePathDup(char *path) char *sanitizePathDup(char *path)
......
...@@ -22,6 +22,17 @@ ...@@ -22,6 +22,17 @@
#include "../config.h" #include "../config.h"
#include <sys/param.h> #include <sys/param.h>
#include <limits.h>
#if !defined(MPD_PATH_MAX)
# if defined(MAXPATHLEN)
# define MPD_PATH_MAX MAXPATHLEN
# elif defined(PATH_MAX)
# define MPD_PATH_MAX PATH_MAX
# else
# define MPD_PATH_MAX 256
# endif
#endif
extern const char *musicDir; extern const char *musicDir;
...@@ -29,33 +40,34 @@ void initPaths(void); ...@@ -29,33 +40,34 @@ void initPaths(void);
void finishPaths(void); void finishPaths(void);
/* utf8ToFsCharset() and fsCharsetToUtf8() char *fs_charset_to_utf8(char *dst, char *str);
* Each returns a static pointer to a dynamically allocated buffer
* which means: char *utf8_to_fs_charset(char *dst, char *str);
* - Do not manually free the return value of these functions, it'll be
* automatically freed the next time it is called.
* - They are not reentrant, xstrdup the return value immediately if
* you expect to call one of these functions again, but still need the
* previous result.
* - The static pointer is unique to each function.
*/
char *utf8ToFsCharset(char *str);
char *fsCharsetToUtf8(char *str);
void setFsCharset(char *charset); void setFsCharset(char *charset);
char *getFsCharset(void); char *getFsCharset(void);
/*
* pfx_dir - sets dst="$pfx/$path" and returns a pointer to path inside * dst
* this will unconditionally put a '/' between pfx and path unlike
* the static pfx_path() function in path.c
* dst is assumed to be MAXPATHLEN in size
* dst can point to the same location as path, but not pfx, which makes
* this better than sprintf(3) in some cases
*/
char *pfx_dir(char *dst,
const char *path, const size_t path_len,
const char *pfx, const size_t pfx_len);
/* relative music path to absolute music path /* relative music path to absolute music path
* char * passed is a static variable, so don't free it * char * passed is a static variable, so don't free it
*/ */
char *rmp2amp(char *file); char *rmp2amp_r(char *dst, const char *rel_path);
/* static char * returned */ char *rpp2app_r(char *dst, const char *rel_path);
char *rpp2app(char *file);
/* static char * returned */ char *parent_path(char *path_max_tmp, const char *path);
char *parentPath(char *path);
/* strips extra "///" and leading "/" and trailing "/" */ /* strips extra "///" and leading "/" and trailing "/" */
char *sanitizePathDup(char *path); char *sanitizePathDup(char *path);
......
...@@ -222,7 +222,7 @@ int playerPlay(int fd, Song * song) ...@@ -222,7 +222,7 @@ int playerPlay(int fd, Song * song)
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
pathcpy_trunc(pc->utf8url, getSongUrl(song)); get_song_url(pc->utf8url, song);
pc->play = 1; pc->play = 1;
if (playerInit() < 0) { if (playerInit() < 0) {
...@@ -337,7 +337,7 @@ int getPlayerError(void) ...@@ -337,7 +337,7 @@ int getPlayerError(void)
char *getPlayerErrorStr(void) char *getPlayerErrorStr(void)
{ {
static char *error; static char *error;
int errorlen = MAXPATHLEN + 1024; int errorlen = MPD_PATH_MAX + 1024;
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
error = xrealloc(error, errorlen); error = xrealloc(error, errorlen);
...@@ -395,7 +395,7 @@ int queueSong(Song * song) ...@@ -395,7 +395,7 @@ int queueSong(Song * song)
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
if (pc->queueState == PLAYER_QUEUE_BLANK) { if (pc->queueState == PLAYER_QUEUE_BLANK) {
pathcpy_trunc(pc->utf8url, getSongUrl(song)); get_song_url(pc->utf8url, song);
if (song->tag) if (song->tag)
pc->fileTime = song->tag->time; pc->fileTime = song->tag->time;
...@@ -454,6 +454,7 @@ void playerQueueUnlock(void) ...@@ -454,6 +454,7 @@ void playerQueueUnlock(void)
int playerSeek(int fd, Song * song, float time) int playerSeek(int fd, Song * song, float time)
{ {
PlayerControl *pc = &(getPlayerData()->playerControl); PlayerControl *pc = &(getPlayerData()->playerControl);
char path_max_tmp[MPD_PATH_MAX];
if (pc->state == PLAYER_STATE_STOP) { if (pc->state == PLAYER_STATE_STOP) {
commandError(fd, ACK_ERROR_PLAYER_SYNC, commandError(fd, ACK_ERROR_PLAYER_SYNC,
...@@ -461,7 +462,7 @@ int playerSeek(int fd, Song * song, float time) ...@@ -461,7 +462,7 @@ int playerSeek(int fd, Song * song, float time)
return -1; return -1;
} }
if (strcmp(pc->utf8url, getSongUrl(song)) != 0) { if (strcmp(pc->utf8url, get_song_url(path_max_tmp, song)) != 0) {
if (song->tag) if (song->tag)
pc->fileTime = song->tag->time; pc->fileTime = song->tag->time;
else else
...@@ -469,7 +470,7 @@ int playerSeek(int fd, Song * song, float time) ...@@ -469,7 +470,7 @@ int playerSeek(int fd, Song * song, float time)
copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk));
pathcpy_trunc(pc->utf8url, getSongUrl(song)); strcpy(pc->utf8url, path_max_tmp);
} }
if (pc->error == PLAYER_ERROR_NOERROR) { if (pc->error == PLAYER_ERROR_NOERROR) {
......
...@@ -71,9 +71,9 @@ typedef struct _PlayerControl { ...@@ -71,9 +71,9 @@ typedef struct _PlayerControl {
volatile float totalTime; volatile float totalTime;
volatile float elapsedTime; volatile float elapsedTime;
volatile float fileTime; volatile float fileTime;
char utf8url[MAXPATHLEN + 1]; char utf8url[MPD_PATH_MAX];
char currentUrl[MAXPATHLEN + 1]; char currentUrl[MPD_PATH_MAX];
char erroredUrl[MAXPATHLEN + 1]; char erroredUrl[MPD_PATH_MAX];
volatile mpd_sint8 queueState; volatile mpd_sint8 queueState;
volatile mpd_sint8 queueLockState; volatile mpd_sint8 queueLockState;
volatile mpd_sint8 lockQueue; volatile mpd_sint8 lockQueue;
......
...@@ -130,9 +130,9 @@ void initPlayerData(void) ...@@ -130,9 +130,9 @@ void initPlayerData(void)
playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED; playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED;
playerData_pd->playerControl.seek = 0; playerData_pd->playerControl.seek = 0;
playerData_pd->playerControl.closeAudio = 0; playerData_pd->playerControl.closeAudio = 0;
memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN + 1); memset(playerData_pd->playerControl.utf8url, 0, MPD_PATH_MAX);
memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN + 1); memset(playerData_pd->playerControl.erroredUrl, 0, MPD_PATH_MAX);
memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN + 1); memset(playerData_pd->playerControl.currentUrl, 0, MPD_PATH_MAX);
playerData_pd->playerControl.crossFade = crossfade; playerData_pd->playerControl.crossFade = crossfade;
playerData_pd->playerControl.softwareVolume = 1000; playerData_pd->playerControl.softwareVolume = 1000;
playerData_pd->playerControl.totalPlayTime = 0; playerData_pd->playerControl.totalPlayTime = 0;
...@@ -145,7 +145,7 @@ void initPlayerData(void) ...@@ -145,7 +145,7 @@ void initPlayerData(void)
playerData_pd->decoderControl.state = DECODE_STATE_STOP; playerData_pd->decoderControl.state = DECODE_STATE_STOP;
playerData_pd->decoderControl.seek = 0; playerData_pd->decoderControl.seek = 0;
playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR; playerData_pd->decoderControl.error = DECODE_ERROR_NOERROR;
memset(playerData_pd->decoderControl.utf8url, 0, MAXPATHLEN + 1); memset(playerData_pd->decoderControl.utf8url, 0, MPD_PATH_MAX);
} }
PlayerData *getPlayerData(void) PlayerData *getPlayerData(void)
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#define PLAYLIST_STATE_FILE_STATE_PAUSE "pause" #define PLAYLIST_STATE_FILE_STATE_PAUSE "pause"
#define PLAYLIST_STATE_FILE_STATE_STOP "stop" #define PLAYLIST_STATE_FILE_STATE_STOP "stop"
#define PLAYLIST_BUFFER_SIZE 2*MAXPATHLEN #define PLAYLIST_BUFFER_SIZE 2*MPD_PATH_MAX
#define PLAYLIST_HASH_MULT 4 #define PLAYLIST_HASH_MULT 4
...@@ -244,9 +244,11 @@ int clearStoredPlaylist(int fd, char *utf8file) ...@@ -244,9 +244,11 @@ int clearStoredPlaylist(int fd, char *utf8file)
int showPlaylist(int fd) int showPlaylist(int fd)
{ {
int i; int i;
char path_max_tmp[MPD_PATH_MAX];
for (i = 0; i < playlist.length; i++) { for (i = 0; i < playlist.length; i++) {
fdprintf(fd, "%i:%s\n", i, getSongUrl(playlist.songs[i])); fdprintf(fd, "%i:%s\n", i,
get_song_url(path_max_tmp, playlist.songs[i]));
} }
return 0; return 0;
...@@ -499,6 +501,8 @@ static void swapSongs(int song1, int song2) ...@@ -499,6 +501,8 @@ static void swapSongs(int song1, int song2)
static void queueNextSongInPlaylist(void) static void queueNextSongInPlaylist(void)
{ {
char path_max_tmp[MPD_PATH_MAX];
if (playlistQueue->numberOfNodes != 0) { if (playlistQueue->numberOfNodes != 0) {
int i; int i;
/* we need to find where in order[] is first song from queue */ /* we need to find where in order[] is first song from queue */
...@@ -511,7 +515,8 @@ static void queueNextSongInPlaylist(void) ...@@ -511,7 +515,8 @@ static void queueNextSongInPlaylist(void)
playlist.queued = i; playlist.queued = i;
DEBUG("playlist: queue song %i:\"%s\"\n", DEBUG("playlist: queue song %i:\"%s\"\n",
playlist.queued, playlist.queued,
getSongUrl(playlist. get_song_url(path_max_tmp,
playlist.
songs[playlist.order[playlist.queued]])); songs[playlist.order[playlist.queued]]));
if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < if (queueSong(playlist.songs[playlist.order[playlist.queued]]) <
...@@ -524,7 +529,8 @@ static void queueNextSongInPlaylist(void) ...@@ -524,7 +529,8 @@ static void queueNextSongInPlaylist(void)
playlist.queued = playlist.current + 1; playlist.queued = playlist.current + 1;
DEBUG("playlist: queue song %i:\"%s\"\n", DEBUG("playlist: queue song %i:\"%s\"\n",
playlist.queued, playlist.queued,
getSongUrl(playlist. get_song_url(path_max_tmp,
playlist.
songs[playlist.order[playlist.queued]])); songs[playlist.order[playlist.queued]]));
if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < if (queueSong(playlist.songs[playlist.order[playlist.queued]]) <
0) { 0) {
...@@ -539,7 +545,8 @@ static void queueNextSongInPlaylist(void) ...@@ -539,7 +545,8 @@ static void queueNextSongInPlaylist(void)
playlist.queued = 0; playlist.queued = 0;
DEBUG("playlist: queue song %i:\"%s\"\n", DEBUG("playlist: queue song %i:\"%s\"\n",
playlist.queued, playlist.queued,
getSongUrl(playlist. get_song_url(path_max_tmp,
playlist.
songs[playlist.order[playlist.queued]])); songs[playlist.order[playlist.queued]]));
if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < if (queueSong(playlist.songs[playlist.order[playlist.queued]]) <
0) { 0) {
...@@ -897,6 +904,8 @@ int stopPlaylist(int fd) ...@@ -897,6 +904,8 @@ int stopPlaylist(int fd)
static int playPlaylistOrderNumber(int fd, int orderNum) static int playPlaylistOrderNumber(int fd, int orderNum)
{ {
char path_max_tmp[MPD_PATH_MAX];
if (playerStop(fd) < 0) if (playerStop(fd) < 0)
return -1; return -1;
...@@ -906,7 +915,8 @@ static int playPlaylistOrderNumber(int fd, int orderNum) ...@@ -906,7 +915,8 @@ static int playPlaylistOrderNumber(int fd, int orderNum)
playlist_queueError = 0; playlist_queueError = 0;
DEBUG("playlist: play %i:\"%s\"\n", orderNum, DEBUG("playlist: play %i:\"%s\"\n", orderNum,
getSongUrl(playlist.songs[playlist.order[orderNum]])); get_song_url(path_max_tmp,
playlist.songs[playlist.order[orderNum]]));
if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) { if (playerPlay(fd, (playlist.songs[playlist.order[orderNum]])) < 0) {
stopPlaylist(fd); stopPlaylist(fd);
...@@ -1003,6 +1013,7 @@ static void syncCurrentPlayerDecodeMetadata(void) ...@@ -1003,6 +1013,7 @@ static void syncCurrentPlayerDecodeMetadata(void)
Song *songPlayer = playerCurrentDecodeSong(); Song *songPlayer = playerCurrentDecodeSong();
Song *song; Song *song;
int songNum; int songNum;
char path_max_tmp[MPD_PATH_MAX];
if (!songPlayer) if (!songPlayer)
return; return;
...@@ -1014,7 +1025,7 @@ static void syncCurrentPlayerDecodeMetadata(void) ...@@ -1014,7 +1025,7 @@ static void syncCurrentPlayerDecodeMetadata(void)
song = playlist.songs[songNum]; song = playlist.songs[songNum];
if (song->type == SONG_TYPE_URL && if (song->type == SONG_TYPE_URL &&
0 == strcmp(getSongUrl(song), songPlayer->url) && 0 == strcmp(get_song_url(path_max_tmp, song), songPlayer->url) &&
!mpdTagsAreEqual(song->tag, songPlayer->tag)) { !mpdTagsAreEqual(song->tag, songPlayer->tag)) {
if (song->tag) if (song->tag)
freeMpdTag(song->tag); freeMpdTag(song->tag);
...@@ -1376,7 +1387,8 @@ int shufflePlaylist(int fd) ...@@ -1376,7 +1387,8 @@ int shufflePlaylist(int fd)
int deletePlaylist(int fd, char *utf8file) int deletePlaylist(int fd, char *utf8file)
{ {
char *file = utf8ToFsCharset(utf8file); char path_max_tmp[MPD_PATH_MAX];
char *file = utf8_to_fs_charset(path_max_tmp, utf8file);
char *rfile = xmalloc(strlen(file) + strlen(".") + char *rfile = xmalloc(strlen(file) + strlen(".") +
strlen(PLAYLIST_FILE_SUFFIX) + 1); strlen(PLAYLIST_FILE_SUFFIX) + 1);
char *actualFile; char *actualFile;
...@@ -1385,7 +1397,8 @@ int deletePlaylist(int fd, char *utf8file) ...@@ -1385,7 +1397,8 @@ int deletePlaylist(int fd, char *utf8file)
strcat(rfile, "."); strcat(rfile, ".");
strcat(rfile, PLAYLIST_FILE_SUFFIX); strcat(rfile, PLAYLIST_FILE_SUFFIX);
if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile)) actualFile = rpp2app_r(path_max_tmp, rfile);
if (isPlaylist(actualFile))
free(rfile); free(rfile);
else { else {
free(rfile); free(rfile);
......
...@@ -66,9 +66,11 @@ Song *newSong(char *url, int type, Directory * parentDir) ...@@ -66,9 +66,11 @@ Song *newSong(char *url, int type, Directory * parentDir)
if (song->type == SONG_TYPE_FILE) { if (song->type == SONG_TYPE_FILE) {
InputPlugin *plugin; InputPlugin *plugin;
unsigned int next = 0; unsigned int next = 0;
char *song_url = getSongUrl(song); char path_max_tmp[MPD_PATH_MAX];
char *abs_path = rmp2amp(utf8ToFsCharset(song_url)); char *abs_path = rmp2amp_r(path_max_tmp,
while (!song->tag && (plugin = isMusic(song_url, get_song_url(path_max_tmp, song));
while (!song->tag && (plugin = isMusic(abs_path,
&(song->mtime), &(song->mtime),
next++))) { next++))) {
song->tag = plugin->tagDupFunc(abs_path); song->tag = plugin->tagDupFunc(abs_path);
...@@ -94,7 +96,6 @@ void freeJustSong(Song * song) ...@@ -94,7 +96,6 @@ void freeJustSong(Song * song)
if (song->tag) if (song->tag)
freeMpdTag(song->tag); freeMpdTag(song->tag);
free(song); free(song);
getSongUrl(NULL);
} }
SongList *newSongList(void) SongList *newSongList(void)
...@@ -231,8 +232,8 @@ static int matchesAnMpdTagItemKey(char *buffer, int *itemType) ...@@ -231,8 +232,8 @@ static int matchesAnMpdTagItemKey(char *buffer, int *itemType)
void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir)
{ {
char buffer[MAXPATHLEN + 1024]; char buffer[MPD_PATH_MAX + 1024];
int bufferSize = MAXPATHLEN + 1024; int bufferSize = MPD_PATH_MAX + 1024;
Song *song = NULL; Song *song = NULL;
ListNode *nextSongNode = list->firstNode; ListNode *nextSongNode = list->firstNode;
ListNode *nodeTemp; ListNode *nodeTemp;
...@@ -292,15 +293,16 @@ int updateSongInfo(Song * song) ...@@ -292,15 +293,16 @@ int updateSongInfo(Song * song)
if (song->type == SONG_TYPE_FILE) { if (song->type == SONG_TYPE_FILE) {
InputPlugin *plugin; InputPlugin *plugin;
unsigned int next = 0; unsigned int next = 0;
char *song_url = getSongUrl(song); char path_max_tmp[MPD_PATH_MAX];
char *abs_path = rmp2amp(song_url); char *abs_path = rmp2amp_r(path_max_tmp,
get_song_url(path_max_tmp, song));
if (song->tag) if (song->tag)
freeMpdTag(song->tag); freeMpdTag(song->tag);
song->tag = NULL; song->tag = NULL;
while (!song->tag && (plugin = isMusic(song_url, while (!song->tag && (plugin = isMusic(abs_path,
&(song->mtime), &(song->mtime),
next++))) { next++))) {
song->tag = plugin->tagDupFunc(abs_path); song->tag = plugin->tagDupFunc(abs_path);
...@@ -312,42 +314,15 @@ int updateSongInfo(Song * song) ...@@ -312,42 +314,15 @@ int updateSongInfo(Song * song)
return 0; return 0;
} }
/* pass song = NULL to reset, we do this freeJustSong(), so that if char *get_song_url(char *path_max_tmp, Song *song)
* we free and recreate this memory we make sure to print it correctly*/
char *getSongUrl(Song * song)
{ {
static char *buffer; if (!song)
static int bufferSize;
static Song *lastSong;
int slen;
int dlen;
int size;
if (!song) {
lastSong = song;
return NULL; return NULL;
}
if (!song->parentDir || !song->parentDir->path) if (!song->parentDir || !song->parentDir->path)
return song->url; strcpy(path_max_tmp, song->url);
else
/* be careful with this! */ pfx_dir(path_max_tmp, song->url, strlen(song->url),
if (song == lastSong) getDirectoryPath(song->parentDir),
return buffer; strlen(getDirectoryPath(song->parentDir)));
return path_max_tmp;
slen = strlen(song->url);
dlen = strlen(getDirectoryPath(song->parentDir));
size = slen + dlen + 2;
if (size > bufferSize) {
buffer = xrealloc(buffer, size);
bufferSize = size;
}
strcpy(buffer, getDirectoryPath(song->parentDir));
buffer[dlen] = '/';
strcpy(buffer + dlen + 1, song->url);
return buffer;
} }
...@@ -74,6 +74,6 @@ int updateSongInfo(Song * song); ...@@ -74,6 +74,6 @@ int updateSongInfo(Song * song);
void printSongUrl(int fd, Song * song); void printSongUrl(int fd, Song * song);
char *getSongUrl(Song * song); char *get_song_url(char *path_max_tmp, Song * song);
#endif #endif
...@@ -34,6 +34,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) ...@@ -34,6 +34,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd)
char *file; char *file;
char *rfile; char *rfile;
char *actualFile; char *actualFile;
static char path_max_tmp[MPD_PATH_MAX]; /* should be MT-safe */
if (strstr(utf8path, "/")) { if (strstr(utf8path, "/")) {
commandError(fd, ACK_ERROR_ARG, "playlist name \"%s\" is " commandError(fd, ACK_ERROR_ARG, "playlist name \"%s\" is "
...@@ -42,8 +43,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) ...@@ -42,8 +43,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd)
return NULL; return NULL;
} }
file = utf8ToFsCharset((char *)utf8path); file = utf8_to_fs_charset(path_max_tmp, (char *)utf8path);
rfile = xmalloc(strlen(file) + strlen(".") + rfile = xmalloc(strlen(file) + strlen(".") +
strlen(PLAYLIST_FILE_SUFFIX) + 1); strlen(PLAYLIST_FILE_SUFFIX) + 1);
...@@ -51,7 +51,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) ...@@ -51,7 +51,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd)
strcat(rfile, "."); strcat(rfile, ".");
strcat(rfile, PLAYLIST_FILE_SUFFIX); strcat(rfile, PLAYLIST_FILE_SUFFIX);
actualFile = rpp2app(rfile); actualFile = rpp2app_r(path_max_tmp, rfile);
free(rfile); free(rfile);
...@@ -100,7 +100,10 @@ static ListNode *nodeOfStoredPlaylist(StoredPlaylist *sp, int index) ...@@ -100,7 +100,10 @@ static ListNode *nodeOfStoredPlaylist(StoredPlaylist *sp, int index)
static void appendSongToStoredPlaylist(StoredPlaylist *sp, Song *song) static void appendSongToStoredPlaylist(StoredPlaylist *sp, Song *song)
{ {
insertInListWithoutKey(sp->list, xstrdup(getSongUrl(song))); char path_max_tmp[MPD_PATH_MAX];
get_song_url(path_max_tmp, song);
insertInListWithoutKey(sp->list, xstrdup(path_max_tmp));
} }
StoredPlaylist *newStoredPlaylist(const char *utf8name, int fd, int ignoreExisting) StoredPlaylist *newStoredPlaylist(const char *utf8name, int fd, int ignoreExisting)
...@@ -138,10 +141,13 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) ...@@ -138,10 +141,13 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd)
char *filename; char *filename;
StoredPlaylist *sp; StoredPlaylist *sp;
FILE *file; FILE *file;
char s[MAXPATHLEN + 1]; char s[MPD_PATH_MAX];
char path_max_tmp[MPD_PATH_MAX];
char path_max_tmp2[MPD_PATH_MAX]; /* TODO: cleanup */
char path_max_tmp3[MPD_PATH_MAX]; /* TODO: cleanup */
int slength = 0; int slength = 0;
char *temp = utf8ToFsCharset((char *)utf8path); char *temp = utf8_to_fs_charset(path_max_tmp2, (char *)utf8path);
char *parent = parentPath(temp); char *parent = parent_path(path_max_tmp3, temp);
int parentlen = strlen(parent); int parentlen = strlen(parent);
int tempInt; int tempInt;
int commentCharFound = 0; int commentCharFound = 0;
...@@ -169,15 +175,18 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) ...@@ -169,15 +175,18 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd)
s[slength] = '\0'; s[slength] = '\0';
if (s[0] == PLAYLIST_COMMENT) if (s[0] == PLAYLIST_COMMENT)
commentCharFound = 1; commentCharFound = 1;
if (strncmp(s, musicDir, strlen(musicDir)) == 0) { if (!strncmp(s, musicDir, strlen(musicDir)) &&
strcpy(s, &(s[strlen(musicDir)])); s[strlen(musicDir)] == '/') {
memmove(s, &(s[strlen(musicDir) + 1]),
strlen(&(s[strlen(musicDir) + 1])) + 1);
printf("s: <%s>\n", s);
} else if (parentlen) { } else if (parentlen) {
temp = xstrdup(s); temp = xstrdup(s);
memset(s, 0, MAXPATHLEN + 1); memset(s, 0, MPD_PATH_MAX);
strcpy(s, parent); strcpy(s, parent);
strncat(s, "/", MAXPATHLEN - parentlen); strncat(s, "/", MPD_PATH_MAX - parentlen);
strncat(s, temp, MAXPATHLEN - parentlen - 1); strncat(s, temp, MPD_PATH_MAX - parentlen - 1);
if (strlen(s) >= MAXPATHLEN) { if (strlen(s) >= MPD_PATH_MAX) {
commandError(sp->fd, commandError(sp->fd,
ACK_ERROR_PLAYLIST_LOAD, ACK_ERROR_PLAYLIST_LOAD,
"\"%s\" is too long", temp); "\"%s\" is too long", temp);
...@@ -189,7 +198,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) ...@@ -189,7 +198,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd)
free(temp); free(temp);
} }
slength = 0; slength = 0;
temp = fsCharsetToUtf8(s); temp = fs_charset_to_utf8(path_max_tmp, s);
if (temp && !commentCharFound) { if (temp && !commentCharFound) {
song = getSongFromDB(temp); song = getSongFromDB(temp);
if (song) { if (song) {
...@@ -206,7 +215,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) ...@@ -206,7 +215,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd)
freeJustSong(song); freeJustSong(song);
} }
} }
} else if (slength == MAXPATHLEN) { } else if (slength == (MPD_PATH_MAX - 1)) {
s[slength] = '\0'; s[slength] = '\0';
commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD, commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD,
"line \"%s\" in playlist \"%s\" " "line \"%s\" in playlist \"%s\" "
...@@ -401,11 +410,11 @@ static int writeStoredPlaylistToPath(StoredPlaylist *sp, const char *fspath) ...@@ -401,11 +410,11 @@ static int writeStoredPlaylistToPath(StoredPlaylist *sp, const char *fspath)
node = sp->list->firstNode; node = sp->list->firstNode;
while (node != NULL) { while (node != NULL) {
s = (char *)node->data; char path_max_tmp[MPD_PATH_MAX];
if (isValidRemoteUtf8Url(s) || !playlist_saveAbsolutePaths)
s = utf8ToFsCharset(s); s = utf8_to_fs_charset(path_max_tmp, (char *)node->data);
else if (playlist_saveAbsolutePaths && !isValidRemoteUtf8Url(s))
s = rmp2amp(utf8ToFsCharset(s)); s = rmp2amp_r(path_max_tmp, s);
fprintf(file, "%s\n", s); fprintf(file, "%s\n", s);
node = node->nextNode; node = node->nextNode;
} }
...@@ -424,6 +433,8 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song) ...@@ -424,6 +433,8 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song)
char *filename; char *filename;
FILE *file; FILE *file;
char *s; char *s;
char path_max_tmp[MPD_PATH_MAX];
char path_max_tmp2[MPD_PATH_MAX];
filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd); filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd);
if (!filename) if (!filename)
...@@ -436,10 +447,10 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song) ...@@ -436,10 +447,10 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song)
return -1; return -1;
} }
s = utf8_to_fs_charset(path_max_tmp2, get_song_url(path_max_tmp, song));
if (playlist_saveAbsolutePaths && song->type == SONG_TYPE_FILE) if (playlist_saveAbsolutePaths && song->type == SONG_TYPE_FILE)
s = rmp2amp(utf8ToFsCharset(getSongUrl(song))); s = rmp2amp_r(path_max_tmp, s);
else
s = utf8ToFsCharset(getSongUrl(song));
fprintf(file, "%s\n", s); fprintf(file, "%s\n", s);
......
...@@ -157,7 +157,8 @@ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, ...@@ -157,7 +157,8 @@ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4,
return NULL; return NULL;
} }
setCharSetConversion("UTF-8", encoding); setCharSetConversion("UTF-8", encoding);
utf8 = (id3_utf8_t *)convStrDup((char *)isostr); utf8 = xmalloc(strlen((char *)isostr) + 1);
utf8 = (id3_utf8_t *)char_conv_str((char *)utf8, (char *)isostr);
if (!utf8) { if (!utf8) {
DEBUG("Unable to convert %s string to UTF-8: " DEBUG("Unable to convert %s string to UTF-8: "
"'%s'\n", encoding, isostr); "'%s'\n", encoding, isostr);
......
...@@ -23,51 +23,42 @@ ...@@ -23,51 +23,42 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
static char *latin1ToUtf8(char c) char *latin1_to_utf8(char *dest, char *in_latin1)
{ {
static unsigned char utf8[3]; unsigned char *cp = (unsigned char *)dest;
unsigned char uc = c; unsigned char *latin1 = (unsigned char *)in_latin1;
memset(utf8, 0, 3); while (*latin1) {
if (*latin1 < 128)
if (uc < 128) *(cp++) = *latin1;
utf8[0] = uc; else {
else if (uc < 192) { if (*latin1 < 192) {
utf8[0] = 194; *(cp++) = 194;
utf8[1] = uc; *(cp++) = *latin1;
} else { } else {
utf8[0] = 195; *(cp++) = 195;
utf8[1] = uc - 64; *(cp++) = (*latin1) - 64;
}
}
++latin1;
} }
return (char *)utf8; *cp = '\0';
return dest;
} }
char *latin1StrToUtf8Dup(char *latin1) char *latin1StrToUtf8Dup(char *latin1)
{ {
/* utf8 should have at most two char's per latin1 char */ /* utf8 should have at most two char's per latin1 char */
int len = strlen(latin1) * 2 + 1; char *ret = xmalloc(strlen(latin1) * 2 + 1);
char *ret = xmalloc(len);
char *cp = ret;
char *utf8;
memset(ret, 0, len); ret = latin1_to_utf8(ret, latin1);
len = 0; return ((ret) ? xrealloc(ret, strlen((char *)ret) + 1) : NULL);
while (*latin1) {
utf8 = latin1ToUtf8(*latin1);
while (*utf8) {
*(cp++) = *(utf8++);
len++;
}
latin1++;
}
return xrealloc(ret, len + 1);
} }
static char utf8ToLatin1(char *inUtf8) static char utf8_to_latin1_char(char *inUtf8)
{ {
unsigned char c = 0; unsigned char c = 0;
unsigned char *utf8 = (unsigned char *)inUtf8; unsigned char *utf8 = (unsigned char *)inUtf8;
...@@ -124,14 +115,10 @@ int validUtf8String(char *string) ...@@ -124,14 +115,10 @@ int validUtf8String(char *string)
char *utf8StrToLatin1Dup(char *utf8) char *utf8StrToLatin1Dup(char *utf8)
{ {
/* utf8 should have at most two char's per latin1 char */ /* utf8 should have at most two char's per latin1 char */
int len = strlen(utf8) + 1; char *ret = xmalloc(strlen(utf8) + 1);
char *ret = xmalloc(len);
char *cp = ret; char *cp = ret;
int count; int count;
size_t len = 0;
memset(ret, 0, len);
len = 0;
while (*utf8) { while (*utf8) {
count = validateUtf8Char(utf8); count = validateUtf8Char(utf8);
...@@ -139,10 +126,32 @@ char *utf8StrToLatin1Dup(char *utf8) ...@@ -139,10 +126,32 @@ char *utf8StrToLatin1Dup(char *utf8)
free(ret); free(ret);
return NULL; return NULL;
} }
*(cp++) = utf8ToLatin1(utf8); *(cp++) = utf8_to_latin1_char(utf8);
utf8 += count; utf8 += count;
len++; len++;
} }
*cp = '\0';
return xrealloc(ret, len + 1); return xrealloc(ret, len + 1);
} }
char *utf8_to_latin1(char *dest, char *utf8)
{
char *cp = dest;
int count;
size_t len = 0;
while (*utf8) {
count = validateUtf8Char(utf8);
if (count) {
*(cp++) = utf8_to_latin1_char(utf8);
utf8 += count;
len++;
} else
return NULL;
}
*cp = '\0';
return dest;
}
...@@ -25,4 +25,9 @@ char *utf8StrToLatin1Dup(char *utf8); ...@@ -25,4 +25,9 @@ char *utf8StrToLatin1Dup(char *utf8);
int validUtf8String(char *string); int validUtf8String(char *string);
char *utf8_to_latin1(char *dest, char *utf8);
char *latin1_to_utf8(char *dest, char *utf8);
#endif #endif
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include <unistd.h> #include <unistd.h>
#include <assert.h> #include <assert.h>
#include <pwd.h> #include <pwd.h>
#include <signal.h>
#include <sys/param.h>
char *myFgets(char *buffer, int bufferSize, FILE * fp) char *myFgets(char *buffer, int bufferSize, FILE * fp)
{ {
...@@ -43,15 +45,21 @@ char *myFgets(char *buffer, int bufferSize, FILE * fp) ...@@ -43,15 +45,21 @@ char *myFgets(char *buffer, int bufferSize, FILE * fp)
return ret; return ret;
} }
char *strDupToUpper(char *str) char *string_toupper(char *str)
{ {
char *ret = xstrdup(str); int i = strlen(str);
int i; char *ret = str;
for (i = 0; i < strlen(str); i++) for (; --i >= 0; ++str)
ret[i] = toupper((int)ret[i]); *str = toupper((int)(*str));
return ret; return ret;
}
char *strDupToUpper(char *str)
{
return string_toupper(xstrdup(str));
} }
void stripReturnChar(char *string) void stripReturnChar(char *string)
......
...@@ -34,7 +34,9 @@ ...@@ -34,7 +34,9 @@
char *myFgets(char *buffer, int bufferSize, FILE * fp); char *myFgets(char *buffer, int bufferSize, FILE * fp);
char *strDupToUpper(char *str); char *string_toupper(char *str);
char *strDupToUpper(char *str); /* avoid, use string_toupper instead */
void stripReturnChar(char *string); void stripReturnChar(char *string);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment