create.c

mail@pastecode.io avatar
unknown
plain_text
2 months ago
4.6 kB
3
Indexable
Never
#include "create.h"
#include "write.h"
#include "header.h"
#define BLOCK_SIZE 512

int create_archive(char *tarfile){
    int tar_fd;

    /* Open tar_file with read write user permissions */
    tar_fd = open(tarfile, O_RDWR | O_CREAT | O_TRUNC, S_IRWXU);

    if(tar_fd == -1){
        perror("open");
        exit(EXIT_FAILURE);
    }

    return tar_fd;
}

void archive_file(int fd, char *parent_path, char *file_name){
    struct stat file_sb;
    struct passwd *file_pwd;
    struct group *file_group;
    struct dirent *dir_entry;
    struct header *file_header;
    DIR *directory;
    char *full_path;
    int file_fd;

    /* Stat current file and exit if it failed */
    if(lstat(file_name, &file_sb) == -1){
        perror("lstat");
        exit(EXIT_FAILURE);
    }

    /* Get user password for user name */
    file_pwd = getpwuid(file_sb.st_uid);
    if(file_pwd == NULL){
        perror("getpwuid");
        exit(EXIT_FAILURE);
    }

    file_group = getgrgid(file_sb.st_gid);

    if(file_group == NULL){
        perror("getgrgid");
        exit(EXIT_FAILURE);
    }

    /* Create full path up to this point */
    full_path = create_full_path(parent_path, file_name, file_sb.st_mode);
    if(verbose_option == 1){
        printf("%s\n", full_path);
    }


    /* Create and write header, on fail skip file */
    file_header = create_header(file_sb, full_path);
    if(file_header == NULL){
        free(full_path);
        return;
    }


    if(S_ISDIR(file_sb.st_mode)){
        /* Change to paths directory */
        if(chdir(file_name) == -1){
            perror("chdir");
            exit(EXIT_FAILURE);
        }

        /* Open the current directory, exit on failure */
        directory = opendir(".");

        if(directory == NULL){
            perror("opendir");
            exit(EXIT_FAILURE);
        }

        write_header(fd, file_header);
        free(file_header);

        write_field(fd, NULL, BLOCK_SIZE);

        while((dir_entry = readdir(directory)) != NULL){
            /* If the entry name is not . or .. archive the file */
            if(strcmp(dir_entry->d_name, ".") &&
                strcmp(dir_entry->d_name, "..")){

                /* Recurse on child entry */
                archive_file(fd, full_path, dir_entry->d_name);
            }
        }

        closedir(directory);

        /* Pop back to current directory */
        if(chdir("..") == -1){
            perror("chdir");
            exit(EXIT_FAILURE);
        }
    }
    else if (S_ISLNK(file_sb.st_mode)){
        write_header(fd, file_header);
        free(file_header);

        write_field(fd, NULL, BLOCK_SIZE);
    }
    else if (S_ISREG(file_sb.st_mode)){
        /* Open file to read contents, on fail return */
        if((file_fd = open(full_path, O_RDONLY, S_IRWXU)) == -1){
            perror("open");
            free(full_path);
            return;
        }

        write_header(fd, file_header);
        free(file_header);

        /* Write file contents */
        write_contents(fd, file_fd, file_sb);

        close(file_fd);
    }
    else{
        /* If file is not a dir, sym link, or a regular file exit */
        perror("unsupported file type: ");
    }

    free(full_path);

    return;
}

/* Takes curr path and curr file name and appends them with a / in between */
char *create_full_path(char *parent_path, char *file_name, mode_t file_mode){
    char *full_path;
    size_t parent_path_len, file_name_len;
    int i;

    parent_path_len = strlen(parent_path);
    file_name_len = strlen(file_name);

    /* Malloc string of size path and file name with 2 spaces for null and / */
    if(S_ISDIR(file_mode)){
        full_path = malloc(parent_path_len + file_name_len + 2);
    }
    else if(S_ISREG(file_mode) || S_ISLNK(file_mode)){
        full_path = malloc(parent_path_len + file_name_len + 1);
    }

    if(full_path == NULL){
        perror("malloc");
        exit(EXIT_FAILURE);
    }

    /* Copy curr path over */
    for(i = 0; i < parent_path_len; i++){
        full_path[i] = parent_path[i];
    }

    /* Copy file name over */
    for(i = 0; i < file_name_len; i++){
        full_path[parent_path_len + i] = file_name[i];
    }

    /* Add null terminating character and slash */
    if(S_ISDIR(file_mode)){
        full_path[parent_path_len + file_name_len] = '/';
        full_path[parent_path_len + file_name_len + 1] = '\0';
    }
    else if(S_ISREG(file_mode) || S_ISLNK(file_mode)){
        full_path[parent_path_len + file_name_len] = '\0';
    }

    return full_path;
}
Leave a Comment