Rebuild binary when our libraries have changed.
[mediadatabase.git] / libfrontend / disk.c
blobfae5cabb1e094ad10c7d4a2afc25ed2156bb0ffc
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * $Id: disk.c,v 1.2 2004/05/21 23:42:49 nedko Exp $
6 * DESCRIPTION:
7 * Mediadatabase disk handling.
9 * AUTHOR:
10 * Nedko Arnaudov <nedko@users.sourceforge.net>
12 * LICENSE:
13 * GNU GENERAL PUBLIC LICENSE version 2
15 *****************************************************************************/
17 #include <stdlib.h>
18 #include <string.h>
19 #include <dirent.h>
20 #include <sys/stat.h>
21 #include <errno.h>
22 #include <sys/wait.h>
24 #include "../result.h"
25 #include "../libdb/libdb.h"
26 #include "disk.h"
27 #include "error.h"
28 #include "../libdb/memory.h"
30 #if defined(OPENBSD)
31 #define DEFAULT_MOUNT_CMD "sudo /sbin/mount /cdrom"
32 #define DEFAULT_UNMOUNT_CMD "sudo /sbin/umount /cdrom"
33 #else
34 #define DEFAULT_MOUNT_CMD "/bin/mount /cdrom"
35 #define DEFAULT_UNMOUNT_CMD "/bin/umount /cdrom"
36 #endif
37 #define DEFAULT_MOUNTDIR "/cdrom"
38 #define MAX_PATH_DEPTH 65535
40 char *g_pszDiskPath = NULL;
41 int g_blnMediaMounted = 0;
42 char *g_pszMountCommand = NULL;
43 char *g_pszUnmountCommand = NULL;
45 struct scan_context
47 disk_scan_callback pCallback;
48 void *pUserContext;
49 char *pszPathBuffer;
50 size_t nPathBufferSize;
51 size_t nDiskPathPrefixLength;
52 unsigned long nTotalFiles;
53 unsigned long long nTotalSize;
56 mediadb_result
57 disk_set_path(const char *pszDiskPath)
59 if (g_pszDiskPath != NULL)
61 free(g_pszDiskPath);
64 g_pszDiskPath = strdup(pszDiskPath);
66 if (g_pszDiskPath == NULL)
68 mediadb_error_callback(
69 MEDIADB_ERROR_CRITICAL,
70 "Out of memory.");
71 return MEDIADB_MEM;
74 return MEDIADB_OK;
77 const char *
78 disk_get_path()
80 return g_pszDiskPath;
83 mediadb_result
84 disk_set_mount_command(const char *pszMountCommand)
86 if (g_pszMountCommand != NULL)
88 free(g_pszMountCommand);
91 g_pszMountCommand = strdup(pszMountCommand);
93 if (g_pszMountCommand == NULL)
95 mediadb_error_callback(
96 MEDIADB_ERROR_CRITICAL,
97 "Out of memory.");
98 return MEDIADB_MEM;
101 return MEDIADB_OK;
104 const char *
105 disk_get_mount_command()
107 return g_pszMountCommand;
110 mediadb_result
111 disk_set_unmount_command(const char *pszUnmountCommand)
113 if (g_pszUnmountCommand != NULL)
115 free(g_pszUnmountCommand);
118 g_pszUnmountCommand = strdup(pszUnmountCommand);
120 if (g_pszUnmountCommand == NULL)
122 mediadb_error_callback(
123 MEDIADB_ERROR_CRITICAL,
124 "Out of memory.");
125 return MEDIADB_MEM;
128 return MEDIADB_OK;
131 const char *
132 disk_get_unmount_command()
134 return g_pszUnmountCommand;
137 mediadb_result
138 disk_set_defaults()
140 if (g_pszMountCommand == NULL)
142 g_pszMountCommand = strdup(DEFAULT_MOUNT_CMD);
143 if (g_pszMountCommand == NULL)
145 mediadb_error_callback(
146 MEDIADB_ERROR_CRITICAL,
147 "Out of memory.");
148 return MEDIADB_MEM;
152 if (g_pszUnmountCommand == NULL)
154 g_pszUnmountCommand = strdup(DEFAULT_UNMOUNT_CMD);
155 if (g_pszUnmountCommand == NULL)
157 mediadb_error_callback(
158 MEDIADB_ERROR_CRITICAL,
159 "Out of memory.");
160 return MEDIADB_MEM;
164 if (g_pszDiskPath == NULL)
166 g_pszDiskPath = strdup(DEFAULT_MOUNTDIR);
167 if (g_pszDiskPath == NULL)
169 mediadb_error_callback(
170 MEDIADB_ERROR_CRITICAL,
171 "Out of memory.");
172 return MEDIADB_MEM;
176 return MEDIADB_OK;
179 static
180 mediadb_result
181 ScanDir(struct scan_context *pContext, unsigned long nDepth)
183 DIR *pDir;
184 struct dirent *pDE;
185 size_t nCurrentPathLength;
186 struct stat st;
187 size_t sizeName;
188 mediadb_result r;
190 if (nDepth >= MAX_PATH_DEPTH)
192 mediadb_error_printf(
193 MEDIADB_ERROR_NONCRITICAL,
194 "Max path depth of \"%u\" reached.\n",
195 (unsigned int)MAX_PATH_DEPTH);
196 r = MEDIADB_FAIL;
197 goto Exit;
200 nCurrentPathLength = strlen(pContext->pszPathBuffer);
202 pDir = opendir(pContext->pszPathBuffer);
203 if (pDir == NULL)
205 mediadb_error_printf(
206 MEDIADB_ERROR_NONCRITICAL,
207 "Cannot open \"%s\"",
208 pContext->pszPathBuffer);
209 r = MEDIADB_FAIL;
210 goto Exit;
213 while ((pDE = readdir(pDir)) != NULL)
215 if (strcmp(pDE->d_name, ".") == 0)
216 continue;
218 if (strcmp(pDE->d_name, "..") == 0)
219 continue;
221 #if defined(OPENBSD)
222 sizeName = pDE->d_namlen;
223 #else
224 sizeName = strlen(pDE->d_name);
225 #endif
227 r = maybe_enlarge_buffer(
228 &pContext->pszPathBuffer,
229 &pContext->nPathBufferSize,
230 nCurrentPathLength + sizeName + 1);
231 if (MEDIADB_IS_ERROR(r))
233 mediadb_error_callback(
234 MEDIADB_ERROR_CRITICAL,
235 "Out of memory");
236 goto ExitCloseDir;
239 memcpy(pContext->pszPathBuffer + nCurrentPathLength, pDE->d_name, sizeName);
240 pContext->pszPathBuffer[nCurrentPathLength + sizeName] = 0;
242 if (lstat(pContext->pszPathBuffer, &st) != 0)
244 mediadb_error_printf(
245 MEDIADB_ERROR_NONCRITICAL,
246 "Cannot stat() %s. Error is %d (%s)",
247 pContext->pszPathBuffer,
248 errno,
249 strerror(errno));
250 r = MEDIADB_FAIL;
251 goto ExitCloseDir;
254 pContext->pszPathBuffer[nCurrentPathLength] = 0;
256 r = pContext->pCallback(
257 pContext->pUserContext,
258 pDE->d_name,
259 (S_ISDIR(st.st_mode))?MEDIADB_FILETYPE_DIR:MEDIADB_FILETYPE_FILE,
260 pContext->pszPathBuffer + pContext->nDiskPathPrefixLength,
261 ((S_ISDIR(st.st_mode))?0:st.st_size),
262 st.st_ctime);
263 if (MEDIADB_IS_ERROR(r))
265 goto ExitCloseDir;
268 pContext->nTotalFiles++;
270 if (S_ISDIR(st.st_mode))
272 memcpy(pContext->pszPathBuffer + nCurrentPathLength, pDE->d_name, sizeName);
273 memcpy(pContext->pszPathBuffer + nCurrentPathLength + sizeName, "/", 2);
274 r = ScanDir(pContext, nDepth + 1);
275 if (MEDIADB_IS_ERROR(r))
277 goto ExitCloseDir;
280 else
282 pContext->nTotalSize += st.st_size;
286 ExitCloseDir:
287 closedir(pDir);
289 Exit:
290 return r;
293 mediadb_result
294 disk_scan(disk_scan_callback pCallback,
295 void *pUserContext,
296 mediadb_uint *pnTotalFiles,
297 mediadb_uint *pnTotalSize)
299 mediadb_result r;
300 struct scan_context context;
302 context.pCallback = pCallback;
303 context.pUserContext = pUserContext;
304 context.pszPathBuffer = NULL;
305 context.nPathBufferSize = 0;
306 context.nTotalFiles = 0;
307 context.nTotalSize = 0;
309 context.nDiskPathPrefixLength = strlen(g_pszDiskPath);
311 r = maybe_enlarge_buffer(
312 &context.pszPathBuffer,
313 &context.nPathBufferSize,
314 context.nDiskPathPrefixLength + 2);
315 if (MEDIADB_IS_ERROR(r))
317 mediadb_error_callback(
318 MEDIADB_ERROR_CRITICAL,
319 "Out of memory");
320 return r;
323 memcpy(context.pszPathBuffer, g_pszDiskPath, context.nDiskPathPrefixLength);
324 memcpy(context.pszPathBuffer + context.nDiskPathPrefixLength, "/", 2);
326 r = ScanDir(&context, 0);
328 if (MEDIADB_IS_SUCCESS(r))
330 *pnTotalFiles = context.nTotalFiles;
331 *pnTotalSize = context.nTotalSize;
334 return r;
337 static mediadb_result
338 ExecuteCommand(const char *pszCommand)
340 int nRet;
342 nRet = system(pszCommand);
343 if (nRet == -1)
345 mediadb_error_printf(
346 MEDIADB_ERROR_NONCRITICAL,
347 "Cannot execute command \"%s\". "
348 "system() returned -1, error is %d (%s)\n",
349 pszCommand,
350 errno,
351 strerror(errno));
352 return MEDIADB_FAIL;
355 if (WIFEXITED(nRet))
357 if (WEXITSTATUS(nRet) != 0)
359 mediadb_error_printf(
360 MEDIADB_ERROR_NONCRITICAL,
361 "Cannot execute command \"%s\". "
362 "Command returned %d\n",
363 pszCommand,
364 (int)WEXITSTATUS(nRet));
365 return MEDIADB_FAIL;
368 else if (WIFSIGNALED(nRet))
370 mediadb_error_printf(
371 MEDIADB_ERROR_NONCRITICAL,
372 "Cannot execute command \"%s\". "
373 "Cammand was terminated because of signal %d\n",
374 pszCommand,
375 (int)WTERMSIG(nRet));
376 return MEDIADB_FAIL;
378 else
380 mediadb_error_printf(
381 MEDIADB_ERROR_NONCRITICAL,
382 "Cannot execute command \"%s\". "
383 "system() returned %d\n",
384 pszCommand,
385 nRet);
386 return MEDIADB_FAIL;
389 return MEDIADB_OK;
392 mediadb_result
393 disk_open()
395 mediadb_result r;
397 r = ExecuteCommand(g_pszMountCommand);
398 if (MEDIADB_IS_SUCCESS(r))
400 g_blnMediaMounted = 1;
403 return r;
406 mediadb_result
407 disk_close()
409 mediadb_result r;
411 r = ExecuteCommand(g_pszUnmountCommand);
412 if (MEDIADB_IS_SUCCESS(r))
414 g_blnMediaMounted = 0;
417 return r;
420 void
421 disk_uninit()
423 if (g_blnMediaMounted)
425 disk_close();
428 if (g_pszMountCommand != NULL)
429 free(g_pszMountCommand);
431 if (g_pszUnmountCommand != NULL)
432 free(g_pszUnmountCommand);
434 if (g_pszDiskPath != NULL)
435 free(g_pszDiskPath);
438 /*****************************************************************************
440 * Modifications log:
442 * !!! WARNING !!! Following lines are automatically updated by the CVS system.
444 * $Log: disk.c,v $
445 * Revision 1.2 2004/05/21 23:42:49 nedko
446 * mediadb_error_callback() now tells if error is critical.
448 * Revision 1.1 2004/05/16 19:01:17 nedko
449 * libfrontend holds code common to frontends but not in libdb.
451 *****************************************************************************/