|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include <sys/types.h> |
|
8 #include <sys/stat.h> |
|
9 #include <fcntl.h> |
|
10 #include <string.h> |
|
11 #include <stdlib.h> |
|
12 #include "mar_private.h" |
|
13 #include "mar.h" |
|
14 |
|
15 #ifdef XP_WIN |
|
16 #include <io.h> |
|
17 #include <direct.h> |
|
18 #endif |
|
19 |
|
20 /* Ensure that the directory containing this file exists */ |
|
21 static int mar_ensure_parent_dir(const char *path) |
|
22 { |
|
23 char *slash = strrchr(path, '/'); |
|
24 if (slash) |
|
25 { |
|
26 *slash = '\0'; |
|
27 mar_ensure_parent_dir(path); |
|
28 #ifdef XP_WIN |
|
29 _mkdir(path); |
|
30 #else |
|
31 mkdir(path, 0755); |
|
32 #endif |
|
33 *slash = '/'; |
|
34 } |
|
35 return 0; |
|
36 } |
|
37 |
|
38 static int mar_test_callback(MarFile *mar, const MarItem *item, void *unused) { |
|
39 FILE *fp; |
|
40 char buf[BLOCKSIZE]; |
|
41 int fd, len, offset = 0; |
|
42 |
|
43 if (mar_ensure_parent_dir(item->name)) |
|
44 return -1; |
|
45 |
|
46 #ifdef XP_WIN |
|
47 fd = _open(item->name, _O_BINARY|_O_CREAT|_O_TRUNC|_O_WRONLY, item->flags); |
|
48 #else |
|
49 fd = creat(item->name, item->flags); |
|
50 #endif |
|
51 if (fd == -1) { |
|
52 fprintf(stderr, "ERROR: could not create file in mar_test_callback()\n"); |
|
53 perror(item->name); |
|
54 return -1; |
|
55 } |
|
56 |
|
57 fp = fdopen(fd, "wb"); |
|
58 if (!fp) |
|
59 return -1; |
|
60 |
|
61 while ((len = mar_read(mar, item, offset, buf, sizeof(buf))) > 0) { |
|
62 if (fwrite(buf, len, 1, fp) != 1) |
|
63 break; |
|
64 offset += len; |
|
65 } |
|
66 |
|
67 fclose(fp); |
|
68 return len == 0 ? 0 : -1; |
|
69 } |
|
70 |
|
71 int mar_extract(const char *path) { |
|
72 MarFile *mar; |
|
73 int rv; |
|
74 |
|
75 mar = mar_open(path); |
|
76 if (!mar) |
|
77 return -1; |
|
78 |
|
79 rv = mar_enum_items(mar, mar_test_callback, NULL); |
|
80 |
|
81 mar_close(mar); |
|
82 return rv; |
|
83 } |