Example #1
0
File: tar.c Project: calccrypto/tar
int write_end_data(const int fd, int size, const char verbosity){
    if (fd < 0){
        return -1;
    }

    // complete current record
    const int pad = RECORDSIZE - (size % RECORDSIZE);
    for(int i = 0; i < pad; i++){
        if (write(fd, "\0", 1) != 1){
            V_PRINT(stderr, "Error: Unable to close tar file\n");
            return -1;
        }
    }

    // if the current record does not have 2 blocks of zeros, add a whole other record
    if (pad < (2 * BLOCKSIZE)){
        for(int i = 0; i < RECORDSIZE; i++){
            if (write(fd, "\0", 1) != 1){
                V_PRINT(stderr, "Error: Unable to close tar file\n");
                return -1;
            }
        }
        return pad + RECORDSIZE;
    }

    return pad;
}
Example #2
0
File: tar.c Project: calccrypto/tar
int tar_update(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
    if (!filecount){
        return 0;
    }

    if (filecount && !files){
        V_PRINT(stderr, "Error: Non-zero file count provided, but file list is NULL");
        return -1;
    }

    // buffer for subset of files that need to be updated
    char ** newer = calloc(filecount, sizeof(char *));

    struct stat st;
    int count = 0;
    int all = 1;

    // check each source to see if it was updated
    struct tar_t * tar = *archive;
    for(int i = 0; i < filecount; i++){
        // make sure original file exists
        if (lstat(files[i], &st)){
            all = 0;
            RC_ERROR(stderr, "Error: Could not stat %s: %s\n", files[i], strerror(rc));
        }

        // find the file in the archive
        struct tar_t * old = exists(tar, files[i], 1);
        newer[count] = calloc(strlen(files[i]) + 1, sizeof(char));

        // if there is an older version, check its timestamp
        if (old){
            if (st.st_mtime > oct2uint(old -> mtime, 11)){
                strncpy(newer[count++], files[i], strlen(files[i]));
                V_PRINT(stdout, "%s\n", files[i]);
            }
        }
        // if there is no older version, just add it
        else{
            strncpy(newer[count++], files[i], strlen(files[i]));
            V_PRINT(stdout, "%s\n", files[i]);
        }
    }

    // update listed files only
    if (tar_write(fd, archive, count, (const char **) newer, verbosity) < 0){
        V_PRINT(stderr, "Error: Unable to update archive\n");
        return -1;
    }

    // cleanup
    for(int i = 0; i < count; i++){
        free(newer[i]);
    }
    free(newer);

    return all?0:-1;
}
Example #3
0
File: tar.c Project: calccrypto/tar
int tar_write(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
    if (fd < 0){
        return -1;
    }

    if (!archive){
        return -1;
    }

    // where file descriptor offset is
    int offset = 0;

    // if there is old data
    struct tar_t ** tar = archive;
    if (*tar){
        // skip to last entry
        while (*tar && (*tar) -> next){
            tar = &((*tar) -> next);
        }

        // get offset past final entry
        unsigned int jump = 512 + oct2uint((*tar) -> size, 11);
        if (jump % 512){
            jump += 512 - (jump % 512);
        }

        // move file descriptor
        offset = (*tar) -> begin + jump;
        if (lseek(fd, offset, SEEK_SET) == (off_t) (-1)){
            RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
        }
        tar = &((*tar) -> next);
    }

    // write entries first
    if (write_entries(fd, tar, archive, filecount, files, &offset, verbosity) < 0){
        V_PRINT(stderr, "Error: Failed to write entries\n");
        return -1;
    }

    // write ending data
    if (write_end_data(fd, offset, verbosity) < 0){
        V_PRINT(stderr, "Error: Failed to write end data");
        return -1;
    }

    // clear original names from data
    tar = archive;
    while (*tar){
        memset((*tar) -> name, 0, 100);
        tar = &((*tar) -> next);
    }
    return offset;
}
Example #4
0
File: tar.c Project: calccrypto/tar
int tar_diff(FILE * f, struct tar_t * archive, const char verbosity){
    struct stat st;
    while (archive){
        V_PRINT(f, "%s\n", archive -> name);

        // if not found, print error
        if (lstat(archive -> name, &st)){
            int rc = errno;
            fprintf(f, "Error: Could not ");
            if (archive -> type == SYMLINK){
                fprintf(f, "readlink");
            }
            else{
                fprintf(f, "stat");
            }
            fprintf(f, " %s: %s\n", archive -> name, strerror(rc));
        }
        else{
            if (st.st_mtime != oct2uint(archive -> mtime, 11)){
                fprintf(f, "%s: Mod time differs", archive -> name);
            }
            if (st.st_size != oct2uint(archive -> size, 11)){
                fprintf(f, "%s: Mod time differs", archive -> name);
            }
        }

        archive = archive -> next;
    }
    return 0;
}
Example #5
0
File: tar.c Project: calccrypto/tar
int tar_extract(const int fd, struct tar_t * archive, const size_t filecount, const char * files[], const char verbosity){
    int ret = 0;

    // extract entries with given names
    if (filecount){
        if (!files){
            V_PRINT(stderr, "Error: Received non-zero file count but got NULL file list\n");
            return -1;
        }

        while (archive){
            for(size_t i = 0; i < filecount; i++){
                if (!strncmp(archive -> name, files[i], MAX(strlen(archive -> name), strlen(files[i])))){
                    if (lseek(fd, archive -> begin, SEEK_SET) == (off_t) (-1)){
                        RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
                    }

                    if (extract_entry(fd, archive, verbosity) < 0){
                        ret = -1;
                    }
                    break;
                }
            }
            archive = archive -> next;
        }
    }
    // extract all
    else{
        // move offset to beginning
        if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
            RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
        }

        // extract each entry
        while (archive){
            if (extract_entry(fd, archive, verbosity) < 0){
                ret = -1;
            }
            archive = archive -> next;
        }
    }

    return ret;
}
Example #6
0
File: tar.c Project: calccrypto/tar
int write_entries(const int fd, struct tar_t ** archive, struct tar_t ** head, const size_t filecount, const char * files[], int * offset, const char verbosity){
    if (fd < 0){
        return -1;
    }

    if (!archive || *archive){
        return -1;
    }

    if (filecount && !files){
        return -1;
    }

    // add new data
    struct tar_t ** tar = archive;  // current entry
    char buf[512];              // one block buffer
    for(unsigned int i = 0; i < filecount; i++){
        *tar = malloc(sizeof(struct tar_t));

        // stat file
        if (format_tar_data(*tar, files[i], verbosity) < 0){
            WRITE_ERROR(stderr, "Error: Failed to stat %s\n", files[i]);
        }

        if (!i){
            *archive = *tar;  // store first address
        }

        (*tar) -> begin = *offset;

        // write different data depending on file type
        if ((*tar) -> type == DIRECTORY){
            // save parent directory name (source will change)
            const size_t len = strlen((*tar) -> name);
            char * parent = calloc(len + 1, sizeof(char));
            strncpy(parent, (*tar) -> name, len);

            // add a '/' character to the end
            if ((len < 99) && ((*tar) -> name[len - 1] != '/')){
                (*tar) -> name[len] = '/';
                (*tar) -> name[len + 1] = '\0';
                calculate_checksum((*tar));
            }

            V_PRINT(stdout, "%s\n", (*tar) -> name);

            // write metadata to (*tar) file
            if (write_size(fd, (*tar) -> block, 512) != 512){
                WRITE_ERROR(stderr, "Error: Failed to write metadata to archive\n");
            }

            // go through directory
            DIR * d = opendir(parent);
            if (!d){
                WRITE_ERROR(stderr, "Error: Cannot read directory %s\n", parent);
            }

            struct dirent * dir;
            while ((dir = readdir(d))){
                // if not special directories . and ..
                const size_t sublen = strlen(dir -> d_name);
                if (strncmp(dir -> d_name, ".", sublen) && strncmp(dir -> d_name, "..", sublen)){
                    char * path = calloc(len + sublen + 2, sizeof(char));
                    sprintf(path, "%s/%s", parent, dir -> d_name);

                    // recursively write each subdirectory
                    if (write_entries(fd, &((*tar) -> next), head, 1, (const char **) &path, offset, verbosity) < 0){
                        WRITE_ERROR(stderr, "Error: Recurse error\n");
                    }

                    // go to end of new data
                    while ((*tar) -> next){
                        tar = &((*tar) -> next);
                    }

                    free(path);
                }
            }

            free(parent);
            closedir(d);
        }
        else{ // if (((*tar) -> type == REGULAR) || ((*tar) -> type == NORMAL) || ((*tar) -> type == CONTIGUOUS) || ((*tar) -> type == SYMLINK) || ((*tar) -> type == CHAR) || ((*tar) -> type == BLOCK) || ((*tar) -> type == FIFO)){
            V_PRINT(stdout, "%s\n", (*tar) -> name);

            char tarred = 0;   // whether or not the file has already been put into the archive
            if (((*tar) -> type == REGULAR) || ((*tar) -> type == NORMAL) || ((*tar) -> type == CONTIGUOUS) || ((*tar) -> type == SYMLINK)){
                struct tar_t * found = exists(*head, files[i], 1);
                tarred = (found != (*tar));

                // if file has already been included, modify the header
                if (tarred){
                    // change type to hard link
                    (*tar) -> type = HARDLINK;

                    // change link name to (*tar)red file name (both are the same)
                    strncpy((*tar) -> link_name, (*tar) -> name, 100);

                    // change size to 0
                    strncpy((*tar) -> size, "00000000000", 11);

                    // recalculate checksum
                    calculate_checksum((*tar));
                }
            }

            // write metadata to (*tar) file
            if (write_size(fd, (*tar) -> block, 512) != 512){
                WRITE_ERROR(stderr, "Error: Failed to write metadata to archive\n");
            }

            if (((*tar) -> type == REGULAR) || ((*tar) -> type == NORMAL) || ((*tar) -> type == CONTIGUOUS)){
                // if the file isn't already in the tar file, copy the contents in
                if (!tarred){
                    int f = open((*tar) -> name, O_RDONLY);
                    if (f < 0){
                        WRITE_ERROR(stderr, "Error: Could not open %s\n", files[i]);
                    }

                    int r = 0;
                    while ((r = read_size(f, buf, 512)) > 0){
                        if (write_size(fd, buf, r) != r){
                            RC_ERROR(stderr, "Error: Could not write to archive: %s\n", strerror(rc));
                        }
                    }

                    close(f);
                }
            }

            // pad data to fill block
            const unsigned int size = oct2uint((*tar) -> size, 11);
            const unsigned int pad = 512 - size % 512;
            if (pad != 512){
                for(unsigned int j = 0; j < pad; j++){
                    if (write_size(fd, "\0", 1) != 1){
                        WRITE_ERROR(stderr, "Error: Could not write padding data\n");
                    }
                }
                *offset += pad;
            }
            *offset += size;
            tar = &((*tar) -> next);
        }

        // add metadata size
        *offset += 512;
    }

    return 0;
}
Example #7
0
File: tar.c Project: calccrypto/tar
int extract_entry(const int fd, struct tar_t * entry, const char verbosity){
    V_PRINT(stdout, "%s\n", entry -> name);

    if ((entry -> type == REGULAR) || (entry -> type == NORMAL) || (entry -> type == CONTIGUOUS)){
        // create intermediate directories
        size_t len = strlen(entry -> name);
        char * path = calloc(len + 1, sizeof(char));
        strncpy(path, entry -> name, len);

        // remove file from path
        while (--len && (path[len] != '/'));
        path[len] = '\0';   // if nothing was found, path is terminated

        if (recursive_mkdir(path, DEFAULT_DIR_MODE, verbosity) < 0){
            V_PRINT(stderr, "Error: Could not make directory %s\n", path);
            free(path);
            return -1;
        }
        free(path);

        if ((entry -> type == REGULAR) || (entry -> type == NORMAL) || (entry -> type == CONTIGUOUS)){
            // create file
            const unsigned int size = oct2uint(entry -> size, 11);
            int f = open(entry -> name, O_WRONLY | O_CREAT | O_TRUNC, oct2uint(entry -> mode, 7) & 0777);
            if (f < 0){
                RC_ERROR(stderr, "Error: Unable to open file %s: %s\n", entry -> name, strerror(rc));
            }

            // move archive pointer to data location
            if (lseek(fd, 512 + entry -> begin, SEEK_SET) == (off_t) (-1)){
                RC_ERROR(stderr, "Error: Bad index: %s\n", strerror(rc));
            }

            // copy data to file
            char buf[512];
            int got = 0;
            while (got < size){
                int r;
                if ((r = read_size(fd, buf, MIN(size - got, 512))) < 0){
                    EXIST_ERROR(stderr, "Error: Unable to read from archive: %s\n", strerror(rc));
                }

                if (write(f, buf, r) != r){
                    EXIST_ERROR(stderr, "Error: Unable to write to %s: %s\n", entry -> name, strerror(rc));
                }

                got += r;
            }

            close(f);
        }
        else if ((entry -> type == CHAR) || (entry -> type == BLOCK)){
            if (mknod(entry -> name, oct2uint(entry -> mode, 7), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
                EXIST_ERROR(stderr, "Error: Unable to make device %s: %s\n", entry -> name, strerror(rc));
            }
        }
    }
    else if (entry -> type == HARDLINK){
        if (link(entry -> link_name, entry -> name) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create hardlink %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == SYMLINK){
        if (symlink(entry -> link_name, entry -> name) < 0){
            EXIST_ERROR(stderr, "Error: Unable to make symlink %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == CHAR){
        if (mknod(entry -> name, S_IFCHR | (oct2uint(entry -> mode, 7) & 0777), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == BLOCK){
        if (mknod(entry -> name, S_IFBLK | (oct2uint(entry -> mode, 7) & 0777), (oct2uint(entry -> major, 7) << 20) | oct2uint(entry -> minor, 7)) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == DIRECTORY){
        if (recursive_mkdir(entry -> name, oct2uint(entry -> mode, 7) & 0777, verbosity) < 0){
            EXIST_ERROR(stderr, "Error: Unable to create directory %s: %s\n", entry -> name, strerror(rc));
        }
    }
    else if (entry -> type == FIFO){
        if (mkfifo(entry -> name, oct2uint(entry -> mode, 7) & 0777) < 0){
            EXIST_ERROR(stderr, "Error: Unable to make pipe %s: %s\n", entry -> name, strerror(rc));
        }
    }
    return 0;
}
Example #8
0
File: tar.c Project: calccrypto/tar
int ls_entry(FILE * f, struct tar_t * entry, unsigned int * max_space, const size_t filecount, const char * files[], const char verbosity){
    if (!verbosity){
        return 0;
    }

    if (filecount && !files){
        V_PRINT(stderr, "Error: Non-zero file count given but no files given\n");
        return -1;
    }

    // figure out whether or not to print
    char print = !filecount;
    for(size_t i = 0; i < filecount; i++){
        if (strncmp(entry -> name, files[i], MAX(strlen(entry -> name), strlen(files[i])))){
            print = 1;
            break;
        }
    }

    if (print){
        if (verbosity > 1){
            const mode_t mode = oct2uint(entry -> mode, 7);
            const char mode_str[26] = { "-hlcbdp-"[entry -> type?entry -> type - '0':0],
                                        mode & S_IRUSR?'r':'-',
                                        mode & S_IWUSR?'w':'-',
                                        mode & S_IXUSR?'x':'-',
                                        mode & S_IRGRP?'r':'-',
                                        mode & S_IWGRP?'w':'-',
                                        mode & S_IXGRP?'x':'-',
                                        mode & S_IROTH?'r':'-',
                                        mode & S_IWOTH?'w':'-',
                                        mode & S_IXOTH?'x':'-',
                                        0};
            fprintf(f, "%s %s/%s ", mode_str, entry -> owner, entry -> group);
            char size_buf[22] = {0};
            int rc = -1;
            switch (entry -> type){
                case REGULAR: case NORMAL: case CONTIGUOUS:
                    rc = sprintf(size_buf, "  %u", oct2uint(entry -> size, 11));
                    break;
                case HARDLINK: case SYMLINK: case DIRECTORY: case FIFO:
                    rc = sprintf(size_buf, "  %u", oct2uint(entry -> size, 11));
                    break;
                case CHAR: case BLOCK:
                    rc = sprintf(size_buf, "%d,%d", oct2uint(entry -> major, 7), oct2uint(entry -> minor, 7));
                    break;
            }

            if (rc < 0){
                fprintf(f, "Error: Failed to write length\n");
                return -1;
            }

            // update padding space
            if (*max_space < rc){
                *max_space = rc;
            }

            // print padding space
            for(unsigned int i = 0; i < (*max_space - rc); i++){
                fprintf(f, " ");
            }

            fprintf(f, "%s", size_buf);

            time_t mtime = oct2uint(entry -> mtime, 11);
            struct tm * time = localtime(&mtime);
            fprintf(f, " %d-%02d-%02d %02d:%02d ", time -> tm_year + 1900, time -> tm_mon + 1, time -> tm_mday, time -> tm_hour, time -> tm_min);
        }

        fprintf(f, "%s", entry -> name);

        if (verbosity > 1){
            switch (entry -> type){
                case HARDLINK:
                    fprintf(f, " link to %s", entry -> link_name);
                    break;
                case SYMLINK:
                    fprintf(f, " -> %s", entry -> link_name);
                    break;
                break;
            }
        }

        fprintf(f, "\n");
    }

    return 0;
}
Example #9
0
File: tar.c Project: calccrypto/tar
int format_tar_data(struct tar_t * entry, const char * filename, const char verbosity){
    if (!entry){
        return -1;
    }

    struct stat st;
    if (lstat(filename, &st)){
        RC_ERROR(stderr, "Error: Cannot stat %s: %s\n", filename, strerror(rc));
        return -1;
    }

    // remove relative path
    int move = 0;
    if (!strncmp(filename, "/", 1)){
        move = 1;
    }
    else if (!strncmp(filename, "./", 2)){
        move = 2;
    }
    else if (!strncmp(filename, "../", 3)){
        move = 3;
    }

    // start putting in new data
    memset(entry, 0, sizeof(struct tar_t));
    strncpy(entry -> original_name, filename, 100);
    strncpy(entry -> name, filename + move, 100);
    sprintf(entry -> mode, "%07o", st.st_mode & 0777);
    sprintf(entry -> uid, "%07o", st.st_uid);
    sprintf(entry -> gid, "%07o", st.st_gid);
    sprintf(entry -> size, "%011o", (int) st.st_size);
    sprintf(entry -> mtime, "%011o", (int) st.st_mtime);
    strncpy(entry -> group, "None", 4);                     // default value
    memcpy(entry -> ustar, "ustar\00000", 8);               // official value?

    // figure out filename type
    switch (st.st_mode & S_IFMT) {
        case S_IFREG:
            entry -> type = NORMAL;
            break;
        case S_IFLNK:
            entry -> type = SYMLINK;

            // file size is 0, but will print link size
            strncpy(entry -> size, "00000000000", 11);

            // get link name
            if (readlink(filename, entry -> link_name, 100) < 0){
                RC_ERROR(stderr, "Error: Could not read link %s: %s\n", filename, strerror(rc));
            }

            break;
        case S_IFCHR:
            entry -> type = CHAR;
            // get character device major and minor values
            sprintf(entry -> major, "%08o", major(st.st_dev));
            sprintf(entry -> minor, "%08o", minor(st.st_dev));
            break;
        case S_IFBLK:
            entry -> type = BLOCK;
            // get block device major and minor values
            sprintf(entry -> major, "%08o", major(st.st_dev));
            sprintf(entry -> minor, "%08o", minor(st.st_dev));
            break;
        case S_IFDIR:
            entry -> type = DIRECTORY;
            break;
        case S_IFIFO:
            entry -> type = FIFO;
            break;
        case S_IFSOCK:
            entry -> type = -1;
            V_PRINT(stderr, "Error: Cannot tar socket\n");
            return -1;
            break;
        default:
            entry -> type = -1;
            V_PRINT(stderr, "Error: Unknown filetype\n");
            return -1;
            break;
    }

    // get username
    if (getlogin_r(entry -> owner, 32)){
        RC_ERROR(stderr, "Warning: Unable to get username: %s\n", strerror(rc));
    }

    // get group name
    struct group * grp = getgrgid(st.st_gid);
    if (grp){
        strncpy(entry -> group, grp -> gr_name, 100);
    }

    // get the checksum
    calculate_checksum(entry);

    return 0;
}
Example #10
0
File: tar.c Project: calccrypto/tar
int tar_remove(const int fd, struct tar_t ** archive, const size_t filecount, const char * files[], const char verbosity){
    if (fd < 0){
        return -1;
    }

    // archive has to exist
    if (!archive || !*archive){
        return -1;
    }

    if (filecount && !files){
        return -1;
    }

    if (!filecount){
        return 0;
    }

    // get file permissions
    struct stat st;
    if (fstat(fd, &st)){
        RC_ERROR(stderr, "Error: Unable to stat archive: %s\n", strerror(rc));
    }

    // reset offset of original file
    if (lseek(fd, 0, SEEK_SET) == (off_t) (-1)){
        RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
    }

    // find first file to be removed that does not exist
    int ret = 0;
    char * bad = calloc(filecount, sizeof(char));
    for(int i = 0; i < filecount; i++){
        if (!exists(*archive, files[i], 0)){
            V_PRINT(stderr, "Error: %s not found in archive\n", files[i]);
            bad[i] = 1;
            ret = -1;
        }
    }

    unsigned int read_offset = 0;
    unsigned int write_offset = 0;
    struct tar_t * prev = NULL;
    struct tar_t * curr = *archive;
    while(curr){
        // get original size
        int total = 512;

        if ((curr -> type == REGULAR) || (curr -> type == NORMAL) || (curr -> type == CONTIGUOUS)){
            total += oct2uint(curr -> size, 11);
            if (total % 512){
                total += 512 - (total % 512);
            }
        }
        const int match = check_match(curr, filecount, bad, files);

        if (match < 0){
            V_PRINT(stderr, "Error: Match failed\n");
            return -1;
        }
        else if (!match){
            // if the old data is not in the right place, move it
            if (write_offset < read_offset){
                int got = 0;
                while (got < total){
                    // go to old data
                    if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
                        RC_ERROR(stderr, "Error: Cannot seek: %s\n", strerror(rc));
                    }

                    char buf[512];

                    // copy chunk out
                    if (read_size(fd, buf, 512) != 512){// guarenteed 512 octets
                        V_PRINT(stderr, "Error: Read error\n");
                        return -1;
                    }

                    // go to new position
                    if (lseek(fd, write_offset, SEEK_SET) == (off_t) (-1)){
                        RC_ERROR(stderr, "Error: Cannot seek: %s\n", strerror(rc));
                    }

                    // write data in
                    if (write_size(fd, buf, 512) != 512){
                        V_PRINT(stderr, "Error: Write error\n");
                        return -1;
                    }

                    // increment offsets
                    got += 512;
                    read_offset += 512;
                    write_offset += 512;
                }
            }
            else{
                read_offset += total;
                write_offset += total;

                // skip past data
                if (lseek(fd, read_offset, SEEK_SET) == (off_t) (-1)){
                    RC_ERROR(stderr, "Error: Cannot seek: %s\n", strerror(rc));
                }
            }
            prev = curr;
            curr = curr -> next;
        }
        else{// if name matches, skip the data
            struct tar_t * tmp = curr;
            if (!prev){
                *archive = curr -> next;
                if (*archive){
                    (*archive) -> begin = 0;
                }
            }
            else{
                prev -> next = curr -> next;

                if (prev -> next){
                    prev -> next -> begin = curr -> begin;
                }
            }
            curr = curr -> next;
            free(tmp);

            // next read starts after current entry
            read_offset += total;
        }
    }

    // resize file
    if (ftruncate(fd, write_offset) < 0){
        RC_ERROR(stderr, "Error: Could not truncate file: %s\n", strerror(rc));
    }

    // add end data
    if (write_end_data(fd, write_offset, verbosity) < 0){
        V_PRINT(stderr, "Error: Could not close file\n");
    }

    return ret;
}
Example #11
0
File: tar.c Project: calccrypto/tar
int tar_read(const int fd, struct tar_t ** archive, const char verbosity){
    if (fd < 0){
        return -1;
    }

    if (!archive || *archive){
        return -1;
    }

    unsigned int offset = 0;
    int count = 0;

    struct tar_t ** tar = archive;
    char update = 1;
    for(count = 0; ; count++){
        *tar = malloc(sizeof(struct tar_t));
        if (update && (read_size(fd, (*tar) -> block, 512) != 512)){
            V_PRINT(stderr, "Error: Bad read. Stopping\n");
            tar_free(*tar);
            *tar = NULL;
            break;
        }

        update = 1;
        // if current block is all zeros
        if (iszeroed((*tar) -> block, 512)){
            if (read_size(fd, (*tar) -> block, 512) != 512){
                V_PRINT(stderr, "Error: Bad read. Stopping\n");
                tar_free(*tar);
                *tar = NULL;
                break;
            }

            // check if next block is all zeros as well
            if (iszeroed((*tar) -> block, 512)){
                tar_free(*tar);
                *tar = NULL;

                // skip to end of record
                if (lseek(fd, RECORDSIZE - (offset % RECORDSIZE), SEEK_CUR) == (off_t) (-1)){
                    RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
                }

                break;
            }

            update = 0;
        }

        // set current entry's file offset
        (*tar) -> begin = offset;

        // skip over data and unfilled block
        unsigned int jump = oct2uint((*tar) -> size, 11);
        if (jump % 512){
            jump += 512 - (jump % 512);
        }

        // move file descriptor
        offset += 512 + jump;
        if (lseek(fd, jump, SEEK_CUR) == (off_t) (-1)){
            RC_ERROR(stderr, "Error: Unable to seek file: %s\n", strerror(rc));
        }

        // ready next value
        tar = &((*tar) -> next);
    }

    return count;
}
Example #12
0
ERROR_CODE help() {
    V_PRINT(HELP_STRING);
    RAISE_NO_ERROR;
}