summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archive/microtar-0.1.0.tar.gzbin0 -> 4843 bytes
-rw-r--r--vendor/microtar-0.1.0/LICENSE19
-rw-r--r--vendor/microtar-0.1.0/README.md99
-rw-r--r--vendor/microtar-0.1.0/src/microtar.c376
-rw-r--r--vendor/microtar-0.1.0/src/microtar.h82
5 files changed, 576 insertions, 0 deletions
diff --git a/archive/microtar-0.1.0.tar.gz b/archive/microtar-0.1.0.tar.gz
new file mode 100644
index 0000000..f7211f6
--- /dev/null
+++ b/archive/microtar-0.1.0.tar.gz
Binary files differ
diff --git a/vendor/microtar-0.1.0/LICENSE b/vendor/microtar-0.1.0/LICENSE
new file mode 100644
index 0000000..7e3bf17
--- /dev/null
+++ b/vendor/microtar-0.1.0/LICENSE
@@ -0,0 +1,19 @@
1Copyright (c) 2017 rxi
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/vendor/microtar-0.1.0/README.md b/vendor/microtar-0.1.0/README.md
new file mode 100644
index 0000000..42acf49
--- /dev/null
+++ b/vendor/microtar-0.1.0/README.md
@@ -0,0 +1,99 @@
1# microtar
2A lightweight tar library written in ANSI C
3
4
5## Basic Usage
6The library consists of `microtar.c` and `microtar.h`. These two files can be
7dropped into an existing project and compiled along with it.
8
9
10#### Reading
11```c
12mtar_t tar;
13mtar_header_t h;
14char *p;
15
16/* Open archive for reading */
17mtar_open(&tar, "test.tar", "r");
18
19/* Print all file names and sizes */
20while ( (mtar_read_header(&tar, &h)) != MTAR_ENULLRECORD ) {
21 printf("%s (%d bytes)\n", h.name, h.size);
22 mtar_next(&tar);
23}
24
25/* Load and print contents of file "test.txt" */
26mtar_find(&tar, "test.txt", &h);
27p = calloc(1, h.size + 1);
28mtar_read_data(&tar, p, h.size);
29printf("%s", p);
30free(p);
31
32/* Close archive */
33mtar_close(&tar);
34```
35
36#### Writing
37```c
38mtar_t tar;
39const char *str1 = "Hello world";
40const char *str2 = "Goodbye world";
41
42/* Open archive for writing */
43mtar_open(&tar, "test.tar", "w");
44
45/* Write strings to files `test1.txt` and `test2.txt` */
46mtar_write_file_header(&tar, "test1.txt", strlen(str1));
47mtar_write_data(&tar, str1, strlen(str1));
48mtar_write_file_header(&tar, "test2.txt", strlen(str2));
49mtar_write_data(&tar, str2, strlen(str2));
50
51/* Finalize -- this needs to be the last thing done before closing */
52mtar_finalize(&tar);
53
54/* Close archive */
55mtar_close(&tar);
56```
57
58
59## Error handling
60All functions which return an `int` will return `MTAR_ESUCCESS` if the operation
61is successful. If an error occurs an error value less-than-zero will be
62returned; this value can be passed to the function `mtar_strerror()` to get its
63corresponding error string.
64
65
66## Wrapping a stream
67If you want to read or write from something other than a file, the `mtar_t`
68struct can be manually initialized with your own callback functions and a
69`stream` pointer.
70
71All callback functions are passed a pointer to the `mtar_t` struct as their
72first argument. They should return `MTAR_ESUCCESS` if the operation succeeds
73without an error, or an integer below zero if an error occurs.
74
75After the `stream` field has been set, all required callbacks have been set and
76all unused fields have been zeroset the `mtar_t` struct can be safely used with
77the microtar functions. `mtar_open` *should not* be called if the `mtar_t`
78struct was initialized manually.
79
80#### Reading
81The following callbacks should be set for reading an archive from a stream:
82
83Name | Arguments | Description
84--------|------------------------------------------|---------------------------
85`read` | `mtar_t *tar, void *data, unsigned size` | Read data from the stream
86`seek` | `mtar_t *tar, unsigned pos` | Set the position indicator
87`close` | `mtar_t *tar` | Close the stream
88
89#### Writing
90The following callbacks should be set for writing an archive to a stream:
91
92Name | Arguments | Description
93--------|------------------------------------------------|---------------------
94`write` | `mtar_t *tar, const void *data, unsigned size` | Write data to the stream
95
96
97## License
98This library is free software; you can redistribute it and/or modify it under
99the terms of the MIT license. See [LICENSE](LICENSE) for details.
diff --git a/vendor/microtar-0.1.0/src/microtar.c b/vendor/microtar-0.1.0/src/microtar.c
new file mode 100644
index 0000000..4b89776
--- /dev/null
+++ b/vendor/microtar-0.1.0/src/microtar.c
@@ -0,0 +1,376 @@
1/*
2 * Copyright (c) 2017 rxi
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 * IN THE SOFTWARE.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <stddef.h>
26#include <string.h>
27
28#include "microtar.h"
29
30typedef struct {
31 char name[100];
32 char mode[8];
33 char owner[8];
34 char group[8];
35 char size[12];
36 char mtime[12];
37 char checksum[8];
38 char type;
39 char linkname[100];
40 char _padding[255];
41} mtar_raw_header_t;
42
43
44static unsigned round_up(unsigned n, unsigned incr) {
45 return n + (incr - n % incr) % incr;
46}
47
48
49static unsigned checksum(const mtar_raw_header_t* rh) {
50 unsigned i;
51 unsigned char *p = (unsigned char*) rh;
52 unsigned res = 256;
53 for (i = 0; i < offsetof(mtar_raw_header_t, checksum); i++) {
54 res += p[i];
55 }
56 for (i = offsetof(mtar_raw_header_t, type); i < sizeof(*rh); i++) {
57 res += p[i];
58 }
59 return res;
60}
61
62
63static int tread(mtar_t *tar, void *data, unsigned size) {
64 int err = tar->read(tar, data, size);
65 tar->pos += size;
66 return err;
67}
68
69
70static int twrite(mtar_t *tar, const void *data, unsigned size) {
71 int err = tar->write(tar, data, size);
72 tar->pos += size;
73 return err;
74}
75
76
77static int write_null_bytes(mtar_t *tar, int n) {
78 int i, err;
79 char nul = '\0';
80 for (i = 0; i < n; i++) {
81 err = twrite(tar, &nul, 1);
82 if (err) {
83 return err;
84 }
85 }
86 return MTAR_ESUCCESS;
87}
88
89
90static int raw_to_header(mtar_header_t *h, const mtar_raw_header_t *rh) {
91 unsigned chksum1, chksum2;
92
93 /* If the checksum starts with a null byte we assume the record is NULL */
94 if (*rh->checksum == '\0') {
95 return MTAR_ENULLRECORD;
96 }
97
98 /* Build and compare checksum */
99 chksum1 = checksum(rh);
100 sscanf(rh->checksum, "%o", &chksum2);
101 if (chksum1 != chksum2) {
102 return MTAR_EBADCHKSUM;
103 }
104
105 /* Load raw header into header */
106 sscanf(rh->mode, "%o", &h->mode);
107 sscanf(rh->owner, "%o", &h->owner);
108 sscanf(rh->size, "%o", &h->size);
109 sscanf(rh->mtime, "%o", &h->mtime);
110 h->type = rh->type;
111 strcpy(h->name, rh->name);
112 strcpy(h->linkname, rh->linkname);
113
114 return MTAR_ESUCCESS;
115}
116
117
118static int header_to_raw(mtar_raw_header_t *rh, const mtar_header_t *h) {
119 unsigned chksum;
120
121 /* Load header into raw header */
122 memset(rh, 0, sizeof(*rh));
123 sprintf(rh->mode, "%o", h->mode);
124 sprintf(rh->owner, "%o", h->owner);
125 sprintf(rh->size, "%o", h->size);
126 sprintf(rh->mtime, "%o", h->mtime);
127 rh->type = h->type ? h->type : MTAR_TREG;
128 strcpy(rh->name, h->name);
129 strcpy(rh->linkname, h->linkname);
130
131 /* Calculate and write checksum */
132 chksum = checksum(rh);
133 sprintf(rh->checksum, "%06o", chksum);
134 rh->checksum[7] = ' ';
135
136 return MTAR_ESUCCESS;
137}
138
139
140const char* mtar_strerror(int err) {
141 switch (err) {
142 case MTAR_ESUCCESS : return "success";
143 case MTAR_EFAILURE : return "failure";
144 case MTAR_EOPENFAIL : return "could not open";
145 case MTAR_EREADFAIL : return "could not read";
146 case MTAR_EWRITEFAIL : return "could not write";
147 case MTAR_ESEEKFAIL : return "could not seek";
148 case MTAR_EBADCHKSUM : return "bad checksum";
149 case MTAR_ENULLRECORD : return "null record";
150 case MTAR_ENOTFOUND : return "file not found";
151 }
152 return "unknown error";
153}
154
155
156static int file_write(mtar_t *tar, const void *data, unsigned size) {
157 unsigned res = fwrite(data, 1, size, tar->stream);
158 return (res == size) ? MTAR_ESUCCESS : MTAR_EWRITEFAIL;
159}
160
161static int file_read(mtar_t *tar, void *data, unsigned size) {
162 unsigned res = fread(data, 1, size, tar->stream);
163 return (res == size) ? MTAR_ESUCCESS : MTAR_EREADFAIL;
164}
165
166static int file_seek(mtar_t *tar, unsigned offset) {
167 int res = fseek(tar->stream, offset, SEEK_SET);
168 return (res == 0) ? MTAR_ESUCCESS : MTAR_ESEEKFAIL;
169}
170
171static int file_close(mtar_t *tar) {
172 fclose(tar->stream);
173 return MTAR_ESUCCESS;
174}
175
176
177int mtar_open(mtar_t *tar, const char *filename, const char *mode) {
178 int err;
179 mtar_header_t h;
180
181 /* Init tar struct and functions */
182 memset(tar, 0, sizeof(*tar));
183 tar->write = file_write;
184 tar->read = file_read;
185 tar->seek = file_seek;
186 tar->close = file_close;
187
188 /* Assure mode is always binary */
189 if ( strchr(mode, 'r') ) mode = "rb";
190 if ( strchr(mode, 'w') ) mode = "wb";
191 if ( strchr(mode, 'a') ) mode = "ab";
192 /* Open file */
193 tar->stream = fopen(filename, mode);
194 if (!tar->stream) {
195 return MTAR_EOPENFAIL;
196 }
197 /* Read first header to check it is valid if mode is `r` */
198 if (*mode == 'r') {
199 err = mtar_read_header(tar, &h);
200 if (err != MTAR_ESUCCESS) {
201 mtar_close(tar);
202 return err;
203 }
204 }
205
206 /* Return ok */
207 return MTAR_ESUCCESS;
208}
209
210
211int mtar_close(mtar_t *tar) {
212 return tar->close(tar);
213}
214
215
216int mtar_seek(mtar_t *tar, unsigned pos) {
217 int err = tar->seek(tar, pos);
218 tar->pos = pos;
219 return err;
220}
221
222
223int mtar_rewind(mtar_t *tar) {
224 tar->remaining_data = 0;
225 tar->last_header = 0;
226 return mtar_seek(tar, 0);
227}
228
229
230int mtar_next(mtar_t *tar) {
231 int err, n;
232 mtar_header_t h;
233 /* Load header */
234 err = mtar_read_header(tar, &h);
235 if (err) {
236 return err;
237 }
238 /* Seek to next record */
239 n = round_up(h.size, 512) + sizeof(mtar_raw_header_t);
240 return mtar_seek(tar, tar->pos + n);
241}
242
243
244int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h) {
245 int err;
246 mtar_header_t header;
247 /* Start at beginning */
248 err = mtar_rewind(tar);
249 if (err) {
250 return err;
251 }
252 /* Iterate all files until we hit an error or find the file */
253 while ( (err = mtar_read_header(tar, &header)) == MTAR_ESUCCESS ) {
254 if ( !strcmp(header.name, name) ) {
255 if (h) {
256 *h = header;
257 }
258 return MTAR_ESUCCESS;
259 }
260 mtar_next(tar);
261 }
262 /* Return error */
263 if (err == MTAR_ENULLRECORD) {
264 err = MTAR_ENOTFOUND;
265 }
266 return err;
267}
268
269
270int mtar_read_header(mtar_t *tar, mtar_header_t *h) {
271 int err;
272 mtar_raw_header_t rh;
273 /* Save header position */
274 tar->last_header = tar->pos;
275 /* Read raw header */
276 err = tread(tar, &rh, sizeof(rh));
277 if (err) {
278 return err;
279 }
280 /* Seek back to start of header */
281 err = mtar_seek(tar, tar->last_header);
282 if (err) {
283 return err;
284 }
285 /* Load raw header into header struct and return */
286 return raw_to_header(h, &rh);
287}
288
289
290int mtar_read_data(mtar_t *tar, void *ptr, unsigned size) {
291 int err;
292 /* If we have no remaining data then this is the first read, we get the size,
293 * set the remaining data and seek to the beginning of the data */
294 if (tar->remaining_data == 0) {
295 mtar_header_t h;
296 /* Read header */
297 err = mtar_read_header(tar, &h);
298 if (err) {
299 return err;
300 }
301 /* Seek past header and init remaining data */
302 err = mtar_seek(tar, tar->pos + sizeof(mtar_raw_header_t));
303 if (err) {
304 return err;
305 }
306 tar->remaining_data = h.size;
307 }
308 /* Read data */
309 err = tread(tar, ptr, size);
310 if (err) {
311 return err;
312 }
313 tar->remaining_data -= size;
314 /* If there is no remaining data we've finished reading and seek back to the
315 * header */
316 if (tar->remaining_data == 0) {
317 return mtar_seek(tar, tar->last_header);
318 }
319 return MTAR_ESUCCESS;
320}
321
322
323int mtar_write_header(mtar_t *tar, const mtar_header_t *h) {
324 mtar_raw_header_t rh;
325 /* Build raw header and write */
326 header_to_raw(&rh, h);
327 tar->remaining_data = h->size;
328 return twrite(tar, &rh, sizeof(rh));
329}
330
331
332int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size) {
333 mtar_header_t h;
334 /* Build header */
335 memset(&h, 0, sizeof(h));
336 strcpy(h.name, name);
337 h.size = size;
338 h.type = MTAR_TREG;
339 h.mode = 0664;
340 /* Write header */
341 return mtar_write_header(tar, &h);
342}
343
344
345int mtar_write_dir_header(mtar_t *tar, const char *name) {
346 mtar_header_t h;
347 /* Build header */
348 memset(&h, 0, sizeof(h));
349 strcpy(h.name, name);
350 h.type = MTAR_TDIR;
351 h.mode = 0775;
352 /* Write header */
353 return mtar_write_header(tar, &h);
354}
355
356
357int mtar_write_data(mtar_t *tar, const void *data, unsigned size) {
358 int err;
359 /* Write data */
360 err = twrite(tar, data, size);
361 if (err) {
362 return err;
363 }
364 tar->remaining_data -= size;
365 /* Write padding if we've written all the data for this file */
366 if (tar->remaining_data == 0) {
367 return write_null_bytes(tar, round_up(tar->pos, 512) - tar->pos);
368 }
369 return MTAR_ESUCCESS;
370}
371
372
373int mtar_finalize(mtar_t *tar) {
374 /* Write two NULL records */
375 return write_null_bytes(tar, sizeof(mtar_raw_header_t) * 2);
376}
diff --git a/vendor/microtar-0.1.0/src/microtar.h b/vendor/microtar-0.1.0/src/microtar.h
new file mode 100644
index 0000000..8a047e3
--- /dev/null
+++ b/vendor/microtar-0.1.0/src/microtar.h
@@ -0,0 +1,82 @@
1/**
2 * Copyright (c) 2017 rxi
3 *
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the MIT license. See `microtar.c` for details.
6 */
7
8#ifndef MICROTAR_H
9#define MICROTAR_H
10
11#include <stdio.h>
12#include <stdlib.h>
13
14#define MTAR_VERSION "0.1.0"
15
16enum {
17 MTAR_ESUCCESS = 0,
18 MTAR_EFAILURE = -1,
19 MTAR_EOPENFAIL = -2,
20 MTAR_EREADFAIL = -3,
21 MTAR_EWRITEFAIL = -4,
22 MTAR_ESEEKFAIL = -5,
23 MTAR_EBADCHKSUM = -6,
24 MTAR_ENULLRECORD = -7,
25 MTAR_ENOTFOUND = -8
26};
27
28enum {
29 MTAR_TREG = '0',
30 MTAR_TLNK = '1',
31 MTAR_TSYM = '2',
32 MTAR_TCHR = '3',
33 MTAR_TBLK = '4',
34 MTAR_TDIR = '5',
35 MTAR_TFIFO = '6'
36};
37
38typedef struct {
39 unsigned mode;
40 unsigned owner;
41 unsigned size;
42 unsigned mtime;
43 unsigned type;
44 char name[100];
45 char linkname[100];
46} mtar_header_t;
47
48
49typedef struct mtar_t mtar_t;
50
51struct mtar_t {
52 int (*read)(mtar_t *tar, void *data, unsigned size);
53 int (*write)(mtar_t *tar, const void *data, unsigned size);
54 int (*seek)(mtar_t *tar, unsigned pos);
55 int (*close)(mtar_t *tar);
56 void *stream;
57 unsigned pos;
58 unsigned remaining_data;
59 unsigned last_header;
60};
61
62
63const char* mtar_strerror(int err);
64
65int mtar_open(mtar_t *tar, const char *filename, const char *mode);
66int mtar_close(mtar_t *tar);
67
68int mtar_seek(mtar_t *tar, unsigned pos);
69int mtar_rewind(mtar_t *tar);
70int mtar_next(mtar_t *tar);
71int mtar_find(mtar_t *tar, const char *name, mtar_header_t *h);
72int mtar_read_header(mtar_t *tar, mtar_header_t *h);
73int mtar_read_data(mtar_t *tar, void *ptr, unsigned size);
74
75int mtar_write_header(mtar_t *tar, const mtar_header_t *h);
76int mtar_write_file_header(mtar_t *tar, const char *name, unsigned size);
77int mtar_write_dir_header(mtar_t *tar, const char *name);
78int mtar_write_data(mtar_t *tar, const void *data, unsigned size);
79int mtar_finalize(mtar_t *tar);
80
81
82#endif