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