diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/audio.c | 2 | ||||
-rw-r--r-- | src/buffer2array.c | 8 | ||||
-rw-r--r-- | src/charConv.c | 24 | ||||
-rw-r--r-- | src/charConv.h | 2 | ||||
-rw-r--r-- | src/conf.c | 3 | ||||
-rw-r--r-- | src/decode.c | 33 | ||||
-rw-r--r-- | src/decode.h | 3 | ||||
-rw-r--r-- | src/directory.c | 226 | ||||
-rw-r--r-- | src/locate.c | 15 | ||||
-rw-r--r-- | src/ls.c | 29 | ||||
-rw-r--r-- | src/ls.h | 2 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/myfprintf.c | 2 | ||||
-rw-r--r-- | src/path.c | 118 | ||||
-rw-r--r-- | src/path.h | 46 | ||||
-rw-r--r-- | src/player.c | 11 | ||||
-rw-r--r-- | src/player.h | 6 | ||||
-rw-r--r-- | src/playerData.c | 8 | ||||
-rw-r--r-- | src/playlist.c | 39 | ||||
-rw-r--r-- | src/song.c | 63 | ||||
-rw-r--r-- | src/song.h | 2 | ||||
-rw-r--r-- | src/storedPlaylist.c | 57 | ||||
-rw-r--r-- | src/tag.c | 3 | ||||
-rw-r--r-- | src/utf8.c | 89 | ||||
-rw-r--r-- | src/utf8.h | 5 | ||||
-rw-r--r-- | src/utils.c | 18 | ||||
-rw-r--r-- | src/utils.h | 4 |
28 files changed, 405 insertions, 429 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index cf56ba1fb..653ccb824 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -151,3 +151,15 @@ sparse-check: $(SPARSE) -I. $(mpd_CFLAGS) $(SPARSE_FLAGS) $(srcdir)/$$i || exit; \ 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 diff --git a/src/audio.c b/src/audio.c index 96712d713..a2d21edd3 100644 --- a/src/audio.c +++ b/src/audio.c @@ -37,7 +37,7 @@ #define AUDIO_DEVICE_STATE "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; diff --git a/src/buffer2array.c b/src/buffer2array.c index d7bfc4561..1684bad94 100644 --- a/src/buffer2array.c +++ b/src/buffer2array.c @@ -79,48 +79,56 @@ int main() int max; b = strdup("lsinfo \"/some/dir/name \\\"test\\\"\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir/name \"test\"", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"/some/dir/name \\\"test\\\" something else\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir/name \"test\" something else", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"/some/dir\\\\name\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir\\name", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"/some/dir name\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("/some/dir name", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"\\\"/some/dir\\\"\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("\"/some/dir\"", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"\\\"/some/dir\\\" x\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("\"/some/dir\" x", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"single quote\\'d from php magicquotes\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("single quote\'d from php magicquotes", a[1]) ); assert( !a[2] ); b = strdup("lsinfo \"double quote\\\"d from php magicquotes\""); + assert(b); max = buffer2array(b, a, 4); assert( !strcmp("lsinfo", a[0]) ); assert( !strcmp("double quote\"d from php magicquotes", a[1]) ); diff --git a/src/charConv.c b/src/charConv.c index 69777c47a..71a86e7d7 100644 --- a/src/charConv.c +++ b/src/charConv.c @@ -95,26 +95,25 @@ int setCharSetConversion(char *to, char *from) return -1; } -char *convStrDup(char *string) +char *char_conv_str(char *dest, char *string) { if (!char_conv_to) return NULL; if (char_conv_same) - return xstrdup(string); + return strcpy(dest, string); #ifdef HAVE_ICONV if (char_conv_use_iconv) { + /* not optimized: */ char buffer[BUFFER_SIZE]; size_t inleft = strlen(string); - char *ret; size_t outleft; size_t retlen = 0; size_t err; char *bufferPtr; - ret = xmalloc(1); - ret[0] = '\0'; + dest[0] = '\0'; while (inleft) { bufferPtr = buffer; @@ -124,27 +123,22 @@ char *convStrDup(char *string) &outleft); if (outleft == BUFFER_SIZE || (err == -1L && errno != E2BIG)) { - free(ret); return NULL; } - - ret = xrealloc(ret, retlen + BUFFER_SIZE - outleft + 1); - memcpy(ret + retlen, buffer, BUFFER_SIZE - outleft); + memcpy(dest + retlen, buffer, BUFFER_SIZE - outleft); retlen += BUFFER_SIZE - outleft; - ret[retlen] = '\0'; + dest[retlen] = '\0'; } - return ret; + return dest; } #endif switch (char_conv_latin1ToUtf8) { case 1: - return latin1StrToUtf8Dup(string); - break; + return latin1_to_utf8(dest, string); case -1: - return utf8StrToLatin1Dup(string); - break; + return utf8_to_latin1(dest, string); } return NULL; diff --git a/src/charConv.h b/src/charConv.h index 4b1ed4237..d50e84520 100644 --- a/src/charConv.h +++ b/src/charConv.h @@ -23,6 +23,6 @@ int setCharSetConversion(char *to, char *from); -char *convStrDup(char *string); +char *char_conv_str(char *dest, char *string); #endif diff --git a/src/conf.c b/src/conf.c index 44f082acd..291ae30d2 100644 --- a/src/conf.c +++ b/src/conf.c @@ -32,8 +32,9 @@ #include <sys/types.h> #include <pwd.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_BLOCK_BEGIN "{" diff --git a/src/decode.c b/src/decode.c index ab255e3c6..79504dc94 100644 --- a/src/decode.c +++ b/src/decode.c @@ -280,29 +280,28 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, int ret; InputStream inStream; InputPlugin *plugin = NULL; - char *path; + char path_max_tmp[MPD_PATH_MAX]; - if (isRemoteUrl(pc->utf8url)) - path = utf8StrToLatin1Dup(pc->utf8url); - else - path = xstrdup(rmp2amp(utf8ToFsCharset(pc->utf8url))); - - if (!path) { - dc->error = DECODE_ERROR_FILE; - dc->state = DECODE_STATE_STOP; - dc->start = 0; - return; - } + /* not actually sure why we convert between latin/UTF8 for URLs */ + if (isRemoteUrl(pc->utf8url)) { + if (!utf8_to_latin1(path_max_tmp, pc->utf8url)) { + dc->error = DECODE_ERROR_FILE; + dc->state = DECODE_STATE_STOP; + dc->start = 0; + return; + } + } else + rmp2amp_r(path_max_tmp, + utf8_to_fs_charset(path_max_tmp, pc->utf8url)); copyMpdTagToOutputBuffer(cb, NULL); pathcpy_trunc(dc->utf8url, pc->utf8url); - if (openInputStream(&inStream, path) < 0) { + if (openInputStream(&inStream, path_max_tmp) < 0) { dc->error = DECODE_ERROR_FILE; dc->state = DECODE_STATE_STOP; dc->start = 0; - free(path); return; } @@ -321,7 +320,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, if (dc->stop) { dc->state = DECODE_STATE_STOP; dc->stop = 0; - free(path); return; } @@ -392,7 +390,8 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, if (plugin->fileDecodeFunc) { closeInputStream(&inStream); - ret = plugin->fileDecodeFunc(cb, dc, path); + ret = plugin->fileDecodeFunc(cb, dc, + path_max_tmp); break; } else if (plugin->streamDecodeFunc) { ret = plugin->streamDecodeFunc(cb, dc, &inStream); @@ -412,8 +411,6 @@ static void decodeStart(PlayerControl * pc, OutputBuffer * cb, dc->stop = 0; dc->state = DECODE_STATE_STOP; } - - free(path); } static int decoderInit(PlayerControl * pc, OutputBuffer * cb, diff --git a/src/decode.h b/src/decode.h index 09eaec416..1c93d3843 100644 --- a/src/decode.h +++ b/src/decode.h @@ -20,6 +20,7 @@ #define DECODE_H #include "../config.h" +#include "path.h" #include "tag.h" #include "mpd_types.h" @@ -51,7 +52,7 @@ typedef struct _DecoderControl { volatile mpd_sint8 cycleLogFiles; volatile double seekWhere; AudioFormat audioFormat; - char utf8url[MAXPATHLEN + 1]; + char utf8url[MPD_PATH_MAX]; volatile float totalTime; } DecoderControl; diff --git a/src/directory.c b/src/directory.c index 2a7e37def..b706b4208 100644 --- a/src/directory.c +++ b/src/directory.c @@ -35,6 +35,7 @@ #include "tagTracker.h" #include "utils.h" #include "volume.h" +#include "ls.h" #include <sys/wait.h> #include <dirent.h> @@ -296,7 +297,9 @@ static void removeSongFromDirectory(Directory * directory, char *shortname) void *song; if (findInList(directory->songs, shortname, &song)) { - LOG("removing: %s\n", getSongUrl((Song *) song)); + char path_max_tmp[MPD_PATH_MAX]; /* wasteful */ + LOG("removing: %s\n", + get_song_url(path_max_tmp, (Song *) song)); deleteFromList(directory->songs, shortname); } } @@ -359,64 +362,40 @@ static int updateInDirectory(Directory * directory, char *shortname, char *name) return 0; } +/* we don't look at hidden files nor files with newlines in them */ +static int skip_path(const char *path) +{ + return (path[0] == '.' || strchr(path, '\n')) ? 1 : 0; +} + /* return values: -1 -> error 0 -> no error, but nothing removed 1 -> no error, and stuff removed */ -static int removeDeletedFromDirectory(Directory * directory, DIR * dir) +static int removeDeletedFromDirectory(char *path_max_tmp, Directory * directory) { - char cwd[2]; - struct dirent *ent; - char *dirname = getDirectoryPath(directory); - List *entList = makeList(free, 1); - void *name; - char *s; - char *utf8; - ListNode *node; - ListNode *tmpNode; + const char *dirname = (directory && directory->path) ? + directory->path : NULL; + ListNode *node, *tmpNode; + DirectoryList *subdirs = directory->subDirectories; int ret = 0; - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; - - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) - continue; - - utf8 = fsCharsetToUtf8(ent->d_name); - - if (!utf8) - continue; - - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) - + strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - insertInList(entList, utf8, s); - } - - node = directory->subDirectories->firstNode; + node = subdirs->firstNode; while (node) { tmpNode = node->nextNode; - if (findInList(entList, node->key, &name)) { - if (!isDir((char *)name)) { - LOG("removing directory: %s\n", (char *)name); - deleteFromList(directory->subDirectories, - node->key); + if (node->key) { + if (dirname) + sprintf(path_max_tmp, "%s/%s", dirname, + node->key); + else + strcpy(path_max_tmp, node->key); + + if (!isDir(path_max_tmp)) { + LOG("removing directory: %s\n", path_max_tmp); + deleteFromList(subdirs, node->key); ret = 1; } - } else { - LOG("removing directory: %s/%s\n", - getDirectoryPath(directory), node->key); - deleteFromList(directory->subDirectories, node->key); - ret = 1; } node = tmpNode; } @@ -424,40 +403,40 @@ static int removeDeletedFromDirectory(Directory * directory, DIR * dir) node = directory->songs->firstNode; while (node) { tmpNode = node->nextNode; - if (findInList(entList, node->key, (void **)&name)) { - if (!isMusic(name, NULL, 0)) { + if (node->key) { + if (dirname) + sprintf(path_max_tmp, "%s/%s", dirname, + node->key); + else + strcpy(path_max_tmp, node->key); + + if (!isFile(path_max_tmp, NULL)) { removeSongFromDirectory(directory, node->key); ret = 1; } - } else { - removeSongFromDirectory(directory, node->key); - ret = 1; } node = tmpNode; } - freeList(entList); - return ret; } static Directory *addDirectoryPathToDB(char *utf8path, char **shortname) { + char path_max_tmp[MPD_PATH_MAX]; char *parent; Directory *parentDirectory; void *directory; - parent = xstrdup(parentPath(utf8path)); + parent = parent_path(path_max_tmp, utf8path); if (strlen(parent) == 0) parentDirectory = (void *)mp3rootDirectory; else parentDirectory = addDirectoryPathToDB(parent, shortname); - if (!parentDirectory) { - free(parent); + if (!parentDirectory) return NULL; - } *shortname = utf8path + strlen(parent); while (*(*shortname) && *(*shortname) == '/') @@ -467,10 +446,9 @@ static Directory *addDirectoryPathToDB(char *utf8path, char **shortname) (parentDirectory->subDirectories, *shortname, &directory)) { struct stat st; if (myStat(utf8path, &st) < 0 || - inodeFoundInParent(parentDirectory, st.st_ino, st.st_dev)) { - free(parent); + inodeFoundInParent(parentDirectory, st.st_ino, st.st_dev)) return NULL; - } else { + else { directory = newDirectory(utf8path, parentDirectory); insertInList(parentDirectory->subDirectories, *shortname, directory); @@ -481,34 +459,29 @@ static Directory *addDirectoryPathToDB(char *utf8path, char **shortname) with potentially the same name */ removeSongFromDirectory(parentDirectory, *shortname); - free(parent); - return (Directory *) directory; } static Directory *addParentPathToDB(char *utf8path, char **shortname) { char *parent; + char path_max_tmp[MPD_PATH_MAX]; Directory *parentDirectory; - parent = xstrdup(parentPath(utf8path)); + parent = parent_path(path_max_tmp, utf8path); if (strlen(parent) == 0) parentDirectory = (void *)mp3rootDirectory; else parentDirectory = addDirectoryPathToDB(parent, shortname); - if (!parentDirectory) { - free(parent); + if (!parentDirectory) return NULL; - } *shortname = utf8path + strlen(parent); while (*(*shortname) && *(*shortname) == '/') (*shortname)++; - free(parent); - return (Directory *) parentDirectory; } @@ -526,6 +499,7 @@ static int updatePath(char *utf8path) char *path = sanitizePathDup(utf8path); time_t mtime; int ret = 0; + char path_max_tmp[MPD_PATH_MAX]; if (NULL == path) return -1; @@ -563,7 +537,8 @@ static int updatePath(char *utf8path) else if (0 == inodeFoundInParent(parentDirectory->parent, parentDirectory->stat->inode, parentDirectory->stat->device) - && song && isMusic(getSongUrl(song), &mtime, 0)) { + && song && + isMusic(get_song_url(path_max_tmp, song), &mtime, 0)) { free(path); if (song->mtime == mtime) return 0; @@ -606,6 +581,14 @@ static int updatePath(char *utf8path) return ret; } +static const char *opendir_path(char *path_max_tmp, char *dirname) +{ + if (*dirname != '\0') + return rmp2amp_r(path_max_tmp, + utf8_to_fs_charset(path_max_tmp, dirname)); + return musicDir; +} + /* return values: -1 -> error 0 -> no error, but nothing updated @@ -614,59 +597,39 @@ static int updatePath(char *utf8path) static int updateDirectory(Directory * directory) { DIR *dir; - char cwd[2]; - struct dirent *ent; - char *s; - char *utf8; char *dirname = getDirectoryPath(directory); + struct dirent *ent; + char path_max_tmp[MPD_PATH_MAX]; int ret = 0; - { - if (!directory->stat && statDirectory(directory) < 0) { - return -1; - } else if (inodeFoundInParent(directory->parent, - directory->stat->inode, - directory->stat->device)) { - return -1; - } - } - - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; + if (!directory->stat && statDirectory(directory) < 0) + return -1; + else if (inodeFoundInParent(directory->parent, + directory->stat->inode, + directory->stat->device)) + return -1; - if ((dir = opendir(rmp2amp(utf8ToFsCharset(dirname)))) == NULL) + dir = opendir(opendir_path(path_max_tmp, dirname)); + if (!dir) return -1; - if (removeDeletedFromDirectory(directory, dir) > 0) + if (removeDeletedFromDirectory(path_max_tmp, directory) > 0) ret = 1; - rewinddir(dir); - while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) + char *utf8; + if (skip_path(ent->d_name)) continue; - utf8 = fsCharsetToUtf8(ent->d_name); - + utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name); if (!utf8) continue; - utf8 = xstrdup(utf8); - - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) + - strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - if (updateInDirectory(directory, utf8, s) > 0) + if (directory->path) + utf8 = pfx_dir(path_max_tmp, utf8, strlen(utf8), + dirname, strlen(dirname)); + if (updateInDirectory(directory, utf8, path_max_tmp) > 0) ret = 1; - free(utf8); - free(s); } closedir(dir); @@ -682,48 +645,35 @@ static int updateDirectory(Directory * directory) static int exploreDirectory(Directory * directory) { DIR *dir; - char cwd[2]; - struct dirent *ent; - char *s; - char *utf8; char *dirname = getDirectoryPath(directory); + struct dirent *ent; + char path_max_tmp[MPD_PATH_MAX]; int ret = 0; - cwd[0] = '.'; - cwd[1] = '\0'; - if (dirname == NULL) - dirname = cwd; - DEBUG("explore: attempting to opendir: %s\n", dirname); - if ((dir = opendir(rmp2amp(utf8ToFsCharset(dirname)))) == NULL) + + dir = opendir(opendir_path(path_max_tmp, dirname)); + if (!dir) return -1; DEBUG("explore: %s\n", dirname); + while ((ent = readdir(dir))) { - if (ent->d_name[0] == '.') - continue; /* hide hidden stuff */ - if (strchr(ent->d_name, '\n')) + char *utf8; + if (skip_path(ent->d_name)) continue; - utf8 = fsCharsetToUtf8(ent->d_name); - + utf8 = fs_charset_to_utf8(path_max_tmp, ent->d_name); if (!utf8) continue; - utf8 = xstrdup(utf8); - DEBUG("explore: found: %s (%s)\n", ent->d_name, utf8); - if (directory->path) { - s = xmalloc(strlen(getDirectoryPath(directory)) + - strlen(utf8) + 2); - sprintf(s, "%s/%s", getDirectoryPath(directory), utf8); - } else - s = xstrdup(utf8); - if (addToDirectory(directory, utf8, s) > 0) + if (directory->path) + utf8 = pfx_dir(path_max_tmp, utf8, strlen(utf8), + dirname, strlen(dirname)); + if (addToDirectory(directory, utf8, path_max_tmp) > 0) ret = 1; - free(utf8); - free(s); } closedir(dir); @@ -735,10 +685,8 @@ static int statDirectory(Directory * dir) { struct stat st; - if (myStat(getDirectoryPath(dir) ? getDirectoryPath(dir) : "", &st) < 0) - { + if (myStat(getDirectoryPath(dir), &st) < 0) return -1; - } dir->stat = newDirectoryStat(&st); @@ -953,8 +901,8 @@ static void writeDirectoryInfo(FILE * fp, Directory * directory) static void readDirectoryInfo(FILE * fp, Directory * directory) { - char buffer[MAXPATHLEN * 2]; - int bufferSize = MAXPATHLEN * 2; + char buffer[MPD_PATH_MAX * 2]; + int bufferSize = MPD_PATH_MAX * 2; char *key; Directory *subDirectory; int strcmpRet; diff --git a/src/locate.c b/src/locate.c index 7c3bab899..d09e68a1e 100644 --- a/src/locate.c +++ b/src/locate.c @@ -16,8 +16,8 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "path.h" #include "locate.h" - #include "utils.h" #define LOCATE_TAG_FILE_KEY "file" @@ -127,13 +127,13 @@ static int strstrSearchTag(Song * song, int type, char *str) int ret = 0; if (type == LOCATE_TAG_FILE_TYPE || type == LOCATE_TAG_ANY_TYPE) { - dup = strDupToUpper(getSongUrl(song)); - if (strstr(dup, str)) + char path_max_tmp[MPD_PATH_MAX]; + + string_toupper(get_song_url(path_max_tmp, song)); + if (strstr(path_max_tmp, str)) ret = 1; - free(dup); - if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) { + if (ret == 1 || type == LOCATE_TAG_FILE_TYPE) return ret; - } } if (!song->tag) @@ -173,7 +173,8 @@ static int tagItemFoundAndMatches(Song * song, int type, char *str) int i; 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; if (type == LOCATE_TAG_FILE_TYPE) return 0; @@ -108,22 +108,24 @@ int lsPlaylists(int fd, char *utf8path) struct dirent *ent; char *dup; char *utf8; - char s[MAXPATHLEN + 1]; + char s[MPD_PATH_MAX]; + char path_max_tmp[MPD_PATH_MAX]; List *list = NULL; ListNode *node = NULL; - char *path = utf8ToFsCharset(utf8path); - char *actualPath = rpp2app(path); + char *actualPath = rpp2app_r(path_max_tmp, + utf8_to_fs_charset(path_max_tmp, + utf8path)); int actlen = strlen(actualPath) + 1; - int maxlen = MAXPATHLEN - actlen; + int maxlen = MPD_PATH_MAX - actlen; int suflen = strlen(PLAYLIST_FILE_SUFFIX) + 1; int suff; - if (actlen > MAXPATHLEN - 1 || (dir = opendir(actualPath)) == NULL) { + if (actlen > MPD_PATH_MAX - 1 || (dir = opendir(actualPath)) == NULL) { return 0; } - s[MAXPATHLEN] = '\0'; - /* this is safe, notice actlen > MAXPATHLEN-1 above */ + s[MPD_PATH_MAX - 1] = '\0'; + /* this is safe, notice actlen > MPD_PATH_MAX-1 above */ strcpy(s, actualPath); strcat(s, "/"); @@ -138,12 +140,14 @@ int lsPlaylists(int fd, char *utf8path) memcpy(s + actlen, ent->d_name, len); if (stat(s, &st) == 0) { if (S_ISREG(st.st_mode)) { + char path_max_tmp[MPD_PATH_MAX]; if (list == NULL) list = makeList(NULL, 1); dup[suff] = '\0'; - if ((utf8 = fsCharsetToUtf8(dup))) { + utf8 = fs_charset_to_utf8(path_max_tmp, + dup); + if (utf8) insertInList(list, utf8, NULL); - } } } } @@ -181,16 +185,17 @@ int lsPlaylists(int fd, char *utf8path) 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; if (actualFile[0] != '/') - actualFile = rmp2amp(file); + actualFile = rmp2amp_r(path_max_tmp, file); return stat(actualFile, st); } -static int isFile(char *utf8file, time_t * mtime) +int isFile(char *utf8file, time_t * mtime) { struct stat st; @@ -49,4 +49,6 @@ InputPlugin *isMusic(char *utf8file, time_t * mtime, unsigned int next); int printRemoteUrlHandlers(int fd); +int isFile(char *utf8file, time_t * mtime); + #endif diff --git a/src/main.c b/src/main.c index ddfe508b6..72359820a 100644 --- a/src/main.c +++ b/src/main.c @@ -208,10 +208,10 @@ static void parseOptions(int argc, char **argv, Options * options) } else if (argcLeft == 1) { struct stat st; char *homedir = getenv("HOME"); - char userfile[MAXPATHLEN + 1] = ""; + char userfile[MPD_PATH_MAX] = ""; if (homedir && (strlen(homedir) + strlen(USER_CONFIG_FILE_LOCATION)) < - MAXPATHLEN) { + MPD_PATH_MAX) { strcpy(userfile, homedir); strcat(userfile, USER_CONFIG_FILE_LOCATION); } diff --git a/src/myfprintf.c b/src/myfprintf.c index a09ae4324..930078398 100644 --- a/src/myfprintf.c +++ b/src/myfprintf.c @@ -31,7 +31,7 @@ #include <string.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) { diff --git a/src/path.c b/src/path.c index 134a0701c..c02103331 100644 --- a/src/path.c +++ b/src/path.c @@ -40,39 +40,25 @@ const char *musicDir; static const char *playlistDir; +static size_t music_dir_len; +static size_t playlist_dir_len; 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) - free(ret); - return setCharSetConversion(to, from) ? NULL : convStrDup(str); + return setCharSetConversion(to, from) ? NULL : char_conv_str(dest, str); } -char *fsCharsetToUtf8(char *str) +char *fs_charset_to_utf8(char *dst, char *str) { - static char *ret; - - ret = pathConvCharset("UTF-8", fsCharset, str, ret); - - if (ret && !validUtf8String(ret)) { - free(ret); - ret = NULL; - } - - return ret; + char *ret = path_conv_charset(dst, "UTF-8", fsCharset, str); + return (ret && !validUtf8String(ret)) ? NULL : ret; } -char *utf8ToFsCharset(char *str) +char *utf8_to_fs_charset(char *dst, char *str) { - static char *ret; - - ret = pathConvCharset(fsCharset, "UTF-8", str, ret); - - if (!ret) - ret = xstrdup(str); - - return ret; + char *ret = path_conv_charset(dst, fsCharset, "UTF-8", str); + return ret ? ret : strcpy(dst, str); } void setFsCharset(char *charset) @@ -111,23 +97,6 @@ char *getFsCharset(void) 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) { ConfigParam *musicParam = parseConfigFilePath(CONF_MUSIC_DIR, 1); @@ -138,8 +107,11 @@ void initPaths(void) char *originalLocale; DIR *dir; - musicDir = appendSlash(&(musicParam->value)); - playlistDir = appendSlash(&(playlistParam->value)); + musicDir = xstrdup(musicParam->value); + playlistDir = xstrdup(playlistParam->value); + + music_dir_len = strlen(musicDir); + playlist_dir_len = strlen(playlistDir); if ((dir = opendir(playlistDir)) == NULL) { FATAL("cannot open %s \"%s\" (config line %i): %s\n", @@ -205,36 +177,35 @@ void finishPaths(void) 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]; - size_t rp_len = strlen(path); - - /* check for the likely condition first: */ - if (mpd_likely((pfx_len + rp_len) < MAXPATHLEN)) { - memcpy(ret, pfx, pfx_len); - memcpy(ret + pfx_len, path, rp_len + 1); - return ret; - } + if (mpd_unlikely((pfx_len + path_len + 1) >= MPD_PATH_MAX)) + FATAL("Cannot prefix '%s' to '%s', PATH_MAX: %d\n", + pfx, path, MPD_PATH_MAX); + + /* memmove allows dst == path */ + memmove(dst + pfx_len + 1, path, path_len + 1); + memcpy(dst, pfx, pfx_len); + dst[pfx_len] = '/'; - /* unlikely, return an empty string because truncating would - * also be wrong... break early and break loudly (the system - * headers are likely screwed, not mpd) */ - ERROR("Cannot prefix '%s' to '%s', max: %d\n", pfx, path, MAXPATHLEN); - ret[0] = '\0'; - return ret; + /* this is weird, but directory.c can use it more safely/efficiently */ + return (dst + pfx_len + 1); } -char *rmp2amp(char *relativePath) +char *rmp2amp_r(char *dst, const char *rel_path) { - size_t pfx_len = strlen(musicDir); - return pfx_path(relativePath, musicDir, pfx_len); + pfx_dir(dst, rel_path, strlen(rel_path), + (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); - return pfx_path(relativePath, playlistDir, pfx_len); + pfx_dir(dst, rel_path, strlen(rel_path), + (const char *)playlistDir, playlist_dir_len); + return dst; } /* 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) { size_t len = strlen(src); - if (mpd_unlikely(len > MAXPATHLEN)) - len = MAXPATHLEN; + if (mpd_unlikely(len >= MPD_PATH_MAX)) + len = MPD_PATH_MAX - 1; memcpy(dest, src, len); dest[len] = '\0'; } -char *parentPath(char *path) +char *parent_path(char *path_max_tmp, const char *path) { - static char parentPath[MAXPATHLEN+1]; char *c; - pathcpy_trunc(parentPath, path); - c = strrchr(parentPath,'/'); + pathcpy_trunc(path_max_tmp, path); + c = strrchr(path_max_tmp,'/'); if (c == NULL) - parentPath[0] = '\0'; + path_max_tmp[0] = '\0'; else { - while ((parentPath <= c) && *(--c) == '/') /* nothing */ + while ((path_max_tmp <= c) && *(--c) == '/') /* nothing */ ; c[1] = '\0'; } - return parentPath; + return path_max_tmp; } char *sanitizePathDup(char *path) diff --git a/src/path.h b/src/path.h index 2357aa25d..ef7bc62a0 100644 --- a/src/path.h +++ b/src/path.h @@ -22,6 +22,17 @@ #include "../config.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; @@ -29,33 +40,34 @@ void initPaths(void); void finishPaths(void); -/* utf8ToFsCharset() and fsCharsetToUtf8() - * Each returns a static pointer to a dynamically allocated buffer - * which means: - * - 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); +char *fs_charset_to_utf8(char *dst, char *str); + +char *utf8_to_fs_charset(char *dst, char *str); void setFsCharset(char *charset); 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 * 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(char *file); +char *rpp2app_r(char *dst, const char *rel_path); -/* static char * returned */ -char *parentPath(char *path); +char *parent_path(char *path_max_tmp, const char *path); /* strips extra "///" and leading "/" and trailing "/" */ char *sanitizePathDup(char *path); diff --git a/src/player.c b/src/player.c index 5fbf590ff..ef66229bc 100644 --- a/src/player.c +++ b/src/player.c @@ -222,7 +222,7 @@ int playerPlay(int fd, Song * song) copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); - pathcpy_trunc(pc->utf8url, getSongUrl(song)); + get_song_url(pc->utf8url, song); pc->play = 1; if (playerInit() < 0) { @@ -337,7 +337,7 @@ int getPlayerError(void) char *getPlayerErrorStr(void) { static char *error; - int errorlen = MAXPATHLEN + 1024; + int errorlen = MPD_PATH_MAX + 1024; PlayerControl *pc = &(getPlayerData()->playerControl); error = xrealloc(error, errorlen); @@ -395,7 +395,7 @@ int queueSong(Song * song) PlayerControl *pc = &(getPlayerData()->playerControl); if (pc->queueState == PLAYER_QUEUE_BLANK) { - pathcpy_trunc(pc->utf8url, getSongUrl(song)); + get_song_url(pc->utf8url, song); if (song->tag) pc->fileTime = song->tag->time; @@ -454,6 +454,7 @@ void playerQueueUnlock(void) int playerSeek(int fd, Song * song, float time) { PlayerControl *pc = &(getPlayerData()->playerControl); + char path_max_tmp[MPD_PATH_MAX]; if (pc->state == PLAYER_STATE_STOP) { commandError(fd, ACK_ERROR_PLAYER_SYNC, @@ -461,7 +462,7 @@ int playerSeek(int fd, Song * song, float time) return -1; } - if (strcmp(pc->utf8url, getSongUrl(song)) != 0) { + if (strcmp(pc->utf8url, get_song_url(path_max_tmp, song)) != 0) { if (song->tag) pc->fileTime = song->tag->time; else @@ -469,7 +470,7 @@ int playerSeek(int fd, Song * song, float time) copyMpdTagToMetadataChunk(song->tag, &(pc->fileMetadataChunk)); - pathcpy_trunc(pc->utf8url, getSongUrl(song)); + strcpy(pc->utf8url, path_max_tmp); } if (pc->error == PLAYER_ERROR_NOERROR) { diff --git a/src/player.h b/src/player.h index cf265635f..462c0b2c9 100644 --- a/src/player.h +++ b/src/player.h @@ -71,9 +71,9 @@ typedef struct _PlayerControl { volatile float totalTime; volatile float elapsedTime; volatile float fileTime; - char utf8url[MAXPATHLEN + 1]; - char currentUrl[MAXPATHLEN + 1]; - char erroredUrl[MAXPATHLEN + 1]; + char utf8url[MPD_PATH_MAX]; + char currentUrl[MPD_PATH_MAX]; + char erroredUrl[MPD_PATH_MAX]; volatile mpd_sint8 queueState; volatile mpd_sint8 queueLockState; volatile mpd_sint8 lockQueue; diff --git a/src/playerData.c b/src/playerData.c index 380e4a148..69ef56bae 100644 --- a/src/playerData.c +++ b/src/playerData.c @@ -130,9 +130,9 @@ void initPlayerData(void) playerData_pd->playerControl.queueLockState = PLAYER_QUEUE_UNLOCKED; playerData_pd->playerControl.seek = 0; playerData_pd->playerControl.closeAudio = 0; - memset(playerData_pd->playerControl.utf8url, 0, MAXPATHLEN + 1); - memset(playerData_pd->playerControl.erroredUrl, 0, MAXPATHLEN + 1); - memset(playerData_pd->playerControl.currentUrl, 0, MAXPATHLEN + 1); + memset(playerData_pd->playerControl.utf8url, 0, MPD_PATH_MAX); + memset(playerData_pd->playerControl.erroredUrl, 0, MPD_PATH_MAX); + memset(playerData_pd->playerControl.currentUrl, 0, MPD_PATH_MAX); playerData_pd->playerControl.crossFade = crossfade; playerData_pd->playerControl.softwareVolume = 1000; playerData_pd->playerControl.totalPlayTime = 0; @@ -145,7 +145,7 @@ void initPlayerData(void) playerData_pd->decoderControl.state = DECODE_STATE_STOP; playerData_pd->decoderControl.seek = 0; 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) diff --git a/src/playlist.c b/src/playlist.c index ce2748930..6d47bdb8f 100644 --- a/src/playlist.c +++ b/src/playlist.c @@ -56,7 +56,7 @@ #define PLAYLIST_STATE_FILE_STATE_PAUSE "pause" #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 @@ -244,9 +244,11 @@ int clearStoredPlaylist(int fd, char *utf8file) int showPlaylist(int fd) { int i; + char path_max_tmp[MPD_PATH_MAX]; 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; @@ -499,6 +501,8 @@ static void swapSongs(int song1, int song2) static void queueNextSongInPlaylist(void) { + char path_max_tmp[MPD_PATH_MAX]; + if (playlistQueue->numberOfNodes != 0) { int i; /* we need to find where in order[] is first song from queue */ @@ -511,8 +515,9 @@ static void queueNextSongInPlaylist(void) playlist.queued = i; DEBUG("playlist: queue song %i:\"%s\"\n", playlist.queued, - getSongUrl(playlist. - songs[playlist.order[playlist.queued]])); + get_song_url(path_max_tmp, + playlist. + songs[playlist.order[playlist.queued]])); if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < 0) { @@ -524,8 +529,9 @@ static void queueNextSongInPlaylist(void) playlist.queued = playlist.current + 1; DEBUG("playlist: queue song %i:\"%s\"\n", playlist.queued, - getSongUrl(playlist. - songs[playlist.order[playlist.queued]])); + get_song_url(path_max_tmp, + playlist. + songs[playlist.order[playlist.queued]])); if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < 0) { playlist.queued = -1; @@ -539,8 +545,9 @@ static void queueNextSongInPlaylist(void) playlist.queued = 0; DEBUG("playlist: queue song %i:\"%s\"\n", playlist.queued, - getSongUrl(playlist. - songs[playlist.order[playlist.queued]])); + get_song_url(path_max_tmp, + playlist. + songs[playlist.order[playlist.queued]])); if (queueSong(playlist.songs[playlist.order[playlist.queued]]) < 0) { playlist.queued = -1; @@ -897,6 +904,8 @@ int stopPlaylist(int fd) static int playPlaylistOrderNumber(int fd, int orderNum) { + char path_max_tmp[MPD_PATH_MAX]; + if (playerStop(fd) < 0) return -1; @@ -906,7 +915,8 @@ static int playPlaylistOrderNumber(int fd, int orderNum) playlist_queueError = 0; 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) { stopPlaylist(fd); @@ -1003,6 +1013,7 @@ static void syncCurrentPlayerDecodeMetadata(void) Song *songPlayer = playerCurrentDecodeSong(); Song *song; int songNum; + char path_max_tmp[MPD_PATH_MAX]; if (!songPlayer) return; @@ -1014,7 +1025,7 @@ static void syncCurrentPlayerDecodeMetadata(void) song = playlist.songs[songNum]; 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)) { if (song->tag) freeMpdTag(song->tag); @@ -1376,16 +1387,18 @@ int shufflePlaylist(int fd) 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(".") + - strlen(PLAYLIST_FILE_SUFFIX) + 1); + strlen(PLAYLIST_FILE_SUFFIX) + 1); char *actualFile; strcpy(rfile, file); strcat(rfile, "."); strcat(rfile, PLAYLIST_FILE_SUFFIX); - if ((actualFile = rpp2app(rfile)) && isPlaylist(actualFile)) + actualFile = rpp2app_r(path_max_tmp, rfile); + if (isPlaylist(actualFile)) free(rfile); else { free(rfile); diff --git a/src/song.c b/src/song.c index 9bcb1a0b4..1a3a78682 100644 --- a/src/song.c +++ b/src/song.c @@ -66,9 +66,11 @@ Song *newSong(char *url, int type, Directory * parentDir) if (song->type == SONG_TYPE_FILE) { InputPlugin *plugin; unsigned int next = 0; - char *song_url = getSongUrl(song); - char *abs_path = rmp2amp(utf8ToFsCharset(song_url)); - while (!song->tag && (plugin = isMusic(song_url, + char path_max_tmp[MPD_PATH_MAX]; + char *abs_path = rmp2amp_r(path_max_tmp, + get_song_url(path_max_tmp, song)); + + while (!song->tag && (plugin = isMusic(abs_path, &(song->mtime), next++))) { song->tag = plugin->tagDupFunc(abs_path); @@ -94,7 +96,6 @@ void freeJustSong(Song * song) if (song->tag) freeMpdTag(song->tag); free(song); - getSongUrl(NULL); } SongList *newSongList(void) @@ -231,8 +232,8 @@ static int matchesAnMpdTagItemKey(char *buffer, int *itemType) void readSongInfoIntoList(FILE * fp, SongList * list, Directory * parentDir) { - char buffer[MAXPATHLEN + 1024]; - int bufferSize = MAXPATHLEN + 1024; + char buffer[MPD_PATH_MAX + 1024]; + int bufferSize = MPD_PATH_MAX + 1024; Song *song = NULL; ListNode *nextSongNode = list->firstNode; ListNode *nodeTemp; @@ -292,15 +293,16 @@ int updateSongInfo(Song * song) if (song->type == SONG_TYPE_FILE) { InputPlugin *plugin; unsigned int next = 0; - char *song_url = getSongUrl(song); - char *abs_path = rmp2amp(song_url); + char path_max_tmp[MPD_PATH_MAX]; + char *abs_path = rmp2amp_r(path_max_tmp, + get_song_url(path_max_tmp, song)); if (song->tag) freeMpdTag(song->tag); song->tag = NULL; - while (!song->tag && (plugin = isMusic(song_url, + while (!song->tag && (plugin = isMusic(abs_path, &(song->mtime), next++))) { song->tag = plugin->tagDupFunc(abs_path); @@ -312,42 +314,15 @@ int updateSongInfo(Song * song) return 0; } -/* pass song = NULL to reset, we do this freeJustSong(), so that if - * we free and recreate this memory we make sure to print it correctly*/ -char *getSongUrl(Song * song) +char *get_song_url(char *path_max_tmp, Song *song) { - static char *buffer; - static int bufferSize; - static Song *lastSong; - int slen; - int dlen; - int size; - - if (!song) { - lastSong = song; + if (!song) return NULL; - } - if (!song->parentDir || !song->parentDir->path) - return song->url; - - /* be careful with this! */ - if (song == lastSong) - return buffer; - - 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; + strcpy(path_max_tmp, song->url); + else + pfx_dir(path_max_tmp, song->url, strlen(song->url), + getDirectoryPath(song->parentDir), + strlen(getDirectoryPath(song->parentDir))); + return path_max_tmp; } diff --git a/src/song.h b/src/song.h index c4100d2a2..46435efb8 100644 --- a/src/song.h +++ b/src/song.h @@ -74,6 +74,6 @@ int updateSongInfo(Song * song); void printSongUrl(int fd, Song * song); -char *getSongUrl(Song * song); +char *get_song_url(char *path_max_tmp, Song * song); #endif diff --git a/src/storedPlaylist.c b/src/storedPlaylist.c index 322cb1b5b..a166064ab 100644 --- a/src/storedPlaylist.c +++ b/src/storedPlaylist.c @@ -34,6 +34,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) char *file; char *rfile; char *actualFile; + static char path_max_tmp[MPD_PATH_MAX]; /* should be MT-safe */ if (strstr(utf8path, "/")) { commandError(fd, ACK_ERROR_ARG, "playlist name \"%s\" is " @@ -42,8 +43,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) return NULL; } - file = utf8ToFsCharset((char *)utf8path); - + file = utf8_to_fs_charset(path_max_tmp, (char *)utf8path); rfile = xmalloc(strlen(file) + strlen(".") + strlen(PLAYLIST_FILE_SUFFIX) + 1); @@ -51,7 +51,7 @@ static char *utf8pathToFsPathInStoredPlaylist(const char *utf8path, int fd) strcat(rfile, "."); strcat(rfile, PLAYLIST_FILE_SUFFIX); - actualFile = rpp2app(rfile); + actualFile = rpp2app_r(path_max_tmp, rfile); free(rfile); @@ -100,7 +100,10 @@ static ListNode *nodeOfStoredPlaylist(StoredPlaylist *sp, int index) 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) @@ -138,10 +141,13 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) char *filename; StoredPlaylist *sp; 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; - char *temp = utf8ToFsCharset((char *)utf8path); - char *parent = parentPath(temp); + char *temp = utf8_to_fs_charset(path_max_tmp2, (char *)utf8path); + char *parent = parent_path(path_max_tmp3, temp); int parentlen = strlen(parent); int tempInt; int commentCharFound = 0; @@ -169,15 +175,18 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) s[slength] = '\0'; if (s[0] == PLAYLIST_COMMENT) commentCharFound = 1; - if (strncmp(s, musicDir, strlen(musicDir)) == 0) { - strcpy(s, &(s[strlen(musicDir)])); + if (!strncmp(s, musicDir, 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) { temp = xstrdup(s); - memset(s, 0, MAXPATHLEN + 1); + memset(s, 0, MPD_PATH_MAX); strcpy(s, parent); - strncat(s, "/", MAXPATHLEN - parentlen); - strncat(s, temp, MAXPATHLEN - parentlen - 1); - if (strlen(s) >= MAXPATHLEN) { + strncat(s, "/", MPD_PATH_MAX - parentlen); + strncat(s, temp, MPD_PATH_MAX - parentlen - 1); + if (strlen(s) >= MPD_PATH_MAX) { commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD, "\"%s\" is too long", temp); @@ -189,7 +198,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) free(temp); } slength = 0; - temp = fsCharsetToUtf8(s); + temp = fs_charset_to_utf8(path_max_tmp, s); if (temp && !commentCharFound) { song = getSongFromDB(temp); if (song) { @@ -206,7 +215,7 @@ StoredPlaylist *loadStoredPlaylist(const char *utf8path, int fd) freeJustSong(song); } } - } else if (slength == MAXPATHLEN) { + } else if (slength == (MPD_PATH_MAX - 1)) { s[slength] = '\0'; commandError(sp->fd, ACK_ERROR_PLAYLIST_LOAD, "line \"%s\" in playlist \"%s\" " @@ -401,11 +410,11 @@ static int writeStoredPlaylistToPath(StoredPlaylist *sp, const char *fspath) node = sp->list->firstNode; while (node != NULL) { - s = (char *)node->data; - if (isValidRemoteUtf8Url(s) || !playlist_saveAbsolutePaths) - s = utf8ToFsCharset(s); - else - s = rmp2amp(utf8ToFsCharset(s)); + char path_max_tmp[MPD_PATH_MAX]; + + s = utf8_to_fs_charset(path_max_tmp, (char *)node->data); + if (playlist_saveAbsolutePaths && !isValidRemoteUtf8Url(s)) + s = rmp2amp_r(path_max_tmp, s); fprintf(file, "%s\n", s); node = node->nextNode; } @@ -424,6 +433,8 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song) char *filename; FILE *file; char *s; + char path_max_tmp[MPD_PATH_MAX]; + char path_max_tmp2[MPD_PATH_MAX]; filename = utf8pathToFsPathInStoredPlaylist(utf8path, fd); if (!filename) @@ -436,10 +447,10 @@ int appendSongToStoredPlaylistByPath(int fd, const char *utf8path, Song *song) 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) - s = rmp2amp(utf8ToFsCharset(getSongUrl(song))); - else - s = utf8ToFsCharset(getSongUrl(song)); + s = rmp2amp_r(path_max_tmp, s); fprintf(file, "%s\n", s); @@ -157,7 +157,8 @@ static id3_utf8_t * processID3FieldString (int is_id3v1, const id3_ucs4_t *ucs4, return NULL; } 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) { DEBUG("Unable to convert %s string to UTF-8: " "'%s'\n", encoding, isostr); diff --git a/src/utf8.c b/src/utf8.c index 2061a78de..bb62a34f7 100644 --- a/src/utf8.c +++ b/src/utf8.c @@ -23,51 +23,42 @@ #include <string.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 uc = c; - - memset(utf8, 0, 3); - - if (uc < 128) - utf8[0] = uc; - else if (uc < 192) { - utf8[0] = 194; - utf8[1] = uc; - } else { - utf8[0] = 195; - utf8[1] = uc - 64; + unsigned char *cp = (unsigned char *)dest; + unsigned char *latin1 = (unsigned char *)in_latin1; + + while (*latin1) { + if (*latin1 < 128) + *(cp++) = *latin1; + else { + if (*latin1 < 192) { + *(cp++) = 194; + *(cp++) = *latin1; + } else { + *(cp++) = 195; + *(cp++) = (*latin1) - 64; + } + } + ++latin1; } - return (char *)utf8; + *cp = '\0'; + + return dest; } char *latin1StrToUtf8Dup(char *latin1) { /* utf8 should have at most two char's per latin1 char */ - int len = strlen(latin1) * 2 + 1; - char *ret = xmalloc(len); - char *cp = ret; - char *utf8; - - memset(ret, 0, len); + char *ret = xmalloc(strlen(latin1) * 2 + 1); - len = 0; + ret = latin1_to_utf8(ret, latin1); - while (*latin1) { - utf8 = latin1ToUtf8(*latin1); - while (*utf8) { - *(cp++) = *(utf8++); - len++; - } - latin1++; - } - - return xrealloc(ret, len + 1); + return ((ret) ? xrealloc(ret, strlen((char *)ret) + 1) : NULL); } -static char utf8ToLatin1(char *inUtf8) +static char utf8_to_latin1_char(char *inUtf8) { unsigned char c = 0; unsigned char *utf8 = (unsigned char *)inUtf8; @@ -124,14 +115,10 @@ int validUtf8String(char *string) char *utf8StrToLatin1Dup(char *utf8) { /* utf8 should have at most two char's per latin1 char */ - int len = strlen(utf8) + 1; - char *ret = xmalloc(len); + char *ret = xmalloc(strlen(utf8) + 1); char *cp = ret; int count; - - memset(ret, 0, len); - - len = 0; + size_t len = 0; while (*utf8) { count = validateUtf8Char(utf8); @@ -139,10 +126,32 @@ char *utf8StrToLatin1Dup(char *utf8) free(ret); return NULL; } - *(cp++) = utf8ToLatin1(utf8); + *(cp++) = utf8_to_latin1_char(utf8); utf8 += count; len++; } + *cp = '\0'; + 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; +} diff --git a/src/utf8.h b/src/utf8.h index 0eb60d82c..05e1a4a31 100644 --- a/src/utf8.h +++ b/src/utf8.h @@ -25,4 +25,9 @@ char *utf8StrToLatin1Dup(char *utf8); int validUtf8String(char *string); +char *utf8_to_latin1(char *dest, char *utf8); + +char *latin1_to_utf8(char *dest, char *utf8); + + #endif diff --git a/src/utils.c b/src/utils.c index ea7edb4c5..e9865aa24 100644 --- a/src/utils.c +++ b/src/utils.c @@ -30,6 +30,8 @@ #include <unistd.h> #include <assert.h> #include <pwd.h> +#include <signal.h> +#include <sys/param.h> char *myFgets(char *buffer, int bufferSize, FILE * fp) { @@ -43,15 +45,21 @@ char *myFgets(char *buffer, int bufferSize, FILE * fp) return ret; } -char *strDupToUpper(char *str) +char *string_toupper(char *str) { - char *ret = xstrdup(str); - int i; + int i = strlen(str); + char *ret = str; - for (i = 0; i < strlen(str); i++) - ret[i] = toupper((int)ret[i]); + for (; --i >= 0; ++str) + *str = toupper((int)(*str)); return ret; + +} + +char *strDupToUpper(char *str) +{ + return string_toupper(xstrdup(str)); } void stripReturnChar(char *string) diff --git a/src/utils.h b/src/utils.h index 09a9bc4e8..258b725f3 100644 --- a/src/utils.h +++ b/src/utils.h @@ -34,7 +34,9 @@ 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); |