1 /* MiniDLNA media server
2 * Copyright (C) 2008-2009 Justin Maggard
4 * This file is part of MiniDLNA.
6 * MiniDLNA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * MiniDLNA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
22 #include <linux/limits.h>
25 #include <sys/types.h>
30 #include "minidlnatypes.h"
31 #include "upnpglobalvars.h"
35 strcatf(struct string_s
*str
, const char *fmt
, ...)
41 ret
= vsnprintf(str
->data
+ str
->off
, str
->size
- str
->off
, fmt
, ap
);
49 ends_with(const char * haystack
, const char * needle
)
52 int nlen
= strlen(needle
);
53 int hlen
= strlen(haystack
);
57 end
= haystack
+ hlen
- nlen
;
59 return (strcasecmp(end
, needle
) ? 0 : 1);
68 for (i
=0; i
<= strlen(str
) && (isspace(str
[i
]) || str
[i
] == '"'); i
++) {
71 for (i
=(strlen(str
)-1); i
>= 0 && (isspace(str
[i
]) || str
[i
] == '"'); i
--) {
77 /* Find the first occurrence of p in s, where s is terminated by t */
79 strstrc(const char *s
, const char *p
, const char t
)
84 endptr
= strchr(s
, t
);
92 if (*s
== *p
&& strncmp(s
+1, p
+1, plen
-1) == 0)
102 modifyString(char * string
, const char * before
, const char * after
, short like
)
104 int oldlen
, newlen
, chgcnt
= 0;
107 oldlen
= strlen(before
);
108 newlen
= strlen(after
);
109 if( newlen
+like
> oldlen
)
112 while( (p
= strstr(s
, before
)) )
117 s
= realloc(string
, strlen(string
)+((newlen
-oldlen
)*chgcnt
)+1+like
);
118 /* If we failed to realloc, return the original alloc'd string */
128 p
= strcasestr(s
, before
);
131 memmove(p
+ newlen
, p
+ oldlen
, strlen(p
+ oldlen
) + 1);
132 memcpy(p
, after
, newlen
);
142 memmove(t
+2, t
+1, strlen(t
+1)+1);
147 memmove(t
+1, t
, strlen(t
)+1);
158 escape_tag(const char *tag
, int force_alloc
)
160 char *esc_tag
= NULL
;
162 if( strchr(tag
, '&') || strchr(tag
, '<') || strchr(tag
, '>') )
164 esc_tag
= strdup(tag
);
165 esc_tag
= modifyString(esc_tag
, "&", "&amp;", 0);
166 esc_tag
= modifyString(esc_tag
, "<", "&lt;", 0);
167 esc_tag
= modifyString(esc_tag
, ">", "&gt;", 0);
169 else if( force_alloc
)
170 esc_tag
= strdup(tag
);
176 strip_ext(char * name
)
180 period
= strrchr(name
, '.');
185 /* Code basically stolen from busybox */
187 make_dir(char * path
, mode_t mode
)
196 /* Bypass leading non-'/'s and then subsequent '/'s. */
202 c
= *s
; /* Save the current char */
203 *s
= 0; /* and replace it with nul. */
209 if (mkdir(path
, mode
) < 0) {
210 /* If we failed for any other reason than the directory
211 * already exists, output a diagnostic and return -1.*/
213 || (stat(path
, &st
) < 0 || !S_ISDIR(st
.st_mode
))) {
220 /* Remove any inserted nul from the path. */
225 DPRINTF(E_WARN
, L_GENERAL
, "make_dir: cannot create directory '%s'\n", path
);
230 is_video(const char * file
)
232 return (ends_with(file
, ".mpg") || ends_with(file
, ".mpeg") ||
233 ends_with(file
, ".avi") || ends_with(file
, ".divx") ||
234 ends_with(file
, ".asf") || ends_with(file
, ".wmv") ||
235 ends_with(file
, ".mp4") || ends_with(file
, ".m4v") ||
236 ends_with(file
, ".mts") || ends_with(file
, ".m2ts") ||
237 ends_with(file
, ".m2t") || ends_with(file
, ".mkv") ||
238 ends_with(file
, ".vob") || ends_with(file
, ".ts") ||
239 ends_with(file
, ".flv") || ends_with(file
, ".xvid") ||
241 ends_with(file
, ".TiVo") ||
243 ends_with(file
, ".mov") || ends_with(file
, ".3gp"));
247 is_audio(const char * file
)
249 return (ends_with(file
, ".mp3") || ends_with(file
, ".flac") ||
250 ends_with(file
, ".wma") || ends_with(file
, ".asf") ||
251 ends_with(file
, ".fla") || ends_with(file
, ".flc") ||
252 ends_with(file
, ".m4a") || ends_with(file
, ".aac") ||
253 ends_with(file
, ".mp4") || ends_with(file
, ".m4p") ||
254 ends_with(file
, ".wav") || ends_with(file
, ".ogg") ||
255 ends_with(file
, ".pcm") || ends_with(file
, ".3gp"));
259 is_image(const char * file
)
261 return (ends_with(file
, ".jpg") || ends_with(file
, ".jpeg"));
265 is_playlist(const char * file
)
267 return (ends_with(file
, ".m3u") || ends_with(file
, ".pls"));
271 is_album_art(const char * name
)
273 struct album_art_name_s
* album_art_name
;
275 /* Check if this file name matches one of the default album art names */
276 for( album_art_name
= album_art_names
; album_art_name
; album_art_name
= album_art_name
->next
)
278 if( album_art_name
->wildcard
)
280 if( strncmp(album_art_name
->name
, name
, strlen(album_art_name
->name
)) == 0 )
285 if( strcmp(album_art_name
->name
, name
) == 0 )
290 return (album_art_name
? 1 : 0);
294 resolve_unknown_type(const char * path
, enum media_types dir_type
)
297 unsigned char type
= TYPE_UNKNOWN
;
298 char str_buf
[PATH_MAX
];
301 if( lstat(path
, &entry
) == 0 )
303 if( S_ISLNK(entry
.st_mode
) )
305 if( (len
= readlink(path
, str_buf
, PATH_MAX
-1)) > 0 )
308 //DEBUG DPRINTF(E_DEBUG, L_GENERAL, "Checking for recursive symbolic link: %s (%s)\n", path, str_buf);
309 if( strncmp(path
, str_buf
, strlen(str_buf
)) == 0 )
311 DPRINTF(E_DEBUG
, L_GENERAL
, "Ignoring recursive symbolic link: %s (%s)\n", path
, str_buf
);
318 if( S_ISDIR(entry
.st_mode
) )
322 else if( S_ISREG(entry
.st_mode
) )
327 if( is_image(path
) ||
334 if( is_audio(path
) ||
360 flag
= fopen("/ramfs/.upnp-av_scan", "w");
364 mkdir("/var/notice", 0755);
365 flag
= fopen("/var/notice/dlna", "w");
368 fprintf(flag
, "Scan in progress");
378 if( access("/ramfs/.rescan_done", F_OK
) == 0 )
379 system("/bin/sh /ramfs/.rescan_done");
380 unlink("/ramfs/.upnp-av_scan");
382 unlink("/var/notice/dlna");