aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
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;
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);