1 /***********************************************************************
2  *    msdllib.c:  utility functions
3  ***********************************************************************
4  * Copyright (C) 2007 metro <me_t_ro@yahoo.com>
5  *
6  * This file is part of msdl, media stream downloader
7  *
8  * utility functions.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *
25  ***********************************************************************/
26 
27 
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <unistd.h>
36 
37 #include "msdl.h"
38 #include "msdllib.h"
39 #include "network.h"
40 #include "display.h"
41 
42 
43 
44 /* ignore case strchr */
xstrcasechr(const char * s1,int c)45 char *xstrcasechr(const char *s1,int c)
46 {
47     const char *hey = s1;
48     int ch = tolower(c);
49     if(!c) {
50 	return (char *)(s1 + strlen(s1));
51     }
52 
53     for(;*hey && tolower(*hey) != ch;hey++);
54     if(*hey) {
55 	return (char *)hey;
56     }
57 
58     return NULL;
59 }
60 
61 /* strstr */
xstrstr(const char * s1,const char * s2)62 char *xstrstr(const char *s1,const char *s2)
63 {
64     const char *hey = s1;
65     const size_t len = strlen(s2);
66     if(len) {
67 	for(;(hey = strchr(hey,*s2)) != 0;hey++) {
68 	    if(!strncmp(hey,s2,len)) {
69 		return (char *)hey;
70 	    }
71 	}
72     }
73     return (char *)hey;
74 }
75 
76 /* ignor case strstr */
xstrcasestr(const char * s1,const char * s2)77 char *xstrcasestr(const char *s1,const char *s2)
78 {
79     const char *hey = s1;
80     const size_t len = strlen(s2);
81     if(len) {
82 	for(;(hey = xstrcasechr(hey,*s2)) != 0;hey++) {
83 	    if(!strncasecmp(hey,s2,len)) {
84 		return (char *)hey;
85 	    }
86 	}
87     }
88     return (char *)hey;
89 }
90 
91 
92 
93 
94 /*
95  * malloc() wrapper
96  */
xmalloc(const size_t size)97 void *xmalloc(const size_t size)
98 {
99     void *p = malloc(size);
100     if(!p) {
101 	fatal_error("could not allocate memory\n");
102     }
103     memset(p,0,size);
104     return p;
105 }
106 
107 
108 
109 /*
110  * realloc() wrapper
111  */
xrealloc(void * p,const size_t size)112 void *xrealloc(void *p,const size_t size)
113 {
114     p = realloc(p,size);
115     if(!p) {
116 	fatal_error("could not reallocate memory\n");
117     }
118     return p;
119 }
120 
121 
122 /*
123  * list manipulation functions
124  * new, append, search and free
125  */
new_list_h(void * p)126 struct list_h *new_list_h(void *p)
127 {
128     struct list_h *newl = xmalloc(sizeof(struct list_h));
129     newl->p = p;
130     newl->next = NULL;
131     newl->prev = NULL;
132     return newl;
133 }
134 
135 
136 /*
137  * append 'p' to 'list'
138  */
list_h_append(struct list_h ** list,void * p)139 struct list_h *list_h_append(struct list_h **list,void *p)
140 {
141     /* non-recursive method for fast append */
142     struct list_h **cur,**prev;
143 
144     for(cur = prev = list ; *cur ; prev = cur,cur = &((*cur)->next));
145     /* now *cur points to NULL */
146     *cur = new_list_h(p);
147     (*cur)->next = NULL;
148     (*cur)->prev = *prev; /* if first element, prev is itself*/
149 
150     return *cur;
151 }
152 
153 
154 
155 /*
156  * free first one element of the list, works like queue.
157  * return value: new list.
158  * do    newone = list_h_free_head(oldone,p,free); etc.
159  */
list_h_free_head(struct list_h ** list,void (* free_er)(void *))160 struct list_h *list_h_free_head(struct list_h **list,void (*free_er)(void *))
161 {
162     struct list_h *del = *list;
163     if(del == NULL) {
164 	return NULL; /* do nothing, just return */
165     }
166 
167     *list = (*list)->next;
168 
169     free_er(del->p);
170     free(del);
171 
172     return *list;
173 }
174 
175 
176 
177 /*
178  * count elements in list_h
179  */
list_h_num(struct list_h * list)180 int list_h_num(struct list_h *list)
181 {
182     int num;
183 
184     for(num = 0; list ; list = list->next) num++;
185     return num;
186 }
187 
188 
189 
190 /*
191  * search list_h, using 'comp' function.
192  */
search_list_h(struct list_h * list,void * p,int (* comp)(void *,void *))193 struct list_h *search_list_h(struct list_h *list,void *p,
194 			     int (*comp)(void *,void *))
195 {
196     struct list_h *iter;
197     if(list == NULL) return NULL;
198 
199     /* non-recursive */
200     for(iter = list ; iter ; iter = iter->next) {
201 	if(!comp(iter->p,p))
202 	    break;
203     }
204 
205     return iter;
206 }
207 
208 
free_list_h(struct list_h * list,void (* free_er)(void *))209 void free_list_h(struct list_h *list,void (*free_er)(void *))
210 {
211     struct list_h *cur,*next;
212     if(list == NULL) return;
213 
214     /* non-recursive */
215     for(cur = list ; cur ; cur = next) {
216 	next = cur->next;
217 	free_er(cur->p);
218 	free(cur);
219     }
220 }
221 
222 
223 
224 /* only4string debuginfo function */
print_list_h(struct list_h * list)225 void print_list_h(struct list_h *list)
226 {
227     if(list == NULL) return;
228 
229     printf("%s\n",(char *)list->p);
230     print_list_h(list->next);
231 }
232 
233 
234 /*
235  * file utils
236  */
237 
238 
239 /*
240  * get file size
241  * return value 1 ... success
242  *             -1 ... failed
243  */
get_filesize(const char * path,uint64_t * size)244 int get_filesize(const char *path,uint64_t *size)
245 {
246     if(!path) {
247 	goto failed;
248     }
249 
250     struct stat s;
251     if(stat(path,&s) < 0) {
252 	display(MSDL_ERR,"get_filesize %s: stat() error\n",path);
253 	perror("");
254 	goto failed;
255     }
256 
257     *size = (uint64_t)s.st_size;
258     return 1;
259 
260   failed:
261     *size = 0;
262     return -1;
263 }
264 
get_line(char ** lineptr,size_t * n,FILE * fp)265 ssize_t get_line(char **lineptr,size_t *n,FILE *fp)
266 {
267     return (get_delim(lineptr,n,'\n',fp));
268 }
269 
270 
271 
272 /*
273  *  return value    read bytes ... bytes in lineptr (not including '\0' at the end)
274  *                          -1 ... failed / EOF
275  */
get_delim(char ** lineptr,size_t * n,int delim,FILE * fp)276 ssize_t get_delim(char **lineptr,size_t *n,int delim,FILE *fp)
277 {
278     size_t cursize = 0;
279 
280     if(lineptr == NULL || n == NULL || fp == NULL) {
281 	display(MSDL_ERR,"wrong arg to get_delim\n");
282 	return -1;
283     }
284 
285     if(*lineptr == NULL || *n == 0) { /* has to allocate buffer */
286 	*n = BUFSIZE_1K;
287 	*lineptr = (char *)xmalloc(*n);
288 	if(*lineptr == NULL) {
289 	    return -1;
290 	}
291     }
292 
293     for(;;) {
294 	int i = fgetc(fp);
295 
296 	if(cursize + 1 >= *n) { /* buffer must be longer */
297 	    char *newptr = NULL;
298 	    *n += BUFSIZE_1K;
299 	    newptr = xrealloc(*lineptr,*n);
300 	    if(!newptr) {
301 		return -1;
302 	    }
303 	    *lineptr = newptr;
304 	}
305 
306 	if(i == EOF) { /* failed to get char (EOF or error )*/
307 	    if(!cursize) {
308 		return -1;
309 	    }
310 
311 	    (*lineptr)[cursize] = '\0';
312 	    return cursize;
313 	}
314 
315 	(*lineptr)[cursize] = i;
316 	cursize++;
317 	if(i == delim) {
318 	    break;
319 	}
320     }
321 
322     (*lineptr)[cursize] = '\0';
323     return cursize;
324 }
325 
326 
327 
328 
dbgdump(const void * str,int size)329 void dbgdump(const void *str,int size)
330 {
331     if(get_current_loglevel() == MSDL_DBG) {
332 	int i = 0;
333 	for(; i < size ; i++) {
334 	    display(MSDL_DBG,"%02x ",((unsigned char *)str)[i]);
335 	    if(i % 16 == 15) {
336 		int j = i - 15;
337 		display(MSDL_DBG,"    |");
338 		for(; j <= i ; j++ ) {
339 		    char c = ((char *)str)[j];
340 		    if(isprint(c)) display(MSDL_DBG,"%c",c);
341 		    else           display(MSDL_DBG," ");
342 		}
343 		display(MSDL_DBG,"|\n");
344 	    }
345 	}
346     }
347 }
348