2 * Copyright (C) 2009 Andre Noll <maan@tuebingen.mpg.de>
4 * Licensed under the GPL v2. For licencing details see COPYING.
8 * \file osltar.c A simple file archiver with many limitations. Do not use it.
9 * It is just an * example to illustrate programming with libosl.
17 #include <sys/types.h>
20 #include <sys/types.h>
26 /** The columns of the osl table. */
38 * Compare two osl objects of string type.
40 * \param obj1 Pointer to the first object.
41 * \param obj2 Pointer to the second object.
43 * \return It returns an integer less than, equal to, or greater than zero if
44 * \a obj1 is found, respectively, to be less than, to match, or be greater than
47 * \sa strcmp(3), strncmp(3), osl_compare_func.
49 static int string_compare(const struct osl_object *obj1, const struct osl_object *obj2)
51 const char *str1 = (const char *)obj1->data;
52 const char *str2 = (const char *)obj2->data;
53 return strcmp(str1, str2);
56 static struct osl_column_description tar_table_cols[] = {
58 .storage_type = OSL_MAPPED_STORAGE,
59 .storage_flags = OSL_RBTREE | OSL_UNIQUE,
61 .compare_function = string_compare,
64 .storage_type = OSL_MAPPED_STORAGE,
70 static struct osl_table *table;
72 static struct osl_table_description tar_table_desc = {
74 .num_columns = NUM_OT_COLUMNS,
76 .column_descriptions = tar_table_cols,
79 static void print_usage_and_die(void)
81 fprintf(stderr, "usage:\n\tosltar c <db_dir> <data_dir>\n");
82 fprintf(stderr, "\tosltar x <db_dir> file1 [file2...]\n");
83 fprintf(stderr, "\tosltar t <db_dir>\n");
88 * Open a file and map it into memory.
90 static int mmap_full_file(const char *path, void **map,
93 int fd, ret, mmap_prot, mmap_flags;
94 struct stat file_status;
96 mmap_prot = PROT_READ;
97 mmap_flags = MAP_PRIVATE;
98 ret = open(path, O_RDONLY, 0);
100 fprintf(stderr, "open: %s\n", strerror(errno));
104 if (fstat(fd, &file_status) < 0) {
106 fprintf(stderr, "fstat: %s\n", strerror(errno));
109 *size = file_status.st_size;
111 fprintf(stderr, "can not add empty file: %s\n", path);
114 *map = mmap(NULL, *size, mmap_prot, mmap_flags, fd, 0);
115 if (*map == MAP_FAILED) {
116 fprintf(stderr, "map failed: %s\n", path);
127 static int add_file(char *name)
130 struct osl_object objs[NUM_OT_COLUMNS] = {
133 .size = strlen(name) + 1
136 printf("%s\n", name);
137 ret = mmap_full_file(name, &objs[OTC_DATA].data,
138 &objs[OTC_DATA].size);
141 return osl_add_row(table, objs);
144 static int populate_table(const char *dirname)
146 struct dirent *entry;
148 int ret = chdir(dirname);
151 fprintf(stderr, "chdir: %s\n", strerror(errno));
156 fprintf(stderr, "opendir: %s\n", strerror(errno));
159 while ((entry = readdir(dir))) {
163 if (!strcmp(entry->d_name, "."))
165 if (!strcmp(entry->d_name, ".."))
167 if (lstat(entry->d_name, &s) == -1)
172 ret = add_file(entry->d_name);
182 static int com_create(int argc, char **argv)
188 print_usage_and_die();
189 if (lstat(argv[2], &statbuf) == -1) {
190 fprintf(stderr, "no such dir: %s\n", argv[2]);
193 if (!S_ISDIR(statbuf.st_mode)) {
194 fprintf(stderr, "not a dir: %s\n", argv[2]);
197 tar_table_desc.dir = argv[1];
198 ret = osl_create_table(&tar_table_desc);
200 fprintf(stderr, "failed to create table\n");
204 ret = osl_open_table(&tar_table_desc, &table);
206 fprintf(stderr, "osl_open_table: %s\n", osl_strerror(-ret));
209 ret = populate_table(argv[2]);
210 osl_close_table(table, OSL_MARK_CLEAN);
211 return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
215 * Write the whole buffer to a file descriptor.
217 static ssize_t write_all(int fd, const void *buf, size_t size)
221 ssize_t ret = write(fd, b, size);
223 fprintf(stderr, "open: %s\n", strerror(errno));
234 * Open a file, write the given buffer and close the file.
236 static int write_file(const char *filename, const void *buf, size_t size)
240 ret = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0644);
242 fprintf(stderr, "open: %s\n", strerror(errno));
247 printf("%s\n", filename);
248 ret = write_all(fd, buf, size);
257 static int extract_file(char *name)
261 struct osl_object obj = {.data = name, .size = strlen(name) + 1};
263 ret = osl_get_row(table, OTC_NAME, &obj, &row);
265 fprintf(stderr, "osl_get_row(%s): %s\n", name,
269 ret = osl_get_object(table, row, OTC_DATA, &obj);
271 fprintf(stderr, "osl_get_object: %s\n", osl_strerror(-ret));
274 return write_file(name, obj.data, obj.size);
277 static int com_extract(int argc, char **argv)
282 print_usage_and_die();
283 tar_table_desc.dir = argv[1];
284 ret = osl_open_table(&tar_table_desc, &table);
286 fprintf(stderr, "osl_open_table: %s\n", osl_strerror(-ret));
290 for (i = 2; i < argc; i++) {
291 ret = extract_file(argv[i]);
296 osl_close_table(table, OSL_MARK_CLEAN);
300 static int list_entry(struct osl_row *row, void *data)
302 struct osl_object obj;
303 int ret = osl_get_object(table, row, OTC_NAME, &obj);
305 fprintf(stderr, "osl_get_object: %s\n", osl_strerror(-ret));
308 printf("%s\n", (char *)obj.data);
312 static int com_list(int argc, char **argv)
317 print_usage_and_die();
318 tar_table_desc.dir = argv[1];
319 ret = osl_open_table(&tar_table_desc, &table);
321 fprintf(stderr, "osl_open_table: %s\n", osl_strerror(-ret));
325 ret = osl_rbtree_loop(table, OTC_NAME, NULL, list_entry);
326 osl_close_table(table, OSL_MARK_CLEAN);
331 * The osltar main funcion.
333 * \param argc Usual argument count.
334 * \param argv Usual argument vector.
336 int main(int argc, char **argv)
339 print_usage_and_die();
340 if (!strcmp(argv[1], "c"))
341 return com_create(argc - 1, argv + 1);
342 if (!strcmp(argv[1], "x"))
343 return com_extract(argc - 1, argv + 1);
344 if (!strcmp(argv[1], "t"))
345 return com_list(argc - 1, argv + 1);
346 print_usage_and_die();