/* * Copyright 2001-2004 Brandon Long * All Rights Reserved. * * ClearSilver Templating System * * This code is made available under the terms of the ClearSilver License. * http://www.clearsilver.net/license.hdf * */ #include "cs_config.h" #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <limits.h> #include <dirent.h> #include <sys/stat.h> #include "neo_misc.h" #include "neo_err.h" #include "neo_files.h" #include "wildmat.h" NEOERR *ne_mkdirs (const char *path, mode_t mode) { char mypath[_POSIX_PATH_MAX]; int x; int r; strncpy (mypath, path, sizeof(mypath)); x = strlen(mypath); if ((x < sizeof(mypath)) && (mypath[x-1] != '/')) { mypath[x] = '/'; mypath[x+1] = '\0'; } for (x = 1; mypath[x]; x++) { if (mypath[x] == '/') { mypath[x] = '\0'; #ifdef __MINGW32__ /* Braindead MINGW32 doesn't just have a dummy argument for mode */ r = mkdir (mypath); #else r = mkdir (mypath, mode); #endif if (r == -1 && errno != EEXIST) { return nerr_raise_errno(NERR_SYSTEM, "ne_mkdirs: mkdir(%s, %x) failed", mypath, mode); } mypath[x] = '/'; } } return STATUS_OK; } NEOERR *ne_load_file_len (const char *path, char **str, int *out_len) { struct stat s; int fd; int len; int bytes_read; *str = NULL; if (out_len) *out_len = 0; if (stat(path, &s) == -1) { if (errno == ENOENT) return nerr_raise (NERR_NOT_FOUND, "File %s not found", path); return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); } fd = open (path, O_RDONLY); if (fd == -1) { return nerr_raise_errno (NERR_SYSTEM, "Unable to open file %s", path); } len = s.st_size; *str = (char *) malloc (len + 1); if (*str == NULL) { close(fd); return nerr_raise (NERR_NOMEM, "Unable to allocate memory (%d) to load file %s", len + 1, path); } if ((bytes_read = read (fd, *str, len)) == -1) { close(fd); free(*str); return nerr_raise_errno (NERR_SYSTEM, "Unable to read file %s", path); } (*str)[bytes_read] = '\0'; close(fd); if (out_len) *out_len = bytes_read; return STATUS_OK; } NEOERR *ne_load_file (const char *path, char **str) { return ne_load_file_len (path, str, NULL); } NEOERR *ne_save_file (const char *path, char *str) { NEOERR *err; int fd; int w, l; fd = open (path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ); if (fd == -1) { return nerr_raise_errno (NERR_IO, "Unable to create file %s", path); } l = strlen(str); w = write (fd, str, l); if (w != l) { err = nerr_raise_errno (NERR_IO, "Unable to write file %s", path); close (fd); return err; } close (fd); return STATUS_OK; } NEOERR *ne_remove_dir (const char *path) { NEOERR *err; DIR *dp; struct stat s; struct dirent *de; char npath[_POSIX_PATH_MAX]; if (stat(path, &s) == -1) { if (errno == ENOENT) return STATUS_OK; return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", path); } if (!S_ISDIR(s.st_mode)) { return nerr_raise (NERR_ASSERT, "Path %s is not a directory", path); } dp = opendir(path); if (dp == NULL) return nerr_raise_errno (NERR_IO, "Unable to open directory %s", path); while ((de = readdir (dp)) != NULL) { if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) { snprintf (npath, sizeof(npath), "%s/%s", path, de->d_name); if (stat(npath, &s) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to stat file %s", npath); } if (S_ISDIR(s.st_mode)) { err = ne_remove_dir(npath); if (err) break; } else { if (unlink(npath) == -1) { if (errno == ENOENT) continue; closedir(dp); return nerr_raise_errno (NERR_SYSTEM, "Unable to unlink file %s", npath); } } } } closedir(dp); if (rmdir(path) == -1) { return nerr_raise_errno (NERR_SYSTEM, "Unable to rmdir %s", path); } return STATUS_OK; } NEOERR *ne_listdir(const char *path, ULIST **files) { return nerr_pass(ne_listdir_fmatch(path, files, NULL, NULL)); } static int _glob_match(void *rock, const char *filename) { return wildmat(filename, rock); } NEOERR *ne_listdir_match(const char *path, ULIST **files, const char *match) { return nerr_pass(ne_listdir_fmatch(path, files, _glob_match, (void *)match)); } NEOERR *ne_listdir_fmatch(const char *path, ULIST **files, MATCH_FUNC fmatch, void *rock) { DIR *dp; struct dirent *de; ULIST *myfiles = NULL; NEOERR *err = STATUS_OK; if (files == NULL) return nerr_raise(NERR_ASSERT, "Invalid call to ne_listdir_fmatch"); if (*files == NULL) { err = uListInit(&myfiles, 10, 0); if (err) return nerr_pass(err); } else { myfiles = *files; } if ((dp = opendir (path)) == NULL) { return nerr_raise_errno(NERR_IO, "Unable to opendir %s", path); } while ((de = readdir (dp)) != NULL) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) continue; if (fmatch != NULL && !fmatch(rock, de->d_name)) continue; err = uListAppend(myfiles, strdup(de->d_name)); if (err) break; } closedir(dp); if (err && *files == NULL) { uListDestroy(&myfiles, ULIST_FREE); } else if (*files == NULL) { *files = myfiles; } return nerr_pass(err); }