c文件操作库

#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

 

posted @ 2011-09-27 11:56  火腿骑士  阅读(216)  评论(0编辑  收藏  举报