2 * Copyright (C) 2015 The ChromiumOS Authors. All rights reserved.
3 * written by Daisuke Nojiri <dnojiri@chromium.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
24 static struct directory
*archive
;
26 static void usage(void)
29 printf(" archive - concatenate files and create an archive\n");
31 printf(" archive archive_name create file0 file1 ...\n");
34 static int get_file_size(const char *file
)
36 FILE *fp
= fopen(file
, "rb");
40 fprintf(stderr
, "Error: failed to open %s\n", file
);
43 fseek(fp
, 0, SEEK_END
);
47 fprintf(stderr
, "Error: failed to get file size\n");
54 static int set_file_name(const char *path
, struct dentry
*dest
)
61 name
= basename(copy
);
63 /* check name length */
64 if (strlen(name
) > NAME_LENGTH
) {
65 fprintf(stderr
, "Error: file name '%s' exceeds %d chars\n",
71 /* check if there is a duplicate name */
72 entry
= get_first_dentry(archive
);
73 for (i
= 0; i
< archive
->count
&& &entry
[i
] != dest
; i
++) {
74 if (!strncmp(entry
[i
].name
, name
, NAME_LENGTH
)) {
75 fprintf(stderr
, "Error: duplicate name '%s'\n", name
);
81 /* copy the name to the entry */
82 strncpy(dest
->name
, name
, NAME_LENGTH
);
89 * Add a file to the archive in RAM
91 * path: path to the file to be added
92 * entry: pointer to struct dentry where file header is created
93 * offset: offset of the file contents from the archive header
95 * return: 0 on success or -1 on error
97 static int add_file(const char *path
, struct dentry
*entry
, uint32_t offset
)
102 if (!path
|| !*path
|| !entry
) {
103 fprintf(stderr
, "Error: invalid path or entry\n");
107 size
= get_file_size(path
);
110 if (offset
+ size
> archive
->size
) {
111 fprintf(stderr
, "Error: invalid offset or size\n");
115 fp
= fopen(path
, "rb");
117 fprintf(stderr
, "Error: failed to open %s (%d: %s)\n",
118 path
, errno
, strerror(errno
));
121 if (fread((char *)archive
+ offset
, sizeof(char), size
, fp
) != size
) {
122 fprintf(stderr
, "Error: failed to read %s\n", path
);
129 if (set_file_name(path
, entry
))
132 entry
->offset
= offset
;
139 * Allocate memory for archive
141 * count: number of files to add
142 * files: pointer to the array of file names
144 * return: 0 on success or -1 on error
146 static int setup_archive(int count
, const char **files
)
151 size
= sizeof(*archive
);
152 for (i
= 0; i
< count
; i
++) {
153 s
= get_file_size(files
[i
]);
156 size
+= sizeof(struct dentry
);
160 archive
= calloc(size
, 1);
162 fprintf(stderr
, "Error: failed to allocate memory\n");
166 /* install magic string */
167 memcpy(archive
->magic
, CBAR_MAGIC
, sizeof(archive
->magic
));
168 archive
->version
= VERSION
;
169 archive
->size
= size
;
170 archive
->count
= count
;
172 printf("Set up archive: size=%d count=%d\n", size
, count
);
178 * Store files in archive
180 static int archive_files(const char **files
)
182 struct dentry
*entry
;
186 entry
= get_first_dentry(archive
);
187 offset
= get_first_offset(archive
);
188 for (i
= 0; i
< archive
->count
; i
++) {
189 if (add_file(files
[i
], entry
, offset
))
191 offset
+= entry
->size
;
198 static void convert_endian(void)
200 struct dentry
*entry
;
203 entry
= get_first_dentry(archive
);
204 for (i
= 0; i
< archive
->count
; i
++) {
205 entry
[i
].offset
= htole32(entry
[i
].offset
);
206 entry
[i
].size
= htole32(entry
[i
].size
);
209 archive
->version
= htole32(archive
->version
);
210 archive
->size
= htole32(archive
->size
);
211 archive
->count
= htole32(archive
->count
);
215 * Write archive to file
217 static int output_archive(const char *path
)
223 fp
= fopen(path
, "wb");
225 fprintf(stderr
, "Error: failed to open %s\n", path
);
229 if (fwrite(archive
, sizeof(char), archive
->size
, fp
) != archive
->size
) {
230 fprintf(stderr
, "Error: failed to write to %s\n", path
);
235 printf("Wrote archive to %s\n", path
);
240 static int cmd_create(const char *archive_path
, int count
, const char **files
)
242 if (count
< 1 || !files
) {
243 fprintf(stderr
, "Error: no input files specified\n");
247 if (setup_archive(count
, files
))
250 if (archive_files(files
))
253 if (output_archive(archive_path
))
259 int main(int argc
, const char *argv
[])
264 fprintf(stderr
, "Error: invalid number of arguments\n");
271 /* branch by command name */
272 if (!strncmp(command
, "create", sizeof("create"))) {
273 if (cmd_create(argv
[1], argc
- 3, &argv
[3]))
276 fprintf(stderr
, "Error: invalid command: %s\n", command
);