Changes in uspace/app/untar/main.c [1433ecda:55092672] in mainline
- File:
-
- 1 edited
-
uspace/app/untar/main.c (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/untar/main.c
r1433ecda r55092672 33 33 */ 34 34 35 #include <errno.h> 35 36 #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" 37 #include <stdarg.h> 38 #include <untar.h> 41 39 42 static size_t get_block_count(size_t bytes) 40 typedef struct { 41 const char *filename; 42 FILE *file; 43 } tar_state_t; 44 45 static int tar_open(tar_file_t *tar) 43 46 { 44 return (bytes + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE; 45 } 47 tar_state_t *state = (tar_state_t *) tar->data; 46 48 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 } 49 state->file = fopen(state->filename, "rb"); 50 if (state->file == NULL) 51 return errno; 52 58 53 return EOK; 59 54 } 60 55 61 static errno_t handle_normal_file(const tar_header_t *header, FILE *tarfile)56 static void tar_close(tar_file_t *tar) 62 57 { 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 99 fclose(file); 100 101 return rc; 58 tar_state_t *state = (tar_state_t *) tar->data; 59 fclose(state->file); 102 60 } 103 61 104 static errno_t handle_directory(const tar_header_t *header, FILE *tarfile)62 static size_t tar_read(tar_file_t *tar, void *data, size_t size) 105 63 { 106 errno_t rc; 64 tar_state_t *state = (tar_state_t *) tar->data; 65 return fread(data, 1, size, state->file); 66 } 107 67 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 } 68 static void tar_vreport(tar_file_t *tar, const char *fmt, va_list args) 69 { 70 vfprintf(stderr, fmt, args); 71 } 116 72 117 return skip_blocks(tarfile, header->size); 118 } 73 tar_file_t tar = { 74 .open = tar_open, 75 .close = tar_close, 76 77 .read = tar_read, 78 .vreport = tar_vreport 79 }; 119 80 120 81 int main(int argc, char *argv[]) … … 125 86 } 126 87 127 const char *filename = argv[1]; 88 tar_state_t state; 89 state.filename = argv[1]; 128 90 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; 91 tar.data = (void *) &state; 92 return untar(&tar); 175 93 } 176 94
Note:
See TracChangeset
for help on using the changeset viewer.
