files.c
1 #include <sys/stat.h> 2 #include <sys/types.h> 3 4 #include <stddef.h> 5 #include <stdio.h> 6 #include <err.h> 7 #include <errno.h> 8 #include <string.h> 9 #include <limits.h> 10 11 typedef struct _path { 12 char *buf; 13 size_t buf_size; 14 int index; 15 } Path; 16 17 void 18 join_path(char *buf, size_t buf_size, const char *path, const char *path2) 19 { 20 int r; 21 char * separator = ""; 22 if(path[0] && path[strlen(path) - 1] != '/') 23 separator = "/"; 24 25 r = snprintf(buf, buf_size, "%s%s%s", path, separator, path2); 26 if (r < 0 || (size_t) r >= buf_size) 27 errx(1, "path truncated: '%s%s%s'", path, separator, path2); 28 } 29 30 void 31 combine_paths(char *ret, const char *path, const char *name) 32 { 33 int r; 34 35 if (path[0] == '\0') r = snprintf(ret, PATH_MAX, "%s", name); 36 else r = snprintf(ret, PATH_MAX, "%s/%s", path, name); 37 38 if (r < 0 || (size_t) r >= PATH_MAX) 39 errx(1, "path truncated...?"); 40 } 41 42 int 43 mkdirp(const char *path) 44 { 45 const char *p; 46 char tmp[PATH_MAX]; 47 char *t; 48 49 // TODO use strchr for this? 50 for(t = tmp, p = path; *p != '\0'; p++, t++) { 51 if (*p != '/') { 52 *t = *p; 53 continue; 54 } 55 56 *t = '\0'; 57 if ( 58 mkdir(tmp, S_IRWXU | S_IRWXG | S_IRWXO) < 0 && 59 errno != EEXIST 60 ) 61 return -1; 62 *t = '/'; 63 } 64 return 0; 65 } 66 67 /* populates buf with the filepath that was opened. */ 68 FILE * 69 fopen_w(const char *name) 70 { 71 FILE *ret; 72 73 mkdirp(name); // TODO minimize calls to this 74 if (!(ret = fopen(name, "w"))) err(1, "fopen: '%s'", name); 75 return ret; 76 } 77 78 /* Handle read or write errors for a FILE * stream */ 79 void 80 check_file_error(FILE *fp, const char *path, int mode) 81 { 82 if (mode == 'r' && ferror(fp)) 83 errx(1, "read error: %s", path); 84 else if (mode == 'w' && (fflush(fp) || ferror(fp))) 85 errx(1, "write error: %s", path); 86 }