/* * Ffindex * written by Andy Hauser . * Please add your name here if you distribute modified versions. * * Ffindex is provided under the Create Commons license "Attribution-ShareAlike * 4.0", which basically captures the spirit of the Gnu Public License (GPL). * * See: * http://creativecommons.org/licenses/by-sa/4.0/ */ #define _GNU_SOURCE 1 #define _LARGEFILE64_SOURCE 1 #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include #include #include "ffindex.h" #include "ffutil.h" #define MAX_FILENAME_LIST_FILES 4096 void usage(char *program_name) { fprintf(stderr, "USAGE: %s [-s|-u|-v] [-f file]* index_filename [filename]*\n" "\t-f file\tfile each line containing a filename\n" "\t\t-f can be specified up to %d times\n" "\t-s\tsort index file\n" "\t-u\tunlink entry (remove from index only)\n" "\t-v\tprint version and other info then exit\n" "\nDesigned and implemented by Andreas W. Hauser .\n", program_name, MAX_FILENAME_LIST_FILES); } int main(int argn, char **argv) { int sort = 0, unlink = 0, version = 0; int err = EXIT_SUCCESS; char* list_filenames[MAX_FILENAME_LIST_FILES]; size_t list_filenames_index = 0; static struct option long_options[] = { { "file", required_argument, NULL, 'f' }, { "sort", no_argument, NULL, 's' }, { "unlink", no_argument, NULL, 'u' }, { "version", no_argument, NULL, 'v' }, { NULL, 0, NULL, 0 } }; int opt; while (1) { int option_index = 0; opt = getopt_long(argn, argv, "suvf:", long_options, &option_index); if (opt == -1) break; switch (opt) { case 'f': list_filenames[list_filenames_index++] = optarg; break; case 's': sort = 1; break; case 'u': unlink = 1; break; case 'v': version = 1; break; default: usage(argv[0]); return EXIT_FAILURE; } } if(version == 1) { /* Don't you dare running it on a platform where byte != 8 bits */ printf("%s version %.2f, off_t = %zd bits\n", argv[0], FFINDEX_VERSION, sizeof(off_t) * 8); return EXIT_SUCCESS; } if(optind >= argn) { usage(argv[0]); return EXIT_FAILURE; } char *index_filename = argv[optind++]; FILE *index_file; index_file = fopen(index_filename, "r+"); if(index_file == NULL) { perror(index_filename); return EXIT_FAILURE; } size_t entries = ffcount_lines(index_filename); ffindex_index_t* index = ffindex_index_parse(index_file, entries); if(index == NULL) { perror("ffindex_index_parse failed"); return (EXIT_FAILURE); } fclose(index_file); /* Unlink entries */ if(unlink) { /* For each list_file unlink all entries */ for(int i = 0; i < list_filenames_index; i++) { printf("Unlinking entries from '%s'\n", list_filenames[i]); FILE *list_file = fopen(list_filenames[i], "r"); if (list_file == NULL) { perror(list_filenames[i]); return EXIT_FAILURE; } /* unlink entries in file, one per line */ char path[PATH_MAX]; while(fgets(path, PATH_MAX, list_file) != NULL) { index = ffindex_unlink(index, ffnchomp(path, strlen(path))); } } /* unlink entries specified by args */ for(int i = optind; i < argn; i++) { index = ffindex_unlink(index, argv[i]); } /* Sort the index entries and write back */ if(sort) { ffindex_sort_index_file(index); index_file = fopen(index_filename, "w"); if(index_file == NULL) { perror(index_filename); return EXIT_FAILURE; } err += ffindex_write(index, index_file); } } /* Write index back */ index_file = fopen(index_filename, "w"); if(index_file == NULL) { perror(index_filename); return EXIT_FAILURE; } err += ffindex_write(index, index_file); return err; } /* vim: ts=2 sw=2 et */