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>
31 extern char **environ
;
33 #include "../libdb/libdb.h"
34 #include "../libdb/memory.h"
40 #define MAX_TITLE_SIZE 128 /* in db */
41 #define MAX_PASS_SIZE 1024
42 #define DEFAULT_MYSQL_USER "mediadatabase"
43 #define DEFAULT_MYSQL_PASS ""
44 #define DEFAULT_MYSQL_HOST "localhost"
45 #define DEFAULT_MYSQL_DB "mediadatabase"
47 #define DEFAULT_MOUNT_CMD "sudo /sbin/mount /cdrom"
48 #define DEFAULT_UNMOUNT_CMD "sudo /sbin/umount /cdrom"
50 #define DEFAULT_MOUNT_CMD "/bin/mount /cdrom"
51 #define DEFAULT_UNMOUNT_CMD "/bin/umount /cdrom"
53 #define DEFAULT_MOUNTDIR "/cdrom"
54 #define MAX_PATH_DEPTH 65535
55 #define DEFAULT_SQLITE_DB "mediadatabase.sqlitedb"
56 #define DEFAULT_BACKEND MEDIADB_DBTYPE_SQLITE
58 #define CONF_FILE ".mediadatabase"
59 #define CFL_SECTION_GLOBAL NULL
60 #define CFL_SECTION_CUI "cui"
61 #define CFL_SECTION_MYSQL "MySQL"
62 #define CFL_SECTION_SQLITE "SQLite"
63 #define CFL_VALUE_MYSQL_HOST "host"
64 #define CFL_VALUE_MYSQL_USER "user"
65 #define CFL_VALUE_MYSQL_PASS "pass"
66 #define CFL_VALUE_MYSQL_DB "db"
67 #define CFL_VALUE_MOUNT "mount"
68 #define CFL_VALUE_UNMOUNT "unmount"
69 #define CFL_VALUE_MOUNTDIR "mountdir"
70 #define CFL_VALUE_SQLITE_DB "dbfile"
71 #define CFL_VALUE_BACKEND "backend"
73 //#define PRINT_FILENAMES
75 char strTitle
[MAX_TITLE_SIZE
+2]; /* + newline + null */
76 char strPass
[MAX_PASS_SIZE
];
77 char *pszPathBuffer
= NULL
;
78 size_t nPathBufferSize
= 0;
79 size_t nMountPrefixLength
;
80 unsigned long nTotalFiles
;
81 unsigned long long nTotalSize
;
82 mediadb_uint nMediaID
= 0ULL;
83 mediadb hDB
= MEDIADB_INVALID_VALUE
;
84 int blnMediaMounted
= 0;
90 char *pszMountMediaCommand
= NULL
;
91 char *pszUnmountMediaCommand
= NULL
;
92 char *pszMountDir
= NULL
;
93 char *pszTitle
= NULL
;
94 char *pszDBSQLite
= NULL
;
96 unsigned int nDBType
= 0;
98 #define MODE_LIST_MEDIA 0
99 #define MODE_ADD_MEDIA 1
100 #define MODE_UPDATE_MEDIA 2
101 unsigned int nMode
= MODE_LIST_MEDIA
;
104 ExecuteCommand(const char *pszCommand
);
109 printf("--> Mounting media ...\n");
110 ExecuteCommand(pszMountMediaCommand
);
111 printf("--> Media mounted.\n");
118 printf("--> Unmounting media ...\n");
119 ExecuteCommand(pszUnmountMediaCommand
);
120 printf("--> Media unmounted.\n");
134 if (hDB
!= MEDIADB_INVALID_VALUE
)
136 r
= mediadb_close(hDB
);
154 if (pszMountMediaCommand
!= NULL
)
155 free(pszMountMediaCommand
);
157 if (pszUnmountMediaCommand
!= NULL
)
158 free(pszUnmountMediaCommand
);
160 if (pszMountDir
!= NULL
)
163 if (pszTitle
!= NULL
)
170 ExecuteCommand(const char *pszCommand
)
174 nRet
= system(pszCommand
);
178 "Cannot execute command \"%s\". "
179 "system() returned -1, error is %d (%s)\n",
188 if (WEXITSTATUS(nRet
) != 0)
191 "Cannot execute command \"%s\". "
192 "Command returned %d\n",
194 (int)WEXITSTATUS(nRet
));
198 else if (WIFSIGNALED(nRet
))
201 "Cannot execute command \"%s\". "
202 "Cammand was terminated because of signal %d\n",
204 (int)WTERMSIG(nRet
));
210 "Cannot execute command \"%s\". "
211 "system() returned %d\n",
219 ReadTitleExitOnEmpty()
224 if (fgets(strTitle
, sizeof(strTitle
), stdin
) == NULL
)
233 fprintf(stderr
, "Error occured while reading standard input.\n");
236 else if (strTitle
[0] == '\n')
241 if ((pch
= strchr(strTitle
, '\n')) == NULL
)
243 fprintf(stderr
, "input line too long.\n");
254 char strMediaID
[100];
256 printf("Media ID: ");
257 if (fgets(strMediaID
, sizeof(strMediaID
), stdin
) == NULL
)
266 fprintf(stderr
, "Error occured while reading standard input.\n");
269 else if (strMediaID
[0] == '\n')
274 if ((pch
= strchr(strMediaID
, '\n')) == NULL
)
276 fprintf(stderr
, "input line too long.\n");
282 nMediaID
= strtoull(strMediaID
, NULL
, 10);
290 ReadTitleIgnoreOnEmpty()
295 if (fgets(strTitle
, sizeof(strTitle
), stdin
) == NULL
)
301 strcpy(strTitle
, pszTitle
);
305 fprintf(stderr
, "Error occured while reading standard input.\n");
308 else if (strTitle
[0] == '\n')
310 strcpy(strTitle
, pszTitle
);
314 if ((pch
= strchr(strTitle
, '\n')) == NULL
)
316 fprintf(stderr
, "input line too long.\n");
328 pszPass
= getpass("MySQL password: ");
330 strcpy(strPass
, pszPass
);
334 MaybeEnlargeBuffer(char ** ppBuffer
,
335 size_t *pnBufferSize
,
336 size_t nSizeRequired
)
340 r
= maybe_enlarge_buffer(
344 if (MEDIADB_IS_ERROR(r
))
347 "Cannot enlarge buffer.\n");
353 ScanDir(unsigned long nDepth
)
358 size_t nCurrentPathLength
;
362 if (nDepth
>= MAX_PATH_DEPTH
)
365 "Max path depth of reached \"%u\"\n",
366 (unsigned int)MAX_PATH_DEPTH
);
370 nCurrentPathLength
= strlen(pszPathBuffer
);
372 pDir
= opendir(pszPathBuffer
);
375 fprintf(stderr
, "Cannot open \"%s\"\n", pszPathBuffer
);
381 while ((pDE
= readdir(pDir
)) != NULL
)
383 if (strcmp(pDE
->d_name
, ".") == 0)
386 if (strcmp(pDE
->d_name
, "..") == 0)
390 sizeName
= pDE
->d_namlen
;
392 sizeName
= strlen(pDE
->d_name
);
395 MaybeEnlargeBuffer(&pszPathBuffer
,
397 nCurrentPathLength
+ sizeName
+ 1);
399 memcpy(pszPathBuffer
+ nCurrentPathLength
, pDE
->d_name
, sizeName
);
400 pszPathBuffer
[nCurrentPathLength
+ sizeName
] = 0;
402 if (lstat(pszPathBuffer
, &st
) != 0)
405 "Cannot stat() %s. Error is %d (%s)\n",
411 pszPathBuffer
[nCurrentPathLength
] = 0;
413 r
= mediadb_file_add_new(
416 (S_ISDIR(st
.st_mode
))?MEDIADB_FILETYPE_DIR
:MEDIADB_FILETYPE_FILE
,
417 pszPathBuffer
+ nMountPrefixLength
,
419 ((S_ISDIR(st
.st_mode
))?0:st
.st_size
),
421 if (MEDIADB_IS_ERROR(r
))
424 "Failed to add new file to database. Error is %d (%s)\n",
426 mediadb_get_error_message(hDB
));
429 memcpy(pszPathBuffer
+ nCurrentPathLength
, pDE
->d_name
, sizeName
);
430 pszPathBuffer
[nCurrentPathLength
+ sizeName
] = 0;
432 #ifdef PRINT_FILENAMES
433 printf("%s", pszPathBuffer
+ nMountPrefixLength
);
438 if (S_ISDIR(st
.st_mode
))
440 #ifdef PRINT_FILENAMES
446 memcpy(pszPathBuffer
+ nCurrentPathLength
+ sizeName
, "/", 2);
451 nTotalSize
+= st
.st_size
;
452 #ifdef PRINT_FILENAMES
472 pszHost
= strdup(DEFAULT_MYSQL_HOST
);
483 pszUser
= strdup(DEFAULT_MYSQL_USER
);
494 pszPass
= strdup(DEFAULT_MYSQL_PASS
);
505 pszDB
= strdup(DEFAULT_MYSQL_DB
);
514 if (pszMountMediaCommand
== NULL
)
516 pszMountMediaCommand
= strdup(DEFAULT_MOUNT_CMD
);
517 if (pszMountMediaCommand
== NULL
)
525 if (pszUnmountMediaCommand
== NULL
)
527 pszUnmountMediaCommand
= strdup(DEFAULT_UNMOUNT_CMD
);
528 if (pszUnmountMediaCommand
== NULL
)
536 if (pszMountDir
== NULL
)
538 pszMountDir
= strdup(DEFAULT_MOUNTDIR
);
539 if (pszMountDir
== NULL
)
547 if (pszDBSQLite
== NULL
)
549 s
= strlen(pszHOME
) + strlen(DEFAULT_SQLITE_DB
)+2;
550 pszDBSQLite
= malloc(s
);
551 if (pszDBSQLite
== NULL
)
565 nDBType
= DEFAULT_BACKEND
;
574 pszExecutable
= strrchr(arg0
, '/');
576 if (pszExecutable
== NULL
)
578 pszExecutable
= arg0
;
587 printf("==============================\n");
588 printf("Offline media content database\n");
589 printf("==============================\n");
591 printf("[<path_to>]%s [options]\n", pszExecutable
);
592 printf(" Options can be:\n");
593 printf(" -? - This help\n");
594 printf(" -L - List media mode\n");
595 printf(" -A - Add media mode\n");
596 printf(" -U - Update media mode\n");
597 printf(" -m <mount_cmd> - command to mount media, default is \"%s\"\n", pszMountMediaCommand
);
598 printf(" -n <unmount_cmd> - command to unmount, default is \"%s\"\n", pszUnmountMediaCommand
);
599 printf(" -M - Use MySQL backend%s\n", (nDBType
== MEDIADB_DBTYPE_MYSQL
)?" (default)":"");
600 printf(" -d <mount_dir> - where media is mounted, default is \"%s\"\n", pszMountDir
);
601 printf(" -h <mysql_host> - MySQL server host, default is \"%s\"\n", pszHost
);
602 printf(" -u <mysql_user> - MySQL user, default is \"%s\"\n", pszUser
);
603 printf(" -p [mysql_pass] - MySQL password, default is \"%s\"\n", pszPass
);
604 printf(" -b <mysql_database> - MySQL database, default is \"%s\"\n", pszDB
);
605 printf(" -S - Use SQLite backend%s\n", (nDBType
== MEDIADB_DBTYPE_SQLITE
)?" (default)":"");
606 printf(" -f <sqlite_database_file> - SQLite database file, default is \"%s\"\n", pszDBSQLite
);
616 printf("NOTE: Currently audio media is not supported.\n");
619 memcpy(pszPathBuffer
+ nMountPrefixLength
, "/", 2);
621 printf("--> Please insert media and enter title.\n");
623 ReadTitleExitOnEmpty();
627 printf("--> Processing media ...\n");
629 r
= mediadb_media_add_new(
636 if (MEDIADB_IS_ERROR(r
))
639 "Failed to add new media to database. Error is %d (%s)\n",
641 mediadb_get_error_message(hDB
));
649 timeAdded
= time(NULL
);
651 r
= mediadb_media_update_properties(
658 if (MEDIADB_IS_ERROR(r
))
661 "Failed to update new media to database. Error is %d (%s)\n",
663 mediadb_get_error_message(hDB
));
669 printf("--> SUCCESS - Media added.\n");
670 printf("Media title: %s\n", strTitle
);
671 printf("Media ID: %u\n", (unsigned int)nMediaID
);
672 printf("Added: %s", ctime(&timeAdded
));
673 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
674 printf("Total size: %u\n", (unsigned int)nTotalSize
);
684 mediadb_uint nTimeAdded
;
685 mediadb_uint nTotalFiles
;
686 mediadb_uint nTotalSize
;
688 printf("NOTE: Currently audio media is not supported.\n");
691 printf("--> Please enter Media ID.\n");
695 memcpy(pszPathBuffer
+ nMountPrefixLength
, "/", 2);
697 r
= mediadb_media_get_properties(
704 if (MEDIADB_IS_ERROR(r
))
707 "Failed to get media properties. Error is %d (%s)\n",
709 mediadb_get_error_message(hDB
));
713 if (strlen(pszTitle
) + 1 > MAX_TITLE_SIZE
)
720 timeAdded
= (time_t)nTimeAdded
;
722 printf("Media title: %s\n", pszTitle
);
723 printf("Added: %s", ctime(&timeAdded
));
724 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
725 printf("Total size: %u\n", (unsigned int)nTotalSize
);
727 printf("--> Please insert media and enter title (Just press return to keep current title).\n");
729 ReadTitleIgnoreOnEmpty();
733 printf("--> Processing media ...\n");
735 if (strcmp(pszTitle
, strTitle
) != 0)
737 r
= mediadb_media_update_name(
741 if (MEDIADB_IS_ERROR(r
))
744 "Cannot update media title. Error is %d (%s)\n",
746 mediadb_get_error_message(hDB
));
751 r
= mediadb_delete_media_files(
755 if (MEDIADB_IS_ERROR(r
))
758 "Failed to delete media files in database. Error is %d (%s)\n",
760 mediadb_get_error_message(hDB
));
768 //timeAdded = time(NULL);
770 r
= mediadb_media_update_properties(
777 if (MEDIADB_IS_ERROR(r
))
780 "Failed to update new media to database. Error is %d (%s)\n",
782 mediadb_get_error_message(hDB
));
788 printf("--> SUCCESS - Media added.\n");
789 printf("Media title: %s\n", strTitle
);
790 printf("Media ID: %u\n", (unsigned int)nMediaID
);
791 printf("Added: %s", ctime(&timeAdded
));
792 printf("Total files: %u\n", (unsigned int)nTotalFiles
);
793 printf("Total size: %u\n", (unsigned int)nTotalSize
);
801 printf("List media mode not implemented yet.\n");
818 cfl_value_type_t CFLValueType
;
821 pszExecutable
= strrchr(argv
[0], '/');
823 if (pszExecutable
== NULL
)
825 pszExecutable
= argv
[0];
832 if (strcmp(pszExecutable
, "mdb_add") == 0)
834 nMode
= MODE_ADD_MEDIA
;
836 else if (strcmp(pszExecutable
, "mdb_update") == 0)
838 nMode
= MODE_UPDATE_MEDIA
;
842 nMode
= MODE_LIST_MEDIA
;
845 /* Find HOME environment variable */
846 pszHOME
= getenv("HOME");
851 "Please set the HOME encironment variable.\n");
855 /* Look into configuration file */
857 s
= strlen(pszHOME
) + 1 + strlen(CONF_FILE
) + 1;
858 pszConf
= (char *)malloc(s
);
859 sprintf(pszConf
, "%s/%s", pszHOME
, CONF_FILE
);
861 hFile
= fopen(pszConf
, "r");
872 nRet
= cfl_init_from_file(
875 CFL_FILE_TYPE_DEFAULT
);
878 printf("cfl_init_from_file() failed. (%s)\n", cfl_errcode_to_message(nRet
));
881 pszCFLValue
= cfl_value_get_by_name(
887 if (pszCFLValue
!= NULL
&&
888 CFLValueType
== CFL_TYPE_STRING
)
890 pszMountMediaCommand
= strdup(pszCFLValue
);
891 if (pszMountMediaCommand
== NULL
)
899 pszCFLValue
= cfl_value_get_by_name(
905 if (pszCFLValue
!= NULL
&&
906 CFLValueType
== CFL_TYPE_STRING
)
908 pszUnmountMediaCommand
= strdup(pszCFLValue
);
909 if (pszUnmountMediaCommand
== NULL
)
917 pszCFLValue
= cfl_value_get_by_name(
923 if (pszCFLValue
!= NULL
&&
924 CFLValueType
== CFL_TYPE_STRING
)
926 pszMountDir
= strdup(pszCFLValue
);
927 if (pszMountDir
== NULL
)
935 pszCFLValue
= cfl_value_get_by_name(
938 CFL_VALUE_MYSQL_HOST
,
941 if (pszCFLValue
!= NULL
&&
942 CFLValueType
== CFL_TYPE_STRING
)
944 pszHost
= strdup(pszCFLValue
);
953 pszCFLValue
= cfl_value_get_by_name(
959 if (pszCFLValue
!= NULL
&&
960 CFLValueType
== CFL_TYPE_STRING
)
962 pszDB
= strdup(pszCFLValue
);
971 pszCFLValue
= cfl_value_get_by_name(
974 CFL_VALUE_MYSQL_USER
,
977 if (pszCFLValue
!= NULL
&&
978 CFLValueType
== CFL_TYPE_STRING
)
980 pszUser
= strdup(pszCFLValue
);
989 pszCFLValue
= cfl_value_get_by_name(
992 CFL_VALUE_MYSQL_PASS
,
995 if (pszCFLValue
!= NULL
&&
996 CFLValueType
== CFL_TYPE_STRING
)
998 pszPass
= strdup(pszCFLValue
);
1002 "Out of memory.\n");
1007 pszCFLValue
= cfl_value_get_by_name(
1010 CFL_VALUE_SQLITE_DB
,
1013 if (pszCFLValue
!= NULL
&&
1014 CFLValueType
== CFL_TYPE_STRING
)
1016 pszDBSQLite
= strdup(pszCFLValue
);
1017 if (pszDBSQLite
== NULL
)
1020 "Out of memory.\n");
1025 pszCFLValue
= cfl_value_get_by_name(
1031 if (pszCFLValue
!= NULL
&&
1032 CFLValueType
== CFL_TYPE_STRING
)
1034 if (strcmp(pszCFLValue
, CFL_SECTION_SQLITE
) == 0)
1036 nDBType
= MEDIADB_DBTYPE_SQLITE
;
1038 else if (strcmp(pszCFLValue
, CFL_SECTION_MYSQL
) == 0)
1040 nDBType
= MEDIADB_DBTYPE_MYSQL
;
1049 /* Process options from command line */
1051 for (i
= 1; i
< argc
; i
++)
1053 if (strcmp(argv
[i
],"-L") == 0)
1055 nMode
= MODE_LIST_MEDIA
;
1057 else if (strcmp(argv
[i
],"-A") == 0)
1059 nMode
= MODE_ADD_MEDIA
;
1061 else if (strcmp(argv
[i
],"-U") == 0)
1063 nMode
= MODE_UPDATE_MEDIA
;
1065 else if (strcmp(argv
[i
],"-h") == 0)
1070 if (pszHost
!= NULL
)
1072 pszHost
= strdup(argv
[i
]);
1073 if (pszHost
== NULL
)
1076 "Out of memory.\n");
1083 "Missing parameter of -h option\n");
1087 else if (strcmp(argv
[i
],"-u") == 0)
1092 if (pszUser
!= NULL
)
1094 pszUser
= strdup(argv
[i
]);
1095 if (pszUser
== NULL
)
1098 "Out of memory.\n");
1105 "Missing parameter of -u option\n");
1109 else if (strcmp(argv
[i
],"-p") == 0)
1111 if (i
+1 < argc
&& argv
[i
+1][0] != '-')
1114 if (pszPass
!= NULL
)
1116 pszPass
= strdup(argv
[i
]);
1117 if (pszPass
== NULL
)
1120 "Out of memory.\n");
1127 if (pszPass
!= NULL
)
1129 pszPass
= strdup(strPass
);
1130 if (pszPass
== NULL
)
1133 "Out of memory.\n");
1138 else if (strcmp(argv
[i
],"-b") == 0)
1145 pszDB
= strdup(argv
[i
]);
1149 "Out of memory.\n");
1156 "Missing parameter of -b option\n");
1160 else if (strcmp(argv
[i
],"-f") == 0)
1165 if (pszDBSQLite
!= NULL
)
1167 pszDBSQLite
= strdup(argv
[i
]);
1168 if (pszDBSQLite
== NULL
)
1171 "Out of memory.\n");
1178 "Missing parameter of -f option\n");
1182 else if (strcmp(argv
[i
],"-m") == 0)
1187 if (pszMountMediaCommand
!= NULL
)
1188 free(pszMountMediaCommand
);
1189 pszMountMediaCommand
= strdup(argv
[i
]);
1190 if (pszMountMediaCommand
== NULL
)
1193 "Out of memory.\n");
1200 "Missing parameter of -m option\n");
1204 else if (strcmp(argv
[i
],"-n") == 0)
1209 if (pszUnmountMediaCommand
!= NULL
)
1210 free(pszUnmountMediaCommand
);
1211 pszUnmountMediaCommand
= strdup(argv
[i
]);
1212 if (pszUnmountMediaCommand
== NULL
)
1215 "Out of memory.\n");
1222 "Missing parameter of -n option\n");
1226 else if (strcmp(argv
[i
],"-d") == 0)
1231 if (pszMountDir
!= NULL
)
1233 pszMountDir
= strdup(argv
[i
]);
1234 if (pszMountDir
== NULL
)
1237 "Out of memory.\n");
1244 "Missing parameter of -d option\n");
1248 else if (strcmp(argv
[i
],"-M") == 0)
1250 nDBType
= MEDIADB_DBTYPE_MYSQL
;
1252 else if (strcmp(argv
[i
],"-S") == 0)
1254 nDBType
= MEDIADB_DBTYPE_SQLITE
;
1256 else if (strcmp(argv
[i
],"-?") == 0)
1263 "Unknown option \"%s\"\n",
1271 if (nDBType
== MEDIADB_DBTYPE_MYSQL
)
1274 MEDIADB_DBTYPE_MYSQL
,
1281 else if (nDBType
== MEDIADB_DBTYPE_SQLITE
)
1284 MEDIADB_DBTYPE_SQLITE
,
1294 "Unknown backend type (internal error)\n");
1298 if (MEDIADB_IS_ERROR(r
))
1301 "Failed to connect to database. Error is %d (%s)\n",
1303 mediadb_get_error_message(NULL
));
1307 nMountPrefixLength
= strlen(pszMountDir
);
1309 MaybeEnlargeBuffer(&pszPathBuffer
,
1311 nMountPrefixLength
+ 2);
1313 memcpy(pszPathBuffer
, pszMountDir
, nMountPrefixLength
);
1315 if (nMode
== MODE_ADD_MEDIA
)
1317 printf("=========================\n");
1318 printf("Add media mode\n");
1319 printf("=========================\n");
1322 else if (nMode
== MODE_UPDATE_MEDIA
)
1324 printf("=========================\n");
1325 printf("Update media mode\n");
1326 printf("=========================\n");
1329 else if (nMode
== MODE_LIST_MEDIA
)
1331 printf("=========================\n");
1332 printf("List media mode\n");
1333 printf("=========================\n");