3 Ann Hell Ex Machina - Music Software
4 Copyright (C) 2003/2008 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>
41 static char **library_path
= NULL
;
42 static int n_library_paths
= 0;
44 static char located_file
[2048];
46 /* global verbose flag */
49 /* global tracing flag */
52 /* transparent converters */
54 const char *from
; /* extension from */
55 const char *to
; /* extension to */
56 const char *convcmd
; /* sprintf() format for converting command */
59 static struct transconv
*transconvs
= NULL
;
60 static int n_transconvs
= 0;
66 * libpath_add - Adds a directory path to the search path
67 * @path: the directory path
68 * @strip: flag to strip the upper level
70 * Adds @path to the list of searchable paths for libpath_fopen(),
71 * optionally stripping the upper level if @strip is set.
72 * The last part of the path is stripped before being stored,
73 * and duplication is avoided.
75 void libpath_add(const char *path
, int strip
)
81 /* if path starts with ~, set it to $HOME */
86 if ((home
= getenv("HOME")) == NULL
)
89 if ((new = malloc(strlen(home
) + strlen(path
) + 2)) == NULL
)
94 strcat(new, path
+ 1);
103 /* if no directory path remains, abort */
104 if ((ptr
= strrchr(p
, '/')) == NULL
) {
109 /* strip the filename part */
113 /* now try to find if that path is already stored */
114 for (n
= 0; n
< n_library_paths
; n
++) {
115 if (strcmp(p
, library_path
[n
]) == 0) {
116 /* found; free and return */
122 /* add room for the new path */
125 (char **) realloc(library_path
, n_library_paths
* sizeof(char *));
128 library_path
[n_library_paths
- 1] = p
;
133 * libpath_fopen - Opens a file, optionally searching in a path list
134 * @filename: the file name
135 * @mode: the file mode
137 * Opens a file. If the file is found as is, it's opened;
138 * otherwise, the full list of directory paths maintained by
139 * libpath_add() is searched until it's found or the
140 * end of the list is reached. Whenever a file
141 * is successfully opened, its path is also stored.
143 FILE *libpath_fopen(const char *filename
, const char *mode
)
149 if ((f
= fopen(filename
, mode
)) != NULL
) {
150 strncpy(located_file
, filename
, sizeof(located_file
));
151 located_file
[sizeof(located_file
) - 1] = '\0';
153 libpath_add(filename
, 1);
157 /* couldn't open; try concatenating all stored paths */
158 for (n
= n_library_paths
- 1; n
>= 0; n
--) {
159 snprintf(located_file
, sizeof(located_file
), "%s/%s",
160 library_path
[n
], filename
);
161 located_file
[sizeof(located_file
) - 1] = '\0';
163 if ((f
= fopen(located_file
, mode
)) != NULL
) {
164 libpath_add(located_file
, 1);
174 * libpath_locate - Locates a file inside the path
175 * @filename: the file to be located
177 * Locates a file inside the library path maintained by libpath_fopen()
178 * and add_library_path(). If the file is found, a pointer to a static
179 * buffer containing the real path of the file is returned, or
182 char *libpath_locate(const char *filename
)
186 if ((f
= libpath_fopen(filename
, "r")) == NULL
)
195 * libpath_print - Prints the library path
197 * Prints the library path.
199 void libpath_print(void)
203 for (n
= 0; n
< n_library_paths
; n
++) {
207 printf("%s", library_path
[n
]);
211 /** transparent conversions **/
213 void transconv_add(const char *from
, const char *to
, const char *convcmd
)
214 /* adds a converter */
218 GROW(transconvs
, n_transconvs
, struct transconv
);
220 t
= &transconvs
[n_transconvs
++];
222 t
->from
= strdup(from
);
224 t
->convcmd
= strdup(convcmd
);
228 static char *transconv_sha_file(const char *file
, const char *ext
)
229 /* builds a unique cache file basename using a SHA1 hash */
231 static char c_file
[64];
232 unsigned char sha1
[20];
237 SHA1_Update(&c
, (char *) file
, strlen(file
));
238 SHA1_Update(&c
, (char *) ext
, strlen(ext
));
239 SHA1_Final(sha1
, &c
);
241 for (n
= 0; n
< sizeof(sha1
); n
++) {
244 snprintf(tmp
, sizeof(tmp
), "%02x", sha1
[n
]);
245 c_file
[n
* 2] = tmp
[0];
246 c_file
[(n
* 2) + 1] = tmp
[1];
249 c_file
[n
* 2] = '\0';
254 static char *transconv_unique_file(const char *file
, const char *ext
,
256 /* builds a unique cache file name with complete path */
258 static char tmp
[2048];
261 if ((c_path
= getenv("TEMP")) == NULL
)
262 if ((c_path
= getenv("TMP")) == NULL
)
265 /* build the directory cache name */
266 snprintf(tmp
, sizeof(tmp
), "%s/%s-%d", c_path
, dir
, getuid());
267 tmp
[sizeof(tmp
) - 1] = '\0';
269 /* create the cache directory */
270 #if CONFOPT_MKDIR_ARGS == 2
277 strcat(tmp
, transconv_sha_file(file
, ext
));
284 char *transconv_pipe(const char *cmd
, const char *ext
, const char *dir
)
285 /* executes cmd as a pipe */
287 char *c_file
= transconv_unique_file(cmd
, ext
, dir
);
289 /* does the file already exist? */
290 if (access(c_file
, R_OK
)) {
293 snprintf(tmp
, sizeof(tmp
), cmd
, c_file
);
294 tmp
[sizeof(tmp
) - 1] = '\0';
297 printf("Converting: %s\n", tmp
);
306 char *transconv(const char *file
, const char *ext
, const char *dir
)
307 /* converts using the transparent converters and the cache, if needed */
314 /* gets this file extension */
315 if (file
== NULL
|| (this_ext
= strrchr(file
, '.')) == NULL
)
318 /* if it's already the desired type, do nothing */
319 if (strcmp(ext
, this_ext
) == 0)
320 return (char *) file
;
322 /* get a unique name */
323 c_file
= transconv_unique_file(file
, ext
, dir
);
325 /* does the file already exist? */
326 if (access(c_file
, R_OK
) == 0)
329 /* no; look for a suitable converter */
330 for (n
= 0, t
= transconvs
; n
< n_transconvs
; n
++, t
++) {
331 if (strcmp(t
->from
, ".*") == 0 ||
332 (strcmp(ext
, t
->to
) == 0 && strcmp(this_ext
, t
->from
) == 0)) {
335 /* found a converter! just do it */
336 snprintf(tmp
, sizeof(tmp
), t
->convcmd
, c_file
, file
);
337 tmp
[sizeof(tmp
) - 1] = '\0';
340 printf("Executing: %s\n", tmp
);
342 if (system(tmp
) == 0)