nsxivff013dd
Revised handling of file names & paths
+100 −81
10 files changed
- M Makefile +1 −1
- M events.c +15 −15
- M image.c +4 −4
- M image.h +1 −1
- M main.c +41 −28
- M thumbs.c +19 −30
- M thumbs.h +2 −2
- M types.h +5 −0
- M util.c +11 −0
- M util.h +1 −0
| @@ -1,6 +1,6 @@ | |||
| 1 | 1 | all: sxiv | |
| 2 | 2 | ||
| 3 | − | VERSION = 0.9 | |
| 3 | + | VERSION = git-20110818 | |
| 4 | 4 | ||
| 5 | 5 | CC = gcc | |
| 6 | 6 | DESTDIR = | |
| @@ -52,7 +52,7 @@ extern img_t img; | |||
| 52 | 52 | extern tns_t tns; | |
| 53 | 53 | extern win_t win; | |
| 54 | 54 | ||
| 55 | − | extern char **filenames; | |
| 55 | + | extern fileinfo_t *files; | |
| 56 | 56 | extern int filecnt, fileidx; | |
| 57 | 57 | ||
| 58 | 58 | int timo_cursor; | |
| @@ -163,7 +163,7 @@ void run() { | |||
| 163 | 163 | gettimeofday(&t0, 0); | |
| 164 | 164 | ||
| 165 | 165 | while (tns.cnt < filecnt && !XPending(win.env.dpy)) { | |
| 166 | − | if (tns_load(&tns, tns.cnt, filenames[tns.cnt], 0)) | |
| 166 | + | if (tns_load(&tns, tns.cnt, &files[tns.cnt], 0)) | |
| 167 | 167 | tns.cnt++; | |
| 168 | 168 | else | |
| 169 | 169 | remove_file(tns.cnt, 0); | |
| @@ -513,7 +513,7 @@ int open_with(arg_t a) { | |||
| 513 | 513 | ||
| 514 | 514 | if((pid = fork()) == 0) { | |
| 515 | 515 | execlp(prog, prog, | |
| 516 | − | filenames[mode == MODE_NORMAL ? fileidx : tns.sel], NULL); | |
| 516 | + | files[mode == MODE_NORMAL ? fileidx : tns.sel].path, NULL); | |
| 517 | 517 | warn("could not exec: %s", prog); | |
| 518 | 518 | exit(1); | |
| 519 | 519 | } else if (pid < 0) { | |
| @@ -526,30 +526,30 @@ int open_with(arg_t a) { | |||
| 526 | 526 | int run_command(arg_t a) { | |
| 527 | 527 | const char *cline = (const char*) a; | |
| 528 | 528 | char *cn, *cmdline; | |
| 529 | − | const char *co, *fname; | |
| 530 | − | int fncnt, fnlen, status; | |
| 529 | + | const char *co, *fpath; | |
| 530 | + | int fpcnt, fplen, status; | |
| 531 | 531 | pid_t pid; | |
| 532 | 532 | ||
| 533 | 533 | if (!cline || !*cline) | |
| 534 | 534 | return 0; | |
| 535 | 535 | ||
| 536 | 536 | /* build command line: */ | |
| 537 | − | fncnt = 0; | |
| 537 | + | fpcnt = 0; | |
| 538 | 538 | co = cline - 1; | |
| 539 | 539 | while ((co = strchr(co + 1, '#'))) | |
| 540 | − | fncnt++; | |
| 541 | − | if (!fncnt) | |
| 540 | + | fpcnt++; | |
| 541 | + | if (!fpcnt) | |
| 542 | 542 | return 0; | |
| 543 | − | fname = filenames[mode == MODE_NORMAL ? fileidx : tns.sel]; | |
| 544 | − | fnlen = strlen(fname); | |
| 545 | − | cn = cmdline = (char*) s_malloc((strlen(cline) + fncnt * (fnlen + 2)) * | |
| 543 | + | fpath = files[mode == MODE_NORMAL ? fileidx : tns.sel].path; | |
| 544 | + | fplen = strlen(fpath); | |
| 545 | + | cn = cmdline = (char*) s_malloc((strlen(cline) + fpcnt * (fplen + 2)) * | |
| 546 | 546 | sizeof(char)); | |
| 547 | 547 | /* replace all '#' with filename: */ | |
| 548 | 548 | for (co = cline; *co; co++) { | |
| 549 | 549 | if (*co == '#') { | |
| 550 | 550 | *cn++ = '"'; | |
| 551 | − | strcpy(cn, fname); | |
| 552 | − | cn += fnlen; | |
| 551 | + | strcpy(cn, fpath); | |
| 552 | + | cn += fplen; | |
| 553 | 553 | *cn++ = '"'; | |
| 554 | 554 | } else { | |
| 555 | 555 | *cn++ = *co; | |
| @@ -575,11 +575,11 @@ int run_command(arg_t a) { | |||
| 575 | 575 | ||
| 576 | 576 | if (mode == MODE_NORMAL) { | |
| 577 | 577 | if (fileidx < tns.cnt) | |
| 578 | − | tns_load(&tns, fileidx, filenames[fileidx], 1); | |
| 578 | + | tns_load(&tns, fileidx, &files[fileidx], 1); | |
| 579 | 579 | img_close(&img, 1); | |
| 580 | 580 | load_image(fileidx); | |
| 581 | 581 | } else { | |
| 582 | − | if (!tns_load(&tns, tns.sel, filenames[tns.sel], 0)) { | |
| 582 | + | if (!tns_load(&tns, tns.sel, &files[tns.sel], 0)) { | |
| 583 | 583 | remove_file(tns.sel, 0); | |
| 584 | 584 | tns.dirty = 1; | |
| 585 | 585 | if (tns.sel >= tns.cnt) | |
| @@ -50,12 +50,12 @@ void img_init(img_t *img, win_t *win) { | |||
| 50 | 50 | } | |
| 51 | 51 | } | |
| 52 | 52 | ||
| 53 | − | int img_load(img_t *img, const char *filename) { | |
| 54 | − | if (!img || !filename) | |
| 53 | + | int img_load(img_t *img, const fileinfo_t *file) { | |
| 54 | + | if (!img || !file || !file->name || !file->path) | |
| 55 | 55 | return 0; | |
| 56 | 56 | ||
| 57 | − | if (access(filename, R_OK) || !(img->im = imlib_load_image(filename))) { | |
| 58 | − | warn("could not open image: %s", filename); | |
| 57 | + | if (access(file->path, R_OK) || !(img->im = imlib_load_image(file->path))) { | |
| 58 | + | warn("could not open image: %s", file->name); | |
| 59 | 59 | return 0; | |
| 60 | 60 | } | |
| 61 | 61 | ||
| @@ -43,7 +43,7 @@ typedef struct { | |||
| 43 | 43 | ||
| 44 | 44 | void img_init(img_t*, win_t*); | |
| 45 | 45 | ||
| 46 | − | int img_load(img_t*, const char*); | |
| 46 | + | int img_load(img_t*, const fileinfo_t*); | |
| 47 | 47 | void img_close(img_t*, int); | |
| 48 | 48 | ||
| 49 | 49 | void img_render(img_t*, win_t*); | |
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | #include "image.h" | |
| 26 | 26 | #include "options.h" | |
| 27 | 27 | #include "thumbs.h" | |
| 28 | + | #include "types.h" | |
| 28 | 29 | #include "util.h" | |
| 29 | 30 | #include "window.h" | |
| 30 | 31 | ||
| @@ -38,7 +39,7 @@ img_t img; | |||
| 38 | 39 | tns_t tns; | |
| 39 | 40 | win_t win; | |
| 40 | 41 | ||
| 41 | − | char **filenames; | |
| 42 | + | fileinfo_t *files; | |
| 42 | 43 | int filecnt, fileidx; | |
| 43 | 44 | size_t filesize; | |
| 44 | 45 | ||
| @@ -54,21 +55,30 @@ void cleanup() { | |||
| 54 | 55 | } | |
| 55 | 56 | } | |
| 56 | 57 | ||
| 57 | − | int check_add_file(char *filename) { | |
| 58 | − | if (!filename) | |
| 59 | − | return 0; | |
| 58 | + | void check_add_file(char *filename) { | |
| 59 | + | if (!filename || !*filename) | |
| 60 | + | return; | |
| 60 | 61 | ||
| 61 | 62 | if (access(filename, R_OK)) { | |
| 62 | 63 | warn("could not open file: %s", filename); | |
| 63 | − | return 0; | |
| 64 | − | } else { | |
| 65 | − | if (fileidx == filecnt) { | |
| 66 | − | filecnt *= 2; | |
| 67 | − | filenames = (char**) s_realloc(filenames, filecnt * sizeof(char*)); | |
| 64 | + | return; | |
| 65 | + | } | |
| 66 | + | ||
| 67 | + | if (fileidx == filecnt) { | |
| 68 | + | filecnt *= 2; | |
| 69 | + | files = (fileinfo_t*) s_realloc(files, filecnt * sizeof(fileinfo_t)); | |
| 70 | + | } | |
| 71 | + | if (*filename != '/') { | |
| 72 | + | files[fileidx].path = absolute_path(filename); | |
| 73 | + | if (!files[fileidx].path) { | |
| 74 | + | warn("could not get absolute path of file: %s\n", filename); | |
| 75 | + | return; | |
| 68 | 76 | } | |
| 69 | − | filenames[fileidx++] = filename; | |
| 70 | − | return 1; | |
| 71 | 77 | } | |
| 78 | + | files[fileidx].name = s_strdup(filename); | |
| 79 | + | if (*filename == '/') | |
| 80 | + | files[fileidx].path = files[fileidx].name; | |
| 81 | + | fileidx++; | |
| 72 | 82 | } | |
| 73 | 83 | ||
| 74 | 84 | void remove_file(int n, unsigned char silent) { | |
| @@ -82,9 +92,12 @@ void remove_file(int n, unsigned char silent) { | |||
| 82 | 92 | exit(!silent); | |
| 83 | 93 | } | |
| 84 | 94 | ||
| 85 | − | if (n + 1 < filecnt) | |
| 86 | − | memmove(filenames + n, filenames + n + 1, (filecnt - n - 1) * | |
| 87 | − | sizeof(char*)); | |
| 95 | + | if (n + 1 < filecnt) { | |
| 96 | + | if (files[n].path != files[n].name) | |
| 97 | + | free((void*) files[n].path); | |
| 98 | + | free((void*) files[n].name); | |
| 99 | + | memmove(files + n, files + n + 1, (filecnt - n - 1) * sizeof(fileinfo_t)); | |
| 100 | + | } | |
| 88 | 101 | if (n + 1 < tns.cnt) { | |
| 89 | 102 | memmove(tns.thumbs + n, tns.thumbs + n + 1, (tns.cnt - n - 1) * | |
| 90 | 103 | sizeof(thumb_t)); | |
| @@ -106,14 +119,14 @@ void load_image(int new) { | |||
| 106 | 119 | win_set_cursor(&win, CURSOR_WATCH); | |
| 107 | 120 | img_close(&img, 0); | |
| 108 | 121 | ||
| 109 | − | while (!img_load(&img, filenames[new])) { | |
| 122 | + | while (!img_load(&img, &files[new])) { | |
| 110 | 123 | remove_file(new, 0); | |
| 111 | 124 | if (new >= filecnt) | |
| 112 | 125 | new = filecnt - 1; | |
| 113 | 126 | } | |
| 114 | 127 | ||
| 115 | 128 | fileidx = new; | |
| 116 | − | if (!stat(filenames[new], &fstats)) | |
| 129 | + | if (!stat(files[new].path, &fstats)) | |
| 117 | 130 | filesize = fstats.st_size; | |
| 118 | 131 | else | |
| 119 | 132 | filesize = 0; | |
| @@ -127,14 +140,14 @@ void update_title() { | |||
| 127 | 140 | if (mode == MODE_THUMBS) { | |
| 128 | 141 | n = snprintf(win_title, TITLE_LEN, "sxiv: [%d/%d] %s", | |
| 129 | 142 | tns.cnt ? tns.sel + 1 : 0, tns.cnt, | |
| 130 | − | tns.cnt ? filenames[tns.sel] : ""); | |
| 143 | + | tns.cnt ? files[tns.sel].name : ""); | |
| 131 | 144 | } else { | |
| 132 | 145 | size = filesize; | |
| 133 | 146 | size_readable(&size, &unit); | |
| 134 | 147 | n = snprintf(win_title, TITLE_LEN, | |
| 135 | 148 | "sxiv: [%d/%d] <%d%%> <%dx%d> (%.2f%s) %s", | |
| 136 | 149 | fileidx + 1, filecnt, (int) (img.zoom * 100.0), img.w, img.h, | |
| 137 | − | size, unit, filenames[fileidx]); | |
| 150 | + | size, unit, files[fileidx].name); | |
| 138 | 151 | } | |
| 139 | 152 | ||
| 140 | 153 | if (n >= TITLE_LEN) { | |
| @@ -146,13 +159,13 @@ void update_title() { | |||
| 146 | 159 | } | |
| 147 | 160 | ||
| 148 | 161 | int fncmp(const void *a, const void *b) { | |
| 149 | − | return strcoll(*((char* const*) a), *((char* const*) b)); | |
| 162 | + | return strcoll(((fileinfo_t*) a)->name, ((fileinfo_t*) b)->name); | |
| 150 | 163 | } | |
| 151 | 164 | ||
| 152 | 165 | int main(int argc, char **argv) { | |
| 153 | 166 | int i, len, start; | |
| 154 | 167 | size_t n; | |
| 155 | − | char *filename = NULL; | |
| 168 | + | char *filename; | |
| 156 | 169 | struct stat fstats; | |
| 157 | 170 | r_dir_t dir; | |
| 158 | 171 | ||
| @@ -174,17 +187,16 @@ int main(int argc, char **argv) { | |||
| 174 | 187 | else | |
| 175 | 188 | filecnt = options->filecnt; | |
| 176 | 189 | ||
| 177 | − | filenames = (char**) s_malloc(filecnt * sizeof(char*)); | |
| 190 | + | files = (fileinfo_t*) s_malloc(filecnt * sizeof(fileinfo_t)); | |
| 178 | 191 | fileidx = 0; | |
| 179 | 192 | ||
| 180 | 193 | /* build file list: */ | |
| 181 | 194 | if (options->from_stdin) { | |
| 195 | + | filename = NULL; | |
| 182 | 196 | while ((len = getline(&filename, &n, stdin)) > 0) { | |
| 183 | 197 | if (filename[len-1] == '\n') | |
| 184 | 198 | filename[len-1] = '\0'; | |
| 185 | − | if (!*filename || !check_add_file(filename)) | |
| 186 | − | free(filename); | |
| 187 | − | filename = NULL; | |
| 199 | + | check_add_file(filename); | |
| 188 | 200 | } | |
| 189 | 201 | } else { | |
| 190 | 202 | for (i = 0; i < options->filecnt; i++) { | |
| @@ -202,13 +214,14 @@ int main(int argc, char **argv) { | |||
| 202 | 214 | continue; | |
| 203 | 215 | } | |
| 204 | 216 | start = fileidx; | |
| 217 | + | printf("reading dir: %s\n", filename); | |
| 205 | 218 | while ((filename = r_readdir(&dir))) { | |
| 206 | − | if (!check_add_file(filename)) | |
| 207 | − | free((void*) filename); | |
| 219 | + | check_add_file(filename); | |
| 220 | + | free((void*) filename); | |
| 208 | 221 | } | |
| 209 | 222 | r_closedir(&dir); | |
| 210 | 223 | if (fileidx - start > 1) | |
| 211 | − | qsort(filenames + start, fileidx - start, sizeof(char*), fncmp); | |
| 224 | + | qsort(files + start, fileidx - start, sizeof(fileinfo_t), fncmp); | |
| 212 | 225 | } | |
| 213 | 226 | } | |
| 214 | 227 | } | |
| @@ -227,7 +240,7 @@ int main(int argc, char **argv) { | |||
| 227 | 240 | if (options->thumbnails) { | |
| 228 | 241 | mode = MODE_THUMBS; | |
| 229 | 242 | tns_init(&tns, filecnt); | |
| 230 | − | while (!tns_load(&tns, 0, filenames[0], 0)) | |
| 243 | + | while (!tns_load(&tns, 0, &files[0], 0)) | |
| 231 | 244 | remove_file(0, 0); | |
| 232 | 245 | tns.cnt = 1; | |
| 233 | 246 | } else { | |
| @@ -44,45 +44,34 @@ int tns_cache_enabled() { | |||
| 44 | 44 | !access(cache_dir, W_OK); | |
| 45 | 45 | } | |
| 46 | 46 | ||
| 47 | − | char* tns_cache_filename(const char *filename) { | |
| 47 | + | char* tns_cache_filepath(const char *filepath) { | |
| 48 | 48 | size_t len; | |
| 49 | 49 | char *cfile = NULL; | |
| 50 | − | const char *abspath; | |
| 51 | 50 | ||
| 52 | − | if (!cache_dir || !filename) | |
| 51 | + | if (!cache_dir || !filepath || *filepath != '/') | |
| 53 | 52 | return NULL; | |
| 54 | 53 | ||
| 55 | − | if (*filename != '/') { | |
| 56 | − | if (!(abspath = absolute_path(filename))) | |
| 57 | − | return NULL; | |
| 58 | − | } else { | |
| 59 | − | abspath = filename; | |
| 60 | − | } | |
| 61 | − | ||
| 62 | − | if (strncmp(abspath, cache_dir, strlen(cache_dir))) { | |
| 63 | − | len = strlen(cache_dir) + strlen(abspath) + 6; | |
| 54 | + | if (strncmp(filepath, cache_dir, strlen(cache_dir))) { | |
| 55 | + | len = strlen(cache_dir) + strlen(filepath) + 6; | |
| 64 | 56 | cfile = (char*) s_malloc(len); | |
| 65 | − | snprintf(cfile, len, "%s/%s.png", cache_dir, abspath + 1); | |
| 57 | + | snprintf(cfile, len, "%s/%s.png", cache_dir, filepath + 1); | |
| 66 | 58 | } | |
| 67 | 59 | ||
| 68 | − | if (abspath != filename) | |
| 69 | − | free((void*) abspath); | |
| 70 | − | ||
| 71 | 60 | return cfile; | |
| 72 | 61 | } | |
| 73 | 62 | ||
| 74 | − | Imlib_Image* tns_cache_load(const char *filename) { | |
| 63 | + | Imlib_Image* tns_cache_load(const char *filepath) { | |
| 75 | 64 | char *cfile; | |
| 76 | 65 | struct stat cstats, fstats; | |
| 77 | 66 | Imlib_Image *im = NULL; | |
| 78 | 67 | ||
| 79 | − | if (!filename) | |
| 68 | + | if (!filepath) | |
| 80 | 69 | return NULL; | |
| 81 | 70 | ||
| 82 | − | if (stat(filename, &fstats)) | |
| 71 | + | if (stat(filepath, &fstats)) | |
| 83 | 72 | return NULL; | |
| 84 | 73 | ||
| 85 | − | if ((cfile = tns_cache_filename(filename))) { | |
| 74 | + | if ((cfile = tns_cache_filepath(filepath))) { | |
| 86 | 75 | if (!stat(cfile, &cstats) && | |
| 87 | 76 | cstats.st_mtim.tv_sec == fstats.st_mtim.tv_sec && | |
| 88 | 77 | cstats.st_mtim.tv_nsec / 1000 == fstats.st_mtim.tv_nsec / 1000) | |
| @@ -101,13 +90,13 @@ void tns_cache_write(thumb_t *t, Bool force) { | |||
| 101 | 90 | struct timeval times[2]; | |
| 102 | 91 | Imlib_Load_Error err = 0; | |
| 103 | 92 | ||
| 104 | − | if (!t || !t->im || !t->filename) | |
| 93 | + | if (!t || !t->im || !t->file || !t->file->name || !t->file->path) | |
| 105 | 94 | return; | |
| 106 | 95 | ||
| 107 | − | if (stat(t->filename, &fstats)) | |
| 96 | + | if (stat(t->file->path, &fstats)) | |
| 108 | 97 | return; | |
| 109 | 98 | ||
| 110 | − | if ((cfile = tns_cache_filename(t->filename))) { | |
| 99 | + | if ((cfile = tns_cache_filepath(t->file->path))) { | |
| 111 | 100 | if (force || stat(cfile, &cstats) || | |
| 112 | 101 | cstats.st_mtim.tv_sec != fstats.st_mtim.tv_sec || | |
| 113 | 102 | cstats.st_mtim.tv_nsec / 1000 != fstats.st_mtim.tv_nsec / 1000) | |
| @@ -125,7 +114,7 @@ void tns_cache_write(thumb_t *t, Bool force) { | |||
| 125 | 114 | } | |
| 126 | 115 | ||
| 127 | 116 | if (err) { | |
| 128 | − | warn("could not cache thumbnail: %s", t->filename); | |
| 117 | + | warn("could not cache thumbnail: %s", t->file->name); | |
| 129 | 118 | } else { | |
| 130 | 119 | TIMESPEC_TO_TIMEVAL(×[0], &fstats.st_atim); | |
| 131 | 120 | TIMESPEC_TO_TIMEVAL(×[1], &fstats.st_mtim); | |
| @@ -223,21 +212,21 @@ void tns_free(tns_t *tns) { | |||
| 223 | 212 | } | |
| 224 | 213 | } | |
| 225 | 214 | ||
| 226 | − | int tns_load(tns_t *tns, int n, const char *filename, unsigned char silent) { | |
| 215 | + | int tns_load(tns_t *tns, int n, const fileinfo_t *file, unsigned char silent) { | |
| 227 | 216 | int w, h; | |
| 228 | 217 | int use_cache, cached = 0; | |
| 229 | 218 | float z, zw, zh; | |
| 230 | 219 | thumb_t *t; | |
| 231 | 220 | Imlib_Image *im; | |
| 232 | 221 | ||
| 233 | − | if (!tns || !tns->thumbs || !filename) | |
| 222 | + | if (!tns || !tns->thumbs || !file || !file->name || !file->path) | |
| 234 | 223 | return 0; | |
| 235 | 224 | ||
| 236 | 225 | if (n < 0 || n >= tns->cap) | |
| 237 | 226 | return 0; | |
| 238 | 227 | ||
| 239 | 228 | t = &tns->thumbs[n]; | |
| 240 | − | t->filename = filename; | |
| 229 | + | t->file = file; | |
| 241 | 230 | ||
| 242 | 231 | if (t->im) { | |
| 243 | 232 | imlib_context_set_image(t->im); | |
| @@ -245,15 +234,15 @@ int tns_load(tns_t *tns, int n, const char *filename, unsigned char silent) { | |||
| 245 | 234 | } | |
| 246 | 235 | ||
| 247 | 236 | if ((use_cache = tns_cache_enabled())) { | |
| 248 | − | if ((im = tns_cache_load(filename))) | |
| 237 | + | if ((im = tns_cache_load(file->path))) | |
| 249 | 238 | cached = 1; | |
| 250 | 239 | } | |
| 251 | 240 | ||
| 252 | 241 | if (!cached && | |
| 253 | − | (access(filename, R_OK) || !(im = imlib_load_image(filename)))) | |
| 242 | + | (access(file->path, R_OK) || !(im = imlib_load_image(file->path)))) | |
| 254 | 243 | { | |
| 255 | 244 | if (!silent) | |
| 256 | − | warn("could not open image: %s", filename); | |
| 245 | + | warn("could not open image: %s", file->name); | |
| 257 | 246 | return 0; | |
| 258 | 247 | } | |
| 259 | 248 | ||
| @@ -26,7 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | 27 | typedef struct { | |
| 28 | 28 | Imlib_Image *im; | |
| 29 | − | const char *filename; | |
| 29 | + | const fileinfo_t *file; | |
| 30 | 30 | int x; | |
| 31 | 31 | int y; | |
| 32 | 32 | int w; | |
| @@ -51,7 +51,7 @@ void tns_clean_cache(tns_t*); | |||
| 51 | 51 | void tns_init(tns_t*, int); | |
| 52 | 52 | void tns_free(tns_t*); | |
| 53 | 53 | ||
| 54 | − | int tns_load(tns_t*, int, const char*, unsigned char); | |
| 54 | + | int tns_load(tns_t*, int, const fileinfo_t*, unsigned char); | |
| 55 | 55 | ||
| 56 | 56 | void tns_render(tns_t*, win_t*); | |
| 57 | 57 | void tns_highlight(tns_t*, win_t*, int, Bool); | |
| @@ -26,4 +26,9 @@ typedef enum { | |||
| 26 | 26 | CURSOR_WATCH | |
| 27 | 27 | } cursor_t; | |
| 28 | 28 | ||
| 29 | + | typedef struct { | |
| 30 | + | const char *name; | |
| 31 | + | const char *path; | |
| 32 | + | } fileinfo_t; | |
| 33 | + | ||
| 29 | 34 | #endif /* TYPES_H */ | |
| @@ -47,6 +47,17 @@ void* s_realloc(void *ptr, size_t size) { | |||
| 47 | 47 | return ptr; | |
| 48 | 48 | } | |
| 49 | 49 | ||
| 50 | + | char* s_strdup(char *s) { | |
| 51 | + | char *d = NULL; | |
| 52 | + | ||
| 53 | + | if (s) { | |
| 54 | + | if (!(d = malloc(strlen(s) + 1))) | |
| 55 | + | die("could not allocate memory"); | |
| 56 | + | strcpy(d, s); | |
| 57 | + | } | |
| 58 | + | return d; | |
| 59 | + | } | |
| 60 | + | ||
| 50 | 61 | void warn(const char* fmt, ...) { | |
| 51 | 62 | va_list args; | |
| 52 | 63 | ||
| @@ -55,6 +55,7 @@ typedef struct { | |||
| 55 | 55 | ||
| 56 | 56 | void* s_malloc(size_t); | |
| 57 | 57 | void* s_realloc(void*, size_t); | |
| 58 | + | char* s_strdup(char*); | |
| 58 | 59 | ||
| 59 | 60 | void warn(const char*, ...); | |
| 60 | 61 | void die(const char*, ...); | |