Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 24fda5e in mainline


Ignore:
Timestamp:
2018-06-05T16:05:16Z (3 years ago)
Author:
Martin Decky <martin@…>
Branches:
master
Children:
18ad56a8, 8404342
Parents:
04051b8e
Message:

separate the TAR extraction to a library to make the code reusable

Location:
uspace
Files:
3 added
3 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/Makefile

    r04051b8e r24fda5e  
    214214        lib/c \
    215215        lib/softint \
    216         lib/softfloat
     216        lib/softfloat \
     217        lib/untar
    217218
    218219LIBS = \
  • uspace/app/untar/Makefile

    r04051b8e r24fda5e  
    3030BINARY = untar
    3131
     32LIBS = untar
     33
    3234SOURCES = \
    33         main.c \
    34         tar.c
     35        main.c
    3536
    3637include $(USPACE_PREFIX)/Makefile.common
  • uspace/app/untar/main.c

    r04051b8e r24fda5e  
    3434
    3535#include <stdio.h>
    36 #include <stdlib.h>
    37 #include <errno.h>
    38 #include <str_error.h>
    39 #include <vfs/vfs.h>
    40 #include "tar.h"
     36#include <stdarg.h>
     37#include <untar.h>
    4138
    42 static size_t get_block_count(size_t bytes)
     39const char *filename;
     40
     41static int tar_open(tar_file_t *tar)
    4342{
    44         return (bytes + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
    45 }
     43        FILE *file = fopen(filename, "rb");
     44        if (file == NULL)
     45                return errno;
    4646
    47 static errno_t skip_blocks(FILE *tarfile, size_t valid_data_size)
    48 {
    49         size_t blocks_to_read = get_block_count(valid_data_size);
    50         while (blocks_to_read > 0) {
    51                 uint8_t block[TAR_BLOCK_SIZE];
    52                 size_t actually_read = fread(block, TAR_BLOCK_SIZE, 1, tarfile);
    53                 if (actually_read != 1) {
    54                         return errno;
    55                 }
    56                 blocks_to_read--;
    57         }
     47        tar->data = (void *) file;
    5848        return EOK;
    5949}
    6050
    61 static errno_t handle_normal_file(const tar_header_t *header, FILE *tarfile)
     51static void tar_close(tar_file_t *tar)
    6252{
    63         // FIXME: create the directory first
    64 
    65         FILE *file = fopen(header->filename, "wb");
    66         if (file == NULL) {
    67                 fprintf(stderr, "Failed to create %s: %s.\n", header->filename,
    68                     str_error(errno));
    69                 return errno;
    70         }
    71 
    72         errno_t rc = EOK;
    73         size_t bytes_remaining = header->size;
    74         size_t blocks = get_block_count(bytes_remaining);
    75         while (blocks > 0) {
    76                 uint8_t block[TAR_BLOCK_SIZE];
    77                 size_t actually_read = fread(block, 1, TAR_BLOCK_SIZE, tarfile);
    78                 if (actually_read != TAR_BLOCK_SIZE) {
    79                         rc = errno;
    80                         fprintf(stderr, "Failed to read block for %s: %s.\n",
    81                             header->filename, str_error(rc));
    82                         break;
    83                 }
    84                 size_t to_write = TAR_BLOCK_SIZE;
    85                 if (bytes_remaining < TAR_BLOCK_SIZE) {
    86                         to_write = bytes_remaining;
    87                 }
    88                 size_t actually_written = fwrite(block, 1, to_write, file);
    89                 if (actually_written != to_write) {
    90                         rc = errno;
    91                         fprintf(stderr, "Failed to write to %s: %s.\n",
    92                             header->filename, str_error(rc));
    93                         break;
    94                 }
    95                 blocks--;
    96                 bytes_remaining -= TAR_BLOCK_SIZE;
    97         }
    98 
     53        FILE *file = (FILE *) tar->data;
    9954        fclose(file);
    100 
    101         return rc;
    10255}
    10356
    104 static errno_t handle_directory(const tar_header_t *header, FILE *tarfile)
     57static size_t tar_read(tar_file_t *tar, void *data, size_t size)
    10558{
    106         errno_t rc;
     59        FILE *file = (FILE *) tar->data;
     60        return fread(data, 1, size, file);
     61}
    10762
    108         rc = vfs_link_path(header->filename, KIND_DIRECTORY, NULL);
    109         if (rc != EOK) {
    110                 if (rc != EEXIST) {
    111                         fprintf(stderr, "Failed to create directory %s: %s.\n",
    112                             header->filename, str_error(rc));
    113                         return rc;
    114                 }
    115         }
     63static void tar_vreport(tar_file_t *tar, const char *fmt, va_list args)
     64{
     65        vfprintf(stderr, fmt, args);
     66}
    11667
    117         return skip_blocks(tarfile, header->size);
    118 }
     68tar_file_t tar = {
     69        .open = tar_open,
     70        .close = tar_close,
     71
     72        .read = tar_read,
     73        .vreport = tar_vreport
     74};
    11975
    12076int main(int argc, char *argv[])
     
    12581        }
    12682
    127         const char *filename = argv[1];
    128 
    129         FILE *tarfile = fopen(filename, "rb");
    130         if (tarfile == NULL) {
    131                 fprintf(stderr, "Failed to open `%s': %s.\n", filename, str_error(errno));
    132                 return 2;
    133         }
    134 
    135         while (true) {
    136                 size_t header_ok;
    137                 tar_header_raw_t header_raw;
    138                 tar_header_t header;
    139                 header_ok = fread(&header_raw, sizeof(header_raw), 1, tarfile);
    140                 if (header_ok != 1) {
    141                         break;
    142                 }
    143                 errno_t rc = tar_header_parse(&header, &header_raw);
    144                 if (rc == EEMPTY) {
    145                         continue;
    146                 }
    147                 if (rc != EOK) {
    148                         fprintf(stderr, "Failed parsing TAR header: %s.\n", str_error(rc));
    149                         break;
    150                 }
    151 
    152                 //printf(" ==> %s (%zuB, type %s)\n", header.filename,
    153                 //    header.size, tar_type_str(header.type));
    154 
    155                 switch (header.type) {
    156                 case TAR_TYPE_DIRECTORY:
    157                         rc = handle_directory(&header, tarfile);
    158                         break;
    159                 case TAR_TYPE_NORMAL:
    160                         rc = handle_normal_file(&header, tarfile);
    161                         break;
    162                 default:
    163                         rc = skip_blocks(tarfile, header.size);
    164                         break;
    165                 }
    166                 if (rc != EOK) {
    167                         break;
    168                 }
    169 
    170         }
    171 
    172         fclose(tarfile);
    173 
    174         return 0;
     83        filename = argv[1];
     84        return untar(&tar);
    17585}
    17686
  • uspace/lib/untar/private/tar.h

    r04051b8e r24fda5e  
    2727 */
    2828
    29 /** @addtogroup untar
     29/** @addtogroup libuntar
    3030 * @{
    3131 */
    3232/** @file
    3333 */
    34 #ifndef TAR_H_GUARD
    35 #define TAR_H_GUARD
     34
     35#ifndef TAR_H_
     36#define TAR_H_
    3637
    3738#define TAR_BLOCK_SIZE 512
     
    6970} tar_header_t;
    7071
    71 
    7272extern errno_t tar_header_parse(tar_header_t *, const tar_header_raw_t *);
    7373extern tar_type_t tar_type_parse(const char);
  • uspace/lib/untar/tar.c

    r04051b8e r24fda5e  
    2727 */
    2828
    29 /** @addtogroup untar
     29/** @addtogroup libuntar
    3030 * @{
    3131 */
     
    3838#include <errno.h>
    3939#include <assert.h>
    40 
    41 #include "tar.h"
     40#include "private/tar.h"
    4241
    4342tar_type_t tar_type_parse(const char type)
     
    7170errno_t tar_header_parse(tar_header_t *parsed, const tar_header_raw_t *raw)
    7271{
    73         errno_t rc;
    74 
    7572        if (str_length(raw->filename) == 0) {
    7673                return EEMPTY;
     
    7875
    7976        size_t size;
    80         rc = str_size_t(raw->size, NULL, 8, true, &size);
     77        errno_t rc = str_size_t(raw->size, NULL, 8, true, &size);
    8178        if (rc != EOK) {
    8279                return rc;
Note: See TracChangeset for help on using the changeset viewer.