1 /* 2 * Copyright 2001-2004 Brandon Long 3 * All Rights Reserved. 4 * 5 * ClearSilver Templating System 6 * 7 * This code is made available under the terms of the ClearSilver License. 8 * http://www.clearsilver.net/license.hdf 9 * 10 */ 11 12 #include "cs_config.h" 13 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <sys/types.h> 17 #include <fcntl.h> 18 #include <string.h> 19 #include <unistd.h> 20 #include <errno.h> 21 #include <limits.h> 22 #include <dirent.h> 23 #include <sys/stat.h> 24 25 #include "neo_misc.h" 26 #include "neo_err.h" 27 #include "neo_files.h" 28 #include "wildmat.h" 29 30 NEOERR *ne_mkdirs (const char *path, mode_t mode) 31 { 32 char mypath[_POSIX_PATH_MAX]; 33 int x; 34 int r; 35 36 strncpy (mypath, path, sizeof(mypath)); 37 x = strlen(mypath); 38 if ((x < sizeof(mypath)) && (mypath[x-1] != '/')) 39 { 40 mypath[x] = '/'; 41 mypath[x+1] = '\0'; 42 } 43 44 for (x = 1; mypath[x]; x++) 45 { 46 if (mypath[x] == '/') 47 { 48 mypath[x] = '\0'; 49 #ifdef __MINGW32__ 50 /* Braindead MINGW32 doesn't just have a dummy argument for mode */ 51 r = mkdir (mypath); 52 #else 53 r = mkdir (mypath, mode); 54 #endif 55 56 if (r == -1 && errno != EEXIST) 57 { 58 return nerr_raise_errno(NERR_SYSTEM, "ne_mkdirs: mkdir(%s, %x) failed", mypath, mode); 59 } 60 mypath[x] = '/'; 61 } 62 } 63 return STATUS_OK; 64 } 65 66 NEOERR *ne_load_file_len (const char *path, char **str, int *out_len) 67 { 68 struct stat s; 69 int fd; 70 int len; 71 int bytes_read; 72 73 *str = NULL; 74 if (out_len) *out_len = 0; 75 76 if (stat(path, &s) == -1) 77 { 78 if (errno == ENOENT) 79 return nerr_raise (NERR_NOT_FOUND, "File %s not found", path); 80 return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); 81 } 82 83 fd = open (path, O_RDONLY); 84 if (fd == -1) 85 { 86 return nerr_raise_errno (NERR_SYSTEM, "Unable to open file %s", path); 87 } 88 len = s.st_size; 89 *str = (char *) malloc (len + 1); 90 91 if (*str == NULL) 92 { 93 close(fd); 94 return nerr_raise (NERR_NOMEM, 95 "Unable to allocate memory (%d) to load file %s", len + 1, path); 96 } 97 if ((bytes_read = read (fd, *str, len)) == -1) 98 { 99 close(fd); 100 free(*str); 101 return nerr_raise_errno (NERR_SYSTEM, "Unable to read file %s", path); 102 } 103 104 (*str)[bytes_read] = '\0'; 105 close(fd); 106 if (out_len) *out_len = bytes_read; 107 108 return STATUS_OK; 109 } 110 111 NEOERR *ne_load_file (const char *path, char **str) { 112 return ne_load_file_len (path, str, NULL); 113 } 114 115 NEOERR *ne_save_file (const char *path, char *str) 116 { 117 NEOERR *err; 118 int fd; 119 int w, l; 120 121 fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); 122 if (fd == -1) 123 { 124 return nerr_raise_errno (NERR_IO, "Unable to create file %s", path); 125 } 126 l = strlen(str); 127 w = write (fd, str, l); 128 if (w != l) 129 { 130 err = nerr_raise_errno (NERR_IO, "Unable to write file %s", path); 131 close (fd); 132 return err; 133 } 134 close (fd); 135 136 return STATUS_OK; 137 } 138 139 NEOERR *ne_remove_dir (const char *path) 140 { 141 NEOERR *err; 142 DIR *dp; 143 struct stat s; 144 struct dirent *de; 145 char npath[_POSIX_PATH_MAX]; 146 147 if (stat(path, &s) == -1) 148 { 149 if (errno == ENOENT) return STATUS_OK; 150 return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); 151 } 152 if (!S_ISDIR(s.st_mode)) 153 { 154 return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path); 155 } 156 dp = opendir(path); 157 if (dp == NULL) 158 return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path); 159 while ((de = readdir (dp)) != NULL) 160 { 161 if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) 162 { 163 snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name); 164 if (stat(npath, &s) == -1) 165 { 166 if (errno == ENOENT) continue; 167 closedir(dp); 168 return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath); 169 } 170 if (S_ISDIR(s.st_mode)) 171 { 172 err = ne_remove_dir(npath); 173 if (err) break; 174 } 175 else 176 { 177 if (unlink(npath) == -1) 178 { 179 if (errno == ENOENT) continue; 180 closedir(dp); 181 return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s", 182 npath); 183 } 184 } 185 } 186 } 187 closedir(dp); 188 if (rmdir(path) == -1) 189 { 190 return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path); 191 } 192 return STATUS_OK; 193 } 194 195 NEOERR *ne_listdir(const char *path, ULIST **files) 196 { 197 return nerr_pass(ne_listdir_fmatch(path, files, NULL, NULL)); 198 } 199 200 static int _glob_match(void *rock, const char *filename) 201 { 202 return wildmat(filename, rock); 203 } 204 205 NEOERR *ne_listdir_match(const char *path, ULIST **files, const char *match) 206 { 207 return nerr_pass(ne_listdir_fmatch(path, files, _glob_match, (void *)match)); 208 } 209 210 NEOERR *ne_listdir_fmatch(const char *path, ULIST **files, MATCH_FUNC fmatch, 211 void *rock) 212 { 213 DIR *dp; 214 struct dirent *de; 215 ULIST *myfiles = NULL; 216 NEOERR *err = STATUS_OK; 217 218 if (files == NULL) 219 return nerr_raise(NERR_ASSERT, "Invalid call to ne_listdir_fmatch"); 220 221 if (*files == NULL) 222 { 223 err = uListInit(&myfiles, 10, 0); 224 if (err) return nerr_pass(err); 225 } 226 else 227 { 228 myfiles = *files; 229 } 230 231 if ((dp = opendir (path)) == NULL) 232 { 233 return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path); 234 } 235 while ((de = readdir (dp)) != NULL) 236 { 237 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) 238 continue; 239 240 if (fmatch != NULL && !fmatch(rock, de->d_name)) 241 continue; 242 243 err = uListAppend(myfiles, strdup(de->d_name)); 244 if (err) break; 245 } 246 closedir(dp); 247 if (err && *files == NULL) 248 { 249 uListDestroy(&myfiles, ULIST_FREE); 250 } 251 else if (*files == NULL) 252 { 253 *files = myfiles; 254 } 255 return nerr_pass(err); 256 } 257