00001
00007 #include <stdbool.h>
00008 #include <stddef.h>
00009 #include <stdint.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013 #include <sys/types.h>
00014 #include <unistd.h>
00015
00016
00017 #include "check.h"
00018 #include "crc32.h"
00019 #include "config.h"
00020 #include "db5_dat.h"
00021 #include "db5_hdr.h"
00022 #include "db5_types.h"
00023 #include "file.h"
00024 #include "logger.h"
00025 #include "wstring.h"
00026
00028 static FILE *db5_dat;
00029
00030 bool db5_dat_init()
00031 {
00032 crc32_init();
00033
00034 db5_dat = file_fcaseopen(CONFIG_DB5_DATA_DIR, CONFIG_DB5_DAT_FILE, "rb+");
00035
00036 if (db5_dat == NULL)
00037 {
00038 add_log(ADDLOG_CRITICAL, "[db5/dat]init", "unable to init database\n");
00039 return false;
00040 }
00041
00042 return true;
00043 }
00044
00045 void db5_dat_free()
00046 {
00047 fclose(db5_dat);
00048 }
00049
00050 bool db5_dat_select_row(const uint32_t index, db5_row *row)
00051 {
00052 check(row != NULL);
00053
00054 if (fseek(db5_dat, index*sizeof(db5_row), SEEK_SET) != 0)
00055 {
00056 add_log(ADDLOG_FAIL, "[db5/dat]read", "unable to find database row (reading)\n");
00057 return false;
00058 }
00059 if (fread(row, sizeof(db5_row), 1, db5_dat) != 1)
00060 {
00061 add_log(ADDLOG_FAIL, "[db5/dat]read", "unable to read into database\n");
00062 return false;
00063 }
00064
00065 return true;
00066 }
00067
00068 bool db5_dat_update(const uint32_t index, db5_row *row)
00069 {
00070 check(row != NULL);
00071
00072 if (fseek(db5_dat, index*sizeof(db5_row), SEEK_SET) != 0)
00073 {
00074 add_log(ADDLOG_FAIL, "[db5/dat]alter", "unable to find database row (writing)\n");
00075 return false;
00076 }
00077 if (fwrite(row, sizeof(db5_row), 1, db5_dat) != 1)
00078 {
00079 add_log(ADDLOG_FAIL, "[db5/dat]alter", "unable to write into database\n");
00080 return false;
00081 }
00082
00083 return true;
00084 }
00085
00086 bool db5_dat_insert(db5_row *row)
00087 {
00088 check(row != NULL);
00089
00090 if (db5_hdr_count() >= CONFIG_MAX_DB5_ENTRY)
00091 {
00092 add_log(ADDLOG_FAIL, "[db5/dat]add", "database if full\n");
00093 return false;
00094 }
00095
00096 if (fseek(db5_dat, db5_hdr_count()*sizeof(db5_row), SEEK_SET) != 0)
00097 {
00098 add_log(ADDLOG_FAIL, "[db5/dat]add", "unable to add database row\n");
00099 return false;
00100 }
00101 if (fwrite(row, sizeof(db5_row), 1, db5_dat) != 1)
00102 {
00103 add_log(ADDLOG_FAIL, "[db5/dat]add", "unable to write into database\n");
00104 return false;
00105 }
00106
00107
00108 if (db5_hdr_grow(1) != true)
00109 {
00110 add_log(ADDLOG_FAIL, "[db5/dat]add", "unable to update meta-database\n");
00111 return false;
00112 }
00113
00114 return true;
00115 }
00116
00117 bool db5_dat_delete_row(const uint32_t index)
00118 {
00119 db5_row row;
00120 uint32_t count;
00121
00122 count = db5_hdr_count();
00123
00124 if (index < 0 || index >= count)
00125 {
00126 add_log(ADDLOG_FAIL, "[db5/dat]delete", "index out of databse (%u)\n", index);
00127 return false;
00128 }
00129
00130 if (index != count-1)
00131 {
00132 if (db5_dat_select_row(count-1, &row) == false)
00133 {
00134 return false;
00135 }
00136
00137 if (db5_dat_update (index, &row) == false)
00138 {
00139 return false;
00140 }
00141 }
00142
00143
00144 if (db5_hdr_grow(-1) != true)
00145 {
00146 add_log(ADDLOG_FAIL, "[db5/dat]delete", "unable to update meta-database\n");
00147 return false;
00148 }
00149
00150
00151 if (!file_truncate(db5_dat, count*sizeof(db5_row)))
00152 {
00153 add_log(ADDLOG_FAIL, "[db5/dat]delete", "unable to resize database file\n");
00154 return false;
00155 }
00156
00157 return true;
00158 }
00159
00161 #define filename_size (membersizeof(db5_row, filename))
00162
00163 uint32_t db5_dat_select_by_filename(const char *filename)
00164 {
00165 char shortname [filename_size];
00166 uint32_t count, i;
00167 db5_row row;
00168
00169 check(filename != NULL);
00170
00171 strncpy(shortname, filename, filename_size/2);
00172 ws_atows(shortname, filename_size);
00173
00174 count = db5_hdr_count();
00175 for(i=0; i < count; i++)
00176 {
00177 if(!db5_dat_select_row(i, &row))
00178 {
00179 add_log(ADDLOG_FAIL, "[db5/dat]select_by_filename", "error reading database\n");
00180 return DB5_ROW_NOT_FOUND;
00181 }
00182
00183 if (memcmp(row.filename, shortname, filename_size) == 0)
00184 {
00185 return i;
00186 }
00187 }
00188
00189 return DB5_ROW_NOT_FOUND;
00190 }
00191