00001
00007 #include <limits.h>
00008 #include <stdbool.h>
00009 #include <stdint.h>
00010 #include <stdio.h>
00011 #include <stdlib.h>
00012 #include <string.h>
00013
00014 #include "check.h"
00015 #include "config.h"
00016 #include "crc32.h"
00017 #include "db5_types.h"
00018 #include "file.h"
00019 #include "logger.h"
00020 #include "names.h"
00021 #include "utf8.h"
00022
00026 typedef struct name_trans_t
00027 {
00029 uint32_t crc32;
00031 char *longname;
00033 struct name_trans_t *next;
00034 } name_trans;
00035
00037 static name_trans *head, *tail;
00038
00044 static void names_insert_full(const uint32_t crc32, const char *filename)
00045 {
00046 size_t length;
00047
00048 check(crc32 != 0);
00049 check(filename != NULL);
00050
00051 if (head == NULL)
00052 {
00053 head = malloc(sizeof(name_trans));
00054 check(head != NULL);
00055
00056 tail = head;
00057 }
00058 else
00059 {
00060 tail->next = malloc(sizeof(name_trans));
00061 check(tail->next != NULL);
00062
00063 tail = tail->next;
00064 }
00065
00066 length = strlen(filename);
00067
00068 tail->longname = malloc(length+1);
00069 check(tail->longname != NULL);
00070 strncpy(tail->longname, filename, length+1);
00071
00072 tail->crc32 = crc32;
00073 tail->next = NULL;
00074 }
00075
00080 static void names_free_row(name_trans *current)
00081 {
00082 check(current != NULL);
00083
00084 free(current->longname);
00085 free(current);
00086 }
00087
00088 bool names_select_shortname(const char *filename, char *shortname, const size_t shortname_size)
00089 {
00090 name_trans *current;
00091 const char *ext;
00092
00093 check(filename != NULL);
00094 check(shortname != NULL);
00095 check(shortname_size > 0);
00096
00097 if (shortname_size != 0)
00098 {
00099 shortname[0] = '\0';
00100 }
00101
00102 ext = file_get_extension(filename);
00103 if (ext == NULL)
00104 {
00105 add_log(ADDLOG_USER_ERROR, "[names]select_short", "unable to get extension\n");
00106 log_dump_latin1("filename", filename);
00107 return false;
00108 }
00109
00110 current = head;
00111 while(current != NULL)
00112 {
00113 if (strcmp(filename, current->longname) == 0)
00114 {
00115
00116 if (snprintf(shortname, shortname_size, "%x%s", current->crc32, ext) >= shortname_size)
00117 {
00118 return false;
00119 }
00120 return true;
00121 }
00122 current = current->next;
00123 }
00124
00125 return false;
00126 }
00127
00133 static const char *names_select_by_crc(const uint32_t crc32)
00134 {
00135 name_trans *current;
00136
00137 check(crc32 != 0);
00138
00139 current = head;
00140 while(current != NULL)
00141 {
00142 if (current->crc32 == crc32)
00143 {
00144 return current->longname;
00145 }
00146 current = current->next;
00147 }
00148 return NULL;
00149 }
00150
00151 bool names_init()
00152 {
00153 char shortname[PATH_MAX], longname[PATH_MAX];
00154 FILE *names;
00155 int length;
00156 uint32_t crc32;
00157
00158 crc32_init();
00159
00160 head = NULL;
00161 tail = NULL;
00162
00163 names = file_fcaseopen(".", CONFIG_NAMES_FILE, "rt");
00164 if (names == NULL)
00165 {
00166 add_log(ADDLOG_FAIL, "[names]init", "unable to load database\n");
00167 }
00168 else
00169 {
00170
00171 while(!feof(names))
00172 {
00173 if (fgets(shortname, sizeof(shortname), names) && fgets(longname, sizeof(longname), names))
00174 {
00175 for(length = 0; longname[length] != '\0'; length++)
00176 {
00177 if ((longname[length] == '\r') || (longname[length] == '\n'))
00178 {
00179 longname[length] = '\0';
00180 break;
00181 }
00182 }
00183 crc32 = strtoul(shortname, NULL, 16);
00184
00185 names_insert_full(crc32, longname);
00186 }
00187 }
00188 fclose(names);
00189 }
00190
00191 if (head == NULL)
00192 {
00193 add_log(ADDLOG_NOTICE, "[names]init", "name database is empty\n");
00194 }
00195
00196 return true;
00197 }
00198
00199 void names_insert(const char *filename)
00200 {
00201 uint32_t crc32;
00202
00203 check(filename != NULL);
00204
00205 crc32 = strcrc32(filename);
00206
00207 add_log(ADDLOG_DEBUG, "[names]insert", "insert a new file, crc32=%08x\n", crc32);
00208 log_dump_latin1("filename", filename);
00209
00210 names_insert_full(crc32, filename);
00211
00212 if (!names_save())
00213 {
00214 add_log(ADDLOG_RECOVER, "[names]insert", "error while saving names list\n");
00215 log_dump_latin1("filename", filename);
00216 }
00217
00218 add_log(ADDLOG_DEBUG, "[names]insert", "done.\n");
00219 }
00220
00221 const char *names_select_longname(const char *shortname)
00222 {
00223 const char *result;
00224 uint32_t crc32;
00225
00226 check(shortname != NULL);
00227
00228
00229 crc32 = strtoul(shortname, NULL, 16);
00230 if (crc32 == 0)
00231 {
00232 return shortname;
00233 }
00234
00235
00236 result = names_select_by_crc(crc32);
00237 if (result == NULL)
00238 {
00239 return shortname;
00240 }
00241
00242 return result;
00243 }
00244
00245 bool names_generate_shortname(const char *longname, char *shortname, const size_t shortname_size)
00246 {
00247 const char *ext;
00248 uint32_t crc32;
00249
00250 check(longname != NULL);
00251 check(shortname != NULL);
00252 check(shortname_size > 0);
00253
00254 ext = file_get_extension(longname);
00255
00256
00257 crc32 = strcrc32(longname);
00258
00259
00260 if (snprintf(shortname, shortname_size, "%x%s", crc32, ext) >= shortname_size)
00261 {
00262 return false;
00263 }
00264
00265 return true;
00266 }
00267
00268 bool names_save()
00269 {
00270 char *ext;
00271 FILE *names;
00272 name_trans *current;
00273
00274 current = head;
00275
00276 names = file_fcaseopen(".", CONFIG_NAMES_FILE, "wb");
00277 if (names == NULL)
00278 {
00279 add_log(ADDLOG_FAIL, "[names]save", "unable to save database\n");
00280 return false;
00281 }
00282
00283 while(current != NULL)
00284 {
00285 check(current->longname != NULL);
00286 ext = strrchr(current->longname, '.');
00287
00288 fprintf(names, "%x%s\r\n%s\r\n", current->crc32, ext, current->longname);
00289
00290 current = current->next;
00291 }
00292
00293 fclose(names);
00294
00295 return true;
00296 }
00297
00298 bool names_delete(const char *filename)
00299 {
00300 name_trans *previous;
00301 name_trans *current;
00302
00303 check(filename != NULL);
00304
00305 previous = NULL;
00306 current = head;
00307
00308 while(current != NULL)
00309 {
00310
00311 if (strcmp(filename, current->longname) == 0)
00312 {
00313
00314 if (head == current && tail == current)
00315 {
00316 head = NULL, tail = NULL;
00317 names_free_row(current);
00318 }
00319
00320 else if (head == current)
00321 {
00322 head = current->next;
00323 names_free_row(current);
00324 }
00325
00326 else if (tail == current)
00327 {
00328 tail = previous;
00329 tail->next = NULL;
00330 names_free_row(current);
00331 }
00332
00333 else
00334 {
00335 previous->next = current->next;
00336 names_free_row(current);
00337 }
00338
00339 if (!names_save())
00340 {
00341 add_log(ADDLOG_RECOVER, "[names]insert", "error while saving names list\n");
00342 }
00343 return true;
00344 }
00345 previous = current, current = current->next;
00346 }
00347 return false;
00348 }
00349
00350 void names_print()
00351 {
00352 name_trans *current;
00353
00354 current = head;
00355 while(current != NULL)
00356 {
00357 add_log(ADDLOG_DUMP, "[names]print", "checksum %08x\n", current->crc32);
00358 log_dump_latin1("current->filename", current->longname);
00359 current = current->next;
00360 }
00361 }
00362
00363 void names_free()
00364 {
00365 name_trans *current;
00366
00367 while(head != NULL)
00368 {
00369 current = head;
00370 head = head->next;
00371 names_free_row(current);
00372 }
00373 }
00374