#ifndef FILE_H #define FILE_H #include "descriptor.h" #include "date.h" #include "dictionary.h" #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/time.h> #include <sys/types.h> #include <time.h> #include <unistd.h> #define FILE_DEFAULT_PERMISSIONS 0664 #define DIRECTORY_DEFAULT_PERMISSIONS 0755 #define FILE_ERROR_NOT_DIRECTORY "Not a Directory" #define FILE_ERROR_FILE_NOT_FOUND "File Not Found" typedef struct { Descriptor *descriptor; struct stat info; const char *name; const char *mime_type; Dictionary *metadata; void *error; } File; File *file_construct(const char *filename); void file_open(File *file, int flags); void file_close(File *file); void file_new(File *file, int flags, mode_t mode); void file_destroy(File *file); void file_delete(File *file); void file_move(File *file, const char *new_path); File *file_clone(File *file); void file_destroy_clone(File *file); int file_poll(File *file); void *file_read(File *file, int *num_bytes); char *file_read_line(File *file); void file_write(File *file, const void *buffer, int num_bytes); int file_get_size(File *file); void file_set_poll_timeout(File *file, unsigned long secs, unsigned long usecs); int file_is_directory(File *file); Date *file_get_modification_date(File *file); Date *file_get_access_date(File *file); Date *file_get_creation_date(File *file); void file_set_modification_date(File *file, Date *date); void file_set_access_date(File *file, Date *date); mode_t file_get_permissions(File *file); const char *file_get_mime_type(File *file); const char *file_get_name(File *file); const char *file_get_dirname(File *file); const char *file_get_basename(File *file); LinkedList *file_get_directory_listing(File *file); int file_exists(File *file); void file_make_directory(File *file); void file_seek_start(File *file); #endif
-----------------------------------------------------
#include "file.h" #include "string.h" #include "logger.h" #include "mimetypes.h" #include "dictionary.h" #include <sys/types.h> #include <sys/stat.h> #define __USE_XOPEN_EXTENDED #include <ftw.h> #include <sys/time.h> #include <sys/types.h> #include <utime.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <dirent.h> #ifdef DMALLOC #include "dmalloc.h" #endif static MimeTypes *mime_types = NULL; #define FTW_MAX_FDS 10 static int file_delete_callback(const char *file, const struct stat *sb, int flag, struct FTW *s); static int file_stat(File *file); File *file_construct(const char *filename) { File *file = NULL; const char *extension = NULL; struct stat file_info = {-1}; if (filename == NULL) { return NULL; } /* * Allocate space for the object and set all fields to zero. */ file = calloc(1, sizeof(File)); file->name = strdup(filename); file->descriptor = NULL; file->info = file_info; if (mime_types == NULL) { mime_types = mime_types_construct(); } extension = rindex(filename, '.'); if (extension != NULL) { file->mime_type = mime_types_get_type(mime_types, extension); } file->metadata = dictionary_construct(); set_error(file, NULL); return file; } void file_destroy(File *file) { if (file == NULL) { return; } if (file->descriptor != NULL) { descriptor_close(file->descriptor); descriptor_destroy(file->descriptor); } if (file->name != NULL) { free((char *) file->name); } free(file); } void file_delete(File *file) { if (file == NULL) { return; } if (file_is_directory(file)) { nftw(file_get_name(file), file_delete_callback, FTW_MAX_FDS, FTW_DEPTH | FTW_PHYS); } else { unlink(file_get_name(file)); } } void file_move(File *file, const char *new_path) { File *new_file = NULL; String *path = NULL; int retval = -1, exists = 0; if (file == NULL) { } if (new_path == NULL) { return; } if (strcmp(file_get_name(file), new_path) == 0) { return; } new_file = file_construct(new_path); exists = file_exists(new_file); if (exists) { if (file_is_directory(new_file)) { path = string_construct(file_get_name(new_file)); string_append_value(path, "/"); string_append_value(path, file_get_basename(file)); } else { return; } } else { path = string_construct(new_path); } retval = rename(file_get_name(file), string_get_value(path)); if (retval < 0) { perror("rename"); } else { free((char *) file->name); file->name = strdup(string_get_value(path)); } string_destroy(path); } void file_open(File *file, int flags) { int fd = -1; if (file == NULL) { return; } if (flags & O_CREAT) { // ... Log warning ... file_new(file, flags, FILE_DEFAULT_PERMISSIONS); } else { /* * Open the file */ fd = open(file->name, flags); if (fd == -1) { /* * FIXME: fix this */ file->error = FILE_ERROR_FILE_NOT_FOUND; return; } file->descriptor = descriptor_construct(fd); file_set_poll_timeout(file, 0, 0); } } void file_close(File *file) { if (file == NULL) { return; } if (file->descriptor == NULL) { return; } descriptor_close(file->descriptor); } void file_new(File *file, int flags, mode_t mode) { int fd = -1; if (file == NULL) { return; } flags |= O_CREAT; /* * Open the file and create it if it doesn't already exist */ fd = open(file->name, flags, mode); if (fd < 0) { perror("open"); return; } if (file->descriptor != NULL) { descriptor_destroy(file->descriptor); } file->descriptor = descriptor_construct(fd); return; } int file_poll(File *file) { if (file == NULL) { return 0; } if (file->descriptor == NULL) { return 0; } return descriptor_has_data(file->descriptor); } void file_set_poll_timeout(File *file, unsigned long secs, unsigned long usecs) { if (file == NULL) { return; } if (file->descriptor == NULL) { return; } descriptor_set_poll_timeout(file->descriptor, secs, usecs); } void *file_read(File *file, int *num_bytes) { void *buf = NULL; if (file == NULL) { return NULL; } if (file->descriptor == NULL) { return NULL; } if (num_bytes == NULL) { return NULL; } buf = descriptor_read(file->descriptor, num_bytes); return buf; } char *file_read_line(File *file) { if (file == NULL) { return NULL; } if (file->descriptor == NULL) { return NULL; } return descriptor_read_line(file->descriptor); } void file_write(File *file, const void *buffer, int num_bytes) { if (file == NULL) { return; } if (file->descriptor == NULL) { return; } descriptor_write(file->descriptor, buffer, &num_bytes); } int file_get_size(File *file) { DIR *dir = NULL; int size = 0; if (file == NULL) { return 0; } if (file_is_directory(file)) { dir = opendir(file_get_name(file)); while (readdir(dir) != NULL) size++; return size - 2; } else { file_stat(file); /* * Return the file size (from the stat() call at object construction) */ return file->info.st_size; } } Date *file_get_modification_date(File *file) { if (file == NULL) { return 0; } file_stat(file); return date_construct_from_timestamp(file->info.st_mtime); } Date *file_get_access_date(File *file) { if (file == NULL) { return 0; } file_stat(file); return date_construct_from_timestamp(file->info.st_atime); } Date *file_get_creation_date(File *file) { if (file == NULL) { return 0; } file_stat(file); return date_construct_from_timestamp(file->info.st_ctime); } void file_set_modification_date(File *file, Date *date) { struct utimbuf timebuf = {0}; Date *access = NULL; if (file == NULL) { return; } access = file_get_access_date(file); timebuf.actime = date_get_timestamp(access); date_destroy(access); timebuf.modtime = date_get_timestamp(date); utime(file->name, &timebuf); } void file_set_access_date(File *file, Date *date) { struct utimbuf timebuf = {0}; Date *modification = NULL; if (file == NULL) { return; } modification = file_get_modification_date(file); timebuf.modtime = date_get_timestamp(modification); date_destroy(modification); timebuf.actime = date_get_timestamp(date); utime(file->name, &timebuf); } const char *file_get_mime_type(File *file) { if (file == NULL) { return NULL; } return file->mime_type; } mode_t file_get_permissions(File *file) { if (file == NULL) { return 0; } file_stat(file); return file->info.st_mode; } const char *file_get_name(File *file) { if (file == NULL) { return NULL; } return file->name; } int file_is_directory(File *file) { if (file == NULL) { return 0; } file_stat(file); return S_ISDIR(file->info.st_mode); } const char *file_get_dirname(File *file) { char *dirname = NULL; static char *buf = NULL; static int buf_length = 0; int filename_length = 0; if (file == NULL) { return NULL; } filename_length = strlen(file->name); if (buf == NULL || buf_length < filename_length) { buf = realloc(buf, filename_length * sizeof(char)); buf_length = filename_length; } strncpy(buf, file->name, filename_length); dirname = rindex(buf, '/'); if (dirname == NULL) { strcpy(buf, "."); } else { dirname[0] = 0; } dirname = buf; return dirname; } const char *file_get_basename(File *file) { const char *basename = NULL; if (file == NULL) { return NULL; } basename = rindex(file->name, '/') + 1; if (basename == NULL) { basename = file->name; } if (basename[0] == 0) { basename = "/"; } return basename; } int file_exists(File *file) { if (file == NULL) { return 0; } return file_stat(file) != -1; } static int file_delete_callback(const char *file, const struct stat *sb, int flag, struct FTW *s) { remove(file); return 0; } static int file_stat(File *file) { struct stat file_info = {-1}; int retval = 0; if (file == NULL) { return -1; } file->info = file_info; retval = stat(file_get_name(file), &file_info); if (retval >= 0) { file->info = file_info; } return retval; } void file_make_directory(File *file) { int retval = 0; if (file == NULL) { return; } if (file_exists(file)) { return; } retval = mkdir(file_get_name(file), DIRECTORY_DEFAULT_PERMISSIONS); if (retval < 0) { perror("mkdir"); } } void file_seek_start(File *file) { if (file == NULL) { return; } lseek(file->descriptor->fd, 0L, SEEK_SET); } #ifdef TEST int main() { File *file = NULL; file = file_construct("test.test"); file_new(file, O_WRONLY | O_TRUNC, 0644); file_write(file, "Foo Bar Baz", sizeof("Foo Bar Baz") - 1); file_close(file); file_destroy(file); return 0; } #endif