1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
5 * Portable frontend to MediaDatabase
8 * gcc main.c -lmysqlclient -o mdb_cui [-DOPENBSD]
11 * Nedko Arnaudov <nedko@users.sourceforge.net>
14 * GNU GENERAL PUBLIC LICENSE version 2
16 *****************************************************************************/
21 #include <sys/types.h>
32 extern char **environ
;
34 #include "../result.h"
35 #include "../libdb/libdb.h"
36 #include "../libdb/memory.h"
37 #include "../libfrontend/error.h"
38 #include "../libfrontend/conf.h"
39 #include "../libfrontend/db.h"
40 #include "../libfrontend/disk.h"
41 #include "../libfrontend/helper.h"
43 #define MAX_TITLE_SIZE 128 /* in db */
44 #define MAX_PASS_SIZE 1024
45 #define MAX_READ_STRING_SIZE 10240
46 //#define PRINT_FILENAMES
48 char strTitle
[MAX_TITLE_SIZE
+2]; /* + newline + null */
49 char strPass
[MAX_PASS_SIZE
];
50 mediadb_uint nMediaID
= 0ULL;
52 char *pszTitle
= NULL
;
55 #define MODE_LIST_MEDIA 0
56 #define MODE_ADD_MEDIA 1
57 #define MODE_UPDATE_MEDIA 2
58 #define MODE_SEARCH_FILES 3
59 unsigned int nMode
= MODE_SEARCH_FILES
;
62 ExecuteCommand(const char *pszCommand
);
67 printf("--> Mounting media ...\n");
69 printf("--> Media mounted.\n");
75 printf("--> Unmounting media ...\n");
77 printf("--> Media unmounted.\n");
101 mediadb_error_callback(
102 unsigned int nCritical
,
103 const char *pszErrorDescription
108 pszErrorDescription
);
110 if (nCritical
== MEDIADB_ERROR_CRITICAL
)
117 ExecuteCommand(const char *pszCommand
)
121 nRet
= system(pszCommand
);
125 "Cannot execute command \"%s\". "
126 "system() returned -1, error is %d (%s)\n",
135 if (WEXITSTATUS(nRet
) != 0)
138 "Cannot execute command \"%s\". "
139 "Command returned %d\n",
141 (int)WEXITSTATUS(nRet
));
145 else if (WIFSIGNALED(nRet
))
148 "Cannot execute command \"%s\". "
149 "Cammand was terminated because of signal %d\n",
151 (int)WTERMSIG(nRet
));
157 "Cannot execute command \"%s\". "
158 "system() returned %d\n",
166 ReadTitleExitOnEmpty()
171 if (fgets(strTitle
, sizeof(strTitle
), stdin
) == NULL
)
180 fprintf(stderr
, "Error occured while reading standard input.\n");
183 else if (strTitle
[0] == '\n')
188 if ((pch
= strchr(strTitle
, '\n')) == NULL
)
190 fprintf(stderr
, "input line too long.\n");
201 char strMediaID
[100];
203 printf("Media ID: ");
204 if (fgets(strMediaID
, sizeof(strMediaID
), stdin
) == NULL
)
213 fprintf(stderr
, "Error occured while reading standard input.\n");
216 else if (strMediaID
[0] == '\n')
221 if ((pch
= strchr(strMediaID
, '\n')) == NULL
)
223 fprintf(stderr
, "input line too long.\n");
229 nMediaID
= strtoull(strMediaID
, NULL
, 10);
238 const char *pszQuestion
,
239 mediadb_bool blnExitOnEmpty
,
245 printf("%s", pszQuestion
);
246 if (fgets(str
, sizeof(str
), stdin
) == NULL
)
255 fprintf(stderr
, "Error occured while reading standard input.\n");
258 else if (str
[0] == '\n')
266 return MEDIADB_FALSE
;
270 if ((pch
= strchr(str
, '\n')) == NULL
)
272 fprintf(stderr
, "input line too long.\n");
278 *pn
= strtoull(str
, NULL
, 10);
284 const char *pszQuestion
,
285 mediadb_bool blnExitOnEmpty
,
290 printf("%s", pszQuestion
);
291 if (fgets(pBuffer
, MAX_READ_STRING_SIZE
, stdin
) == NULL
)
300 fprintf(stderr
, "Error occured while reading standard input.\n");
303 else if (pBuffer
[0] == '\n')
311 return MEDIADB_FALSE
;
315 if ((pch
= strchr(pBuffer
, '\n')) == NULL
)
317 fprintf(stderr
, "input line too long.\n");
327 const char *pszQuestion
,
328 const char **ppszOptions
,
329 unsigned int nOptionsCount
,
330 unsigned int nDefaultIndex
,
331 unsigned int *pnIndex
)
336 unsigned long choice
;
338 assert(nDefaultIndex
< nOptionsCount
);
341 printf("%s\n", pszQuestion
);
342 for (i
= 0 ; i
< nOptionsCount
; i
++)
344 printf(" [%u] %s", i
+1, ppszOptions
[i
]);
345 if (i
== nDefaultIndex
)
347 printf(" (default)\n");
355 printf("What is your choice ? [default %u] ", nDefaultIndex
+1);
356 if (fgets(str
, sizeof(str
), stdin
) == NULL
)
365 fprintf(stderr
, "Error occured while reading standard input.\n");
368 else if (str
[0] == '\n')
370 *pnIndex
= nDefaultIndex
;
374 if ((pch
= strchr(str
, '\n')) == NULL
)
376 fprintf(stderr
, "input line too long.\n");
382 choice
= strtoul(str
, NULL
, 10);
384 if (choice
< 1 || choice
> nOptionsCount
)
386 printf("Cannot interpret \"%s\" as valid menu selection.", str
);
390 *pnIndex
= choice
- 1;
394 ReadTitleIgnoreOnEmpty()
399 if (fgets(strTitle
, sizeof(strTitle
), stdin
) == NULL
)
408 fprintf(stderr
, "Error occured while reading standard input.\n");
411 else if (strTitle
[0] == '\n')
413 strcpy(strTitle
, pszTitle
);
417 if ((pch
= strchr(strTitle
, '\n')) == NULL
)
419 fprintf(stderr
, "input line too long.\n");
431 pszPass
= getpass("MySQL password: ");
433 strcpy(strPass
, pszPass
);
437 MaybeEnlargeBuffer(char ** ppBuffer
,
438 size_t *pnBufferSize
,
439 size_t nSizeRequired
)
443 r
= maybe_enlarge_buffer(
447 if (MEDIADB_IS_ERROR(r
))
450 "Cannot enlarge buffer.\n");
456 mediadb_scan_callback(
458 const char *pszFilename
,
459 const mediadb_filetype nType
,
461 mediadb_uint nFileSize
,
462 mediadb_uint nFileTime
)
466 r
= mediadb_file_add_new(
474 if (MEDIADB_IS_ERROR(r
))
477 "Failed to add new file to database. Error is %d (%s)\n",
479 mediadb_get_error_message(g_hDB
));
482 #ifdef PRINT_FILENAMES
483 printf("%s/%s", pszPath
, pszFilename
);
486 if (nType
== MEDIADB_FILETYPE_DIR
)
488 #ifdef PRINT_FILENAMES
496 #ifdef PRINT_FILENAMES
521 pszExecutable
= strrchr(arg0
, '/');
523 if (pszExecutable
== NULL
)
525 pszExecutable
= arg0
;
534 printf("==============================\n");
535 printf("Offline media content database\n");
536 printf("==============================\n");
538 printf("[<path_to>]%s [options]\n", pszExecutable
);
539 printf(" Options can be:\n");
540 printf(" -? - This help\n");
541 /* printf(" -L - List media mode\n"); */
542 printf(" -A - Add media mode\n");
543 printf(" -U - Update media mode\n");
544 printf(" -F - Search files mode\n");
545 printf(" -m <mount_cmd> - command to mount media, default is \"%s\"\n", disk_get_mount_command());
546 printf(" -n <unmount_cmd> - command to unmount, default is \"%s\"\n", disk_get_unmount_command());
547 printf(" -M - Use MySQL backend%s\n", (db_get_type() == MEDIADB_DBTYPE_MYSQL
)?" (default)":"");
548 printf(" -d <mount_dir> - where media is mounted, default is \"%s\"\n", disk_get_path());
549 printf(" -h <mysql_host> - MySQL server host, default is \"%s\"\n", db_get_mysql_host());
550 printf(" -u <mysql_user> - MySQL user, default is \"%s\"\n", db_get_mysql_user());
551 printf(" -p [mysql_pass] - MySQL password, default is \"%s\"\n", db_get_mysql_pass());
552 printf(" -b <mysql_database> - MySQL database, default is \"%s\"\n", db_get_mysql_database());
553 printf(" -S - Use SQLite backend%s\n", (db_get_type() == MEDIADB_DBTYPE_SQLITE
)?" (default)":"");
554 printf(" -f <sqlite_database_file> - SQLite database file, default is \"%s\"\n", db_get_sqlite_database());
563 mediadb_uint nTotalFiles
;
564 mediadb_uint nTotalSize
;
566 printf("NOTE: Currently audio media is not supported.\n");
569 printf("--> Please insert media and enter title.\n");
571 ReadTitleExitOnEmpty();
575 printf("--> Processing media ...\n");
577 r
= mediadb_media_add_new(
584 if (MEDIADB_IS_ERROR(r
))
587 "Failed to add new media to database. Error is %d (%s)\n",
589 mediadb_get_error_message(g_hDB
));
593 disk_scan(mediadb_scan_callback
,
600 timeAdded
= time(NULL
);
602 r
= mediadb_media_update_properties(
609 if (MEDIADB_IS_ERROR(r
))
612 "Failed to update new media to database. Error is %d (%s)\n",
614 mediadb_get_error_message(g_hDB
));
620 printf("--> SUCCESS - Media added.\n");
621 printf("Media title: %s\n", strTitle
);
622 printf("Media ID: %u\n", (unsigned int)nMediaID
);
623 printf("Added: %s", ctime(&timeAdded
));
624 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
625 printf("Total size: %u\n", (unsigned int)nTotalSize
);
635 mediadb_uint nTimeAdded
;
636 mediadb_uint nTotalFiles
;
637 mediadb_uint nTotalSize
;
638 mediadb_mediatype nType
;
639 mediadb_uint nLocationID
;
641 printf("NOTE: Currently audio media is not supported.\n");
644 printf("--> Please enter Media ID.\n");
648 r
= mediadb_media_get_properties(
655 if (MEDIADB_IS_ERROR(r
))
658 "Failed to get media properties. Error is %d (%s)\n",
660 mediadb_get_error_message(g_hDB
));
664 if (nType
!= MEDIADB_MT_DATA
)
667 "Only data cd type is supprted.\n");
671 r
= mediadb_media_get_properties_data(
676 if (MEDIADB_IS_ERROR(r
))
679 "Failed to get media properties. Error is %d (%s)\n",
681 mediadb_get_error_message(g_hDB
));
685 if (strlen(pszTitle
) + 1 > MAX_TITLE_SIZE
)
692 timeAdded
= (time_t)nTimeAdded
;
694 printf("Media title: %s\n", pszTitle
);
695 printf("Added: %s", ctime(&timeAdded
));
696 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
697 printf("Total size: %u\n", (unsigned int)nTotalSize
);
699 printf("--> Please insert media and enter title (Just press return to keep current title).\n");
701 ReadTitleIgnoreOnEmpty();
705 printf("--> Processing media ...\n");
707 if (strcmp(pszTitle
, strTitle
) != 0)
709 r
= mediadb_media_update_name(
713 if (MEDIADB_IS_ERROR(r
))
716 "Cannot update media title. Error is %d (%s)\n",
718 mediadb_get_error_message(g_hDB
));
723 r
= mediadb_delete_media_files(
727 if (MEDIADB_IS_ERROR(r
))
730 "Failed to delete media files in database. Error is %d (%s)\n",
732 mediadb_get_error_message(g_hDB
));
736 disk_scan(mediadb_scan_callback
,
743 //timeAdded = time(NULL);
745 r
= mediadb_media_update_properties(
752 if (MEDIADB_IS_ERROR(r
))
755 "Failed to update new media to database. Error is %d (%s)\n",
757 mediadb_get_error_message(g_hDB
));
763 printf("--> SUCCESS - Media added.\n");
764 printf("Media title: %s\n", strTitle
);
765 printf("Media ID: %u\n", (unsigned int)nMediaID
);
766 printf("Added: %s", ctime(&timeAdded
));
767 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
768 printf("Total size: %u\n", (unsigned int)nTotalSize
);
776 /* printf("List media mode not implemented yet.\n"); */
779 mediadb_uint g_SearchFilesCounter
;
784 mediadb_uint nMediaID
,
785 mediadb_mediatype nMediaType
,
786 const char *pszMediaName
,
787 const char *pszMediaLocation
,
790 mediadb_filetype Filetype
,
797 char strSize
[MAX_SIZE_DESCRIPTION
];
799 localtime_r(&time
, &tm
);
801 "%u-%02u-%02u %02u:%02u:%02u",
809 get_size_description(nSize
, strSize
);
811 printf("--------------------\n");
812 printf("Name: %s%s\n", pszPath
, pszName
);
813 if (Filetype
== MEDIADB_FILETYPE_FILE
)
815 printf("Size: %s\n", strSize
);
817 printf("Time: %s\n", strTime
);
818 printf("MediaID: %u\n", (unsigned int)nMediaID
);
819 printf("Media name: %s\n", pszMediaName
);
820 printf("Media location: %s\n", pszMediaLocation
);
822 g_SearchFilesCounter
++;
829 mediadb_uint nMinSize
;
830 mediadb_uint nMaxSize
;
831 char strFilenamePattern
[MAX_READ_STRING_SIZE
];
832 char strPathPattern
[MAX_READ_STRING_SIZE
];
833 const char **ppszPMMS
;
834 const struct mediadb_pattern_match_method
*pPMM
;
835 unsigned int nPPMCount
;
836 unsigned int nFilenamePMMIndex
;
837 unsigned int nPathPMMIndex
;
839 struct timeval tv1
, tv2
;
843 r
= mediadb_get_pattern_match_methods(
846 if (MEDIADB_IS_ERROR(r
))
849 "Cannot get pattern match methods from backend. Error is %d (%s)\n",
851 mediadb_get_error_message(g_hDB
));
856 while (pPMM
[nPPMCount
].nID
!= MEDIADB_PMM_NULL
)
864 "Backend returned zero pattern march methods.\n");
868 ppszPMMS
= malloc(sizeof(const char *) * nPPMCount
);
869 if (ppszPMMS
== NULL
)
876 for (i
= 0 ; i
< nPPMCount
; i
++)
878 ppszPMMS
[i
] = pPMM
[i
].pszName
;
881 if (!ReadString("Filename pattern: ", MEDIADB_FALSE
, strFilenamePattern
))
883 strFilenamePattern
[0] = 0;
887 Menu("Filename pattern match method",
894 if (!ReadString("Path pattern: ", MEDIADB_FALSE
, strPathPattern
))
896 strPathPattern
[0] = 0;
900 Menu("Path pattern match method",
909 if (!ReadInteger("Min size: ", MEDIADB_FALSE
, &nMinSize
))
914 if (!ReadInteger("Max size: ", MEDIADB_FALSE
, &nMaxSize
))
919 printf("--> Searching ...\n");
920 g_SearchFilesCounter
= 0;
922 if (gettimeofday(&tv1
, &tz
) == -1)
925 "gettimeofday() failed. Error is %d (%s)\n",
931 r
= mediadb_files_search(
933 strFilenamePattern
[0]?pPMM
[nFilenamePMMIndex
].nID
:MEDIADB_PMM_NULL
,
934 strFilenamePattern
[0]?strFilenamePattern
:NULL
,
935 strPathPattern
[0]?pPMM
[nPathPMMIndex
].nID
:MEDIADB_PMM_NULL
,
936 strPathPattern
[0]?strPathPattern
:NULL
,
937 nMinSize
?&nMinSize
:NULL
,
938 nMaxSize
?&nMaxSize
:NULL
,
942 if (gettimeofday(&tv2
, &tz
) == -1)
945 "gettimeofday() failed. Error is %d (%s)\n",
951 printf("--------------------\n");
953 if (MEDIADB_IS_ERROR(r
))
956 "Search failed. Error is %d (%s)\n",
958 mediadb_get_error_message(g_hDB
));
962 printf("%u file(s) found\n", (unsigned int)g_SearchFilesCounter
);
965 t1
+= (double)tv1
.tv_usec
/ 1000000.0;
967 t2
+= (double)tv2
.tv_usec
/ 1000000.0;
968 printf("Search took %f seconds\n", t2
-t1
);
981 pszExecutable
= strrchr(argv
[0], '/');
983 if (pszExecutable
== NULL
)
985 pszExecutable
= argv
[0];
992 if (strcmp(pszExecutable
, "mdb_add") == 0)
994 nMode
= MODE_ADD_MEDIA
;
996 else if (strcmp(pszExecutable
, "mdb_update") == 0)
998 nMode
= MODE_UPDATE_MEDIA
;
1002 nMode
= MODE_SEARCH_FILES
;
1005 /* Find HOME environment variable */
1006 pszHOME
= getenv("HOME");
1008 if (pszHOME
== NULL
)
1011 "Please set the HOME encironment variable.\n");
1015 /* Look into configuration file */
1018 /* Process options from command line */
1020 for (i
= 1; i
< argc
; i
++)
1022 /* if (strcmp(argv[i],"-L") == 0) */
1024 /* nMode = MODE_LIST_MEDIA; */
1027 if (strcmp(argv
[i
],"-A") == 0)
1029 nMode
= MODE_ADD_MEDIA
;
1031 else if (strcmp(argv
[i
],"-U") == 0)
1033 nMode
= MODE_UPDATE_MEDIA
;
1035 else if (strcmp(argv
[i
],"-F") == 0)
1037 nMode
= MODE_SEARCH_FILES
;
1039 else if (strcmp(argv
[i
],"-h") == 0)
1044 db_set_mysql_host(argv
[i
]);
1049 "Missing parameter of -h option\n");
1053 else if (strcmp(argv
[i
],"-u") == 0)
1058 db_set_mysql_user(argv
[i
]);
1063 "Missing parameter of -u option\n");
1067 else if (strcmp(argv
[i
],"-p") == 0)
1069 if (i
+1 < argc
&& argv
[i
+1][0] != '-')
1072 db_set_mysql_pass(argv
[i
]);
1077 db_set_mysql_pass(strPass
);
1080 else if (strcmp(argv
[i
],"-b") == 0)
1085 db_set_mysql_database(argv
[i
]);
1090 "Missing parameter of -b option\n");
1094 else if (strcmp(argv
[i
],"-f") == 0)
1099 db_set_sqlite_database(argv
[i
]);
1104 "Missing parameter of -f option\n");
1108 else if (strcmp(argv
[i
],"-m") == 0)
1113 disk_set_mount_command(argv
[i
]);
1118 "Missing parameter of -m option\n");
1122 else if (strcmp(argv
[i
],"-n") == 0)
1127 disk_set_unmount_command(argv
[i
]);
1132 "Missing parameter of -n option\n");
1136 else if (strcmp(argv
[i
],"-d") == 0)
1141 disk_set_path(argv
[i
]);
1146 "Missing parameter of -d option\n");
1150 else if (strcmp(argv
[i
],"-M") == 0)
1154 else if (strcmp(argv
[i
],"-S") == 0)
1158 else if (strcmp(argv
[i
],"-?") == 0)
1165 "Unknown option \"%s\"\n",
1175 if (nMode
== MODE_ADD_MEDIA
)
1177 printf("=========================\n");
1178 printf("Add media mode\n");
1179 printf("=========================\n");
1182 else if (nMode
== MODE_UPDATE_MEDIA
)
1184 printf("=========================\n");
1185 printf("Update media mode\n");
1186 printf("=========================\n");
1189 /* else if (nMode == MODE_LIST_MEDIA) */
1191 /* printf("=========================\n"); */
1192 /* printf("List media mode\n"); */
1193 /* printf("=========================\n"); */
1196 else if (nMode
== MODE_SEARCH_FILES
)
1198 printf("=========================\n");
1199 printf("Search files mode\n");
1200 printf("=========================\n");