source: mainline/uspace/app/untar/main.c@ fd57cf17

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since fd57cf17 was b7fd2a0, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 8 years ago

Use errno_t in all uspace and kernel code.

Change type of every variable, parameter and return value that holds an
<errno.h> constant to either errno_t (the usual case), or sys_errno_t
(some places in kernel). This is for the purpose of self-documentation,
as well as for type-checking with a bit of type definition hackery.

Although this is a massive commit, it is a simple text replacement, and thus
is very easy to verify. Simply do the following:

`
git checkout <this commit's hash>
git reset HEAD
git add .
tools/srepl '\berrno_t\b' int
git add .
tools/srepl '\bsys_errno_t\b' sysarg_t
git reset
git diff
`

While this doesn't ensure that the replacements are correct, it does ensure
that the commit doesn't do anything except those replacements. Since errno_t
is typedef'd to int in the usual case (and sys_errno_t to sysarg_t), even if
incorrect, this commit cannot change behavior.

  • Property mode set to 100644
File size: 4.6 KB
Line 
1/*
2 * Copyright (c) 2013 Vojtech Horky
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup untar
30 * @{
31 */
32/** @file
33 */
34
35#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"
41
42static size_t get_block_count(size_t bytes) {
43 return (bytes + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE;
44}
45
46static errno_t skip_blocks(FILE *tarfile, size_t valid_data_size)
47{
48 size_t blocks_to_read = get_block_count(valid_data_size);
49 while (blocks_to_read > 0) {
50 uint8_t block[TAR_BLOCK_SIZE];
51 size_t actually_read = fread(block, TAR_BLOCK_SIZE, 1, tarfile);
52 if (actually_read != 1) {
53 return errno;
54 }
55 blocks_to_read--;
56 }
57 return EOK;
58}
59
60static errno_t handle_normal_file(const tar_header_t *header, FILE *tarfile)
61{
62 // FIXME: create the directory first
63
64 FILE *file = fopen(header->filename, "wb");
65 if (file == NULL) {
66 fprintf(stderr, "Failed to create %s: %s.\n", header->filename,
67 str_error(errno));
68 return errno;
69 }
70
71 errno_t rc = EOK;
72 size_t bytes_remaining = header->size;
73 size_t blocks = get_block_count(bytes_remaining);
74 while (blocks > 0) {
75 uint8_t block[TAR_BLOCK_SIZE];
76 size_t actually_read = fread(block, 1, TAR_BLOCK_SIZE, tarfile);
77 if (actually_read != TAR_BLOCK_SIZE) {
78 rc = errno;
79 fprintf(stderr, "Failed to read block for %s: %s.\n",
80 header->filename, str_error(rc));
81 break;
82 }
83 size_t to_write = TAR_BLOCK_SIZE;
84 if (bytes_remaining < TAR_BLOCK_SIZE) {
85 to_write = bytes_remaining;
86 }
87 size_t actually_written = fwrite(block, 1, to_write, file);
88 if (actually_written != to_write) {
89 rc = errno;
90 fprintf(stderr, "Failed to write to %s: %s.\n",
91 header->filename, str_error(rc));
92 break;
93 }
94 blocks--;
95 bytes_remaining -= TAR_BLOCK_SIZE;
96 }
97
98 fclose(file);
99
100 return rc;
101}
102
103static errno_t handle_directory(const tar_header_t *header, FILE *tarfile)
104{
105 errno_t rc;
106
107 rc = vfs_link_path(header->filename, KIND_DIRECTORY, NULL);
108 if (rc != EOK) {
109 if (rc != EEXIST) {
110 fprintf(stderr, "Failed to create directory %s: %s.\n",
111 header->filename, str_error(rc));
112 return rc;
113 }
114 }
115
116 return skip_blocks(tarfile, header->size);
117}
118
119int main(int argc, char *argv[])
120{
121 if (argc != 2) {
122 fprintf(stderr, "Usage: %s tar-file\n", argv[0]);
123 return 1;
124 }
125
126 const char *filename = argv[1];
127
128 FILE *tarfile = fopen(filename, "rb");
129 if (tarfile == NULL) {
130 fprintf(stderr, "Failed to open `%s': %s.\n", filename, str_error(errno));
131 return 2;
132 }
133
134 while (true) {
135 size_t header_ok;
136 tar_header_raw_t header_raw;
137 tar_header_t header;
138 header_ok = fread(&header_raw, sizeof(header_raw), 1, tarfile);
139 if (header_ok != 1) {
140 break;
141 }
142 errno_t rc = tar_header_parse(&header, &header_raw);
143 if (rc == EEMPTY) {
144 continue;
145 }
146 if (rc != EOK) {
147 fprintf(stderr, "Failed parsing TAR header: %s.\n", str_error(rc));
148 break;
149 }
150
151 //printf(" ==> %s (%zuB, type %s)\n", header.filename,
152 // header.size, tar_type_str(header.type));
153
154 switch (header.type) {
155 case TAR_TYPE_DIRECTORY:
156 rc = handle_directory(&header, tarfile);
157 break;
158 case TAR_TYPE_NORMAL:
159 rc = handle_normal_file(&header, tarfile);
160 break;
161 default:
162 rc = skip_blocks(tarfile, header.size);
163 break;
164 }
165 if (rc != EOK) {
166 break;
167 }
168
169 }
170
171 fclose(tarfile);
172
173 return 0;
174}
175
176/** @}
177 */
Note: See TracBrowser for help on using the repository browser.