3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2006 Angel Ortega <angel@triptico.com>
6 support.c - Miscellaneous support functions
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
33 #include <sys/types.h>
42 static char ** library_path
= NULL
;
43 static int n_library_paths
= 0;
45 static char located_file
[2048];
47 /* global verbose flag */
50 /* global tracing flag */
53 /* transparent converters */
56 char * from
; /* extension from */
57 char * to
; /* extension to */
58 char * convcmd
; /* sprintf() format for converting command */
61 static struct transconv
* transconvs
= NULL
;
62 static int n_transconvs
= 0;
69 * libpath_add - Adds a directory path to the search path
70 * @path: the directory path
71 * @strip: flag to strip the upper level
73 * Adds @path to the list of searchable paths for libpath_fopen(),
74 * optionally stripping the upper level if @strip is set.
75 * The last part of the path is stripped before being stored,
76 * and duplication is avoided.
78 void libpath_add(char * path
, int strip
)
83 /* if path starts with ~, set it to $HOME */
89 if((home
= getenv("HOME")) == NULL
)
92 if((new = malloc(strlen(home
) + strlen(path
) + 2)) == NULL
)
97 strcat(new, path
+ 1);
107 /* if no directory path remains, abort */
108 if((ptr
= strrchr(path
, '/')) == NULL
)
114 /* strip the filename part */
115 if(strip
) *ptr
= '\0';
117 /* now try to find if that path is already stored */
118 for(n
= 0;n
< n_library_paths
;n
++)
120 if(strcmp(path
, library_path
[n
]) == 0)
122 /* found; free and return */
128 /* add room for the new path */
130 library_path
= (char **)realloc(library_path
,
131 n_library_paths
* sizeof(char *));
134 library_path
[n_library_paths
- 1] = path
;
139 * libpath_fopen - Opens a file, optionally searching in a path list
140 * @filename: the file name
141 * @mode: the file mode
143 * Opens a file. If the file is found as is, it's opened;
144 * otherwise, the full list of directory paths maintained by
145 * libpath_add() is searched until it's found or the
146 * end of the list is reached. Whenever a file
147 * is successfully opened, its path is also stored.
149 FILE * libpath_fopen(char * filename
, char * mode
)
155 if((f
= fopen(filename
, mode
)) != NULL
)
157 strncpy(located_file
, filename
, sizeof(located_file
));
158 located_file
[sizeof(located_file
) - 1] = '\0';
160 libpath_add(filename
, 1);
164 /* couldn't open; try concatenating all stored paths */
165 for(n
= n_library_paths
- 1;n
>= 0;n
--)
167 snprintf(located_file
, sizeof(located_file
), "%s/%s",
168 library_path
[n
], filename
);
169 located_file
[sizeof(located_file
) - 1] = '\0';
171 if((f
= fopen(located_file
, mode
)) != NULL
)
173 libpath_add(located_file
, 1);
183 * libpath_locate - Locates a file inside the path
184 * @filename: the file to be located
186 * Locates a file inside the library path maintained by libpath_fopen()
187 * and add_library_path(). If the file is found, a pointer to a static
188 * buffer containing the real path of the file is returned, or
191 char * libpath_locate(char * filename
)
195 if((f
= libpath_fopen(filename
, "r")) == NULL
)
199 return(located_file
);
203 /** transparent conversions **/
205 void transconv_add(char * from
, char * to
, char * convcmd
)
206 /* adds a converter */
208 struct transconv
* t
;
210 GROW(transconvs
, n_transconvs
, struct transconv
);
212 t
= &transconvs
[n_transconvs
++];
214 t
->from
= strdup(from
);
216 t
->convcmd
= strdup(convcmd
);
220 static char * transconv_sha_file(char * file
, char * ext
)
221 /* builds a unique cache file basename using a SHA1 hash */
223 static char c_file
[64];
224 unsigned char sha1
[20];
229 SHA1_Update(&c
, file
, strlen(file
));
230 SHA1_Update(&c
, ext
, strlen(ext
));
231 SHA1_Final(sha1
, &c
);
233 for(n
= 0;n
< sizeof(sha1
);n
++)
237 snprintf(tmp
, sizeof(tmp
), "%02x", sha1
[n
]);
238 c_file
[n
* 2] = tmp
[0];
239 c_file
[(n
* 2) + 1] = tmp
[1];
242 c_file
[n
* 2] = '\0';
247 static char * transconv_unique_file(char * file
, char * ext
, char * dir
)
248 /* builds a unique cache file name with complete path */
250 static char tmp
[2048];
251 char * c_path
= NULL
;
253 if((c_path
= getenv("TEMP")) == NULL
)
254 if((c_path
= getenv("TMP")) == NULL
)
257 /* build the directory cache name */
258 snprintf(tmp
, sizeof(tmp
), "%s/%s-%d", c_path
, dir
, getuid());
259 tmp
[sizeof(tmp
) - 1] = '\0';
261 /* create the cache directory */
265 strcat(tmp
, transconv_sha_file(file
, ext
));
272 char * transconv(char * file
, char * ext
, char * dir
)
273 /* converts using the transparent converters and the cache, if needed */
278 struct transconv
* t
;
280 /* gets this file extension */
281 if(file
== NULL
|| (this_ext
= strrchr(file
, '.')) == NULL
)
284 /* if it's already the desired type, do nothing */
285 if(strcmp(ext
, this_ext
) == 0)
288 /* get a unique name */
289 c_file
= transconv_unique_file(file
, ext
, dir
);
291 /* does the file already exist? */
292 if(access(c_file
, R_OK
) == 0)
295 /* no; look for a suitable converter */
296 for(n
= 0, t
= transconvs
;n
< n_transconvs
;n
++, t
++)
298 if(strcmp(ext
, t
->to
) == 0 && strcmp(this_ext
, t
->from
) == 0)
302 /* found a converter! just do it */
303 snprintf(tmp
, sizeof(tmp
), t
->convcmd
, c_file
, file
);
304 tmp
[sizeof(tmp
) - 1] = '\0';
307 printf("Converting: %s\n", tmp
);