summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2007-12-28 02:56:25 +0000
committerEric Wong <normalperson@yhbt.net>2007-12-28 02:56:25 +0000
commitb79f6b882a70526ec2e9fc231e0baeebdfef1e52 (patch)
tree719912135d059476070834c3c62ae940955e9e20
parent0d26248a0d8cb2e5cf6be5a438a18b16793bbb63 (diff)
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
-rw-r--r--Makefile.am4
-rw-r--r--src/Makefile.am12
-rw-r--r--src/audio.c2
-rw-r--r--src/buffer2array.c8
-rw-r--r--src/charConv.c24
-rw-r--r--src/charConv.h2
-rw-r--r--src/conf.c3
-rw-r--r--src/decode.c33
-rw-r--r--src/decode.h3
-rw-r--r--src/directory.c226
-rw-r--r--src/locate.c15
-rw-r--r--src/ls.c29
-rw-r--r--src/ls.h2
-rw-r--r--src/main.c4
-rw-r--r--src/myfprintf.c2
-rw-r--r--src/path.c118
-rw-r--r--src/path.h46
-rw-r--r--src/player.c11
-rw-r--r--src/player.h6
-rw-r--r--src/playerData.c8
-rw-r--r--src/playlist.c39
-rw-r--r--src/song.c63
-rw-r--r--src/song.h2
-rw-r--r--src/storedPlaylist.c57
-rw-r--r--src/tag.c3
-rw-r--r--src/utf8.c89
-rw-r--r--src/utf8.h5
-rw-r--r--src/utils.c18
-rw-r--r--src/utils.h4
29 files changed, 408 insertions, 430 deletions
diff --git a/Makefile.am b/Makefile.am
index 952d42762..004fae3c7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,5 +5,7 @@ docdir = $(prefix)/share/doc/$(PACKAGE)
doc_DATA = README UPGRADING
EXTRA_DIST = COPYING $(doc_DATA)
-sparse-check:
+sparse-check test:
$(MAKE) -C src $@
+
+.PHONY: sparse-check test
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;
diff --git a/src/ls.c b/src/ls.c
index 0b3f7f354..7d0421537 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -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;
diff --git a/src/ls.h b/src/ls.h
index 20f668bd9..aa34187c2 100644
--- a/src/ls.h
+++ b/src/ls.h
@@ -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);
diff --git a/src/tag.c b/src/tag.c
index 57ca14669..3761e2079 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -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);