1 /* SPDX-License-Identifier: GPL-2.0-only */
12 static struct directory
*archive
;
14 static void usage(void)
17 printf(" archive - concatenate files and create an archive\n");
19 printf(" archive archive_name create file0 file1 ...\n");
22 static int get_file_size(const char *file
)
24 FILE *fp
= fopen(file
, "rb");
28 fprintf(stderr
, "Error: failed to open %s\n", file
);
31 fseek(fp
, 0, SEEK_END
);
35 fprintf(stderr
, "Error: failed to get file size\n");
42 static int set_file_name(const char *path
, struct dentry
*dest
)
49 name
= basename(copy
);
51 /* check name length */
52 if (strlen(name
) > NAME_LENGTH
) {
53 fprintf(stderr
, "Error: file name '%s' exceeds %d chars\n",
59 /* check if there is a duplicate name */
60 entry
= get_first_dentry(archive
);
61 for (i
= 0; i
< archive
->count
&& &entry
[i
] != dest
; i
++) {
62 if (!strncmp(entry
[i
].name
, name
, NAME_LENGTH
)) {
63 fprintf(stderr
, "Error: duplicate name '%s'\n", name
);
69 /* copy the name to the entry */
70 strncpy(dest
->name
, name
, NAME_LENGTH
);
77 * Add a file to the archive in RAM
79 * path: path to the file to be added
80 * entry: pointer to struct dentry where file header is created
81 * offset: offset of the file contents from the archive header
83 * return: 0 on success or -1 on error
85 static int add_file(const char *path
, struct dentry
*entry
, uint32_t offset
)
90 if (!path
|| !*path
|| !entry
) {
91 fprintf(stderr
, "Error: invalid path or entry\n");
95 size
= get_file_size(path
);
98 if (offset
+ size
> archive
->size
) {
99 fprintf(stderr
, "Error: invalid offset or size\n");
103 fp
= fopen(path
, "rb");
105 fprintf(stderr
, "Error: failed to open %s (%d: %s)\n",
106 path
, errno
, strerror(errno
));
109 if (fread((char *)archive
+ offset
, sizeof(char), size
, fp
) != (size_t)size
) {
110 fprintf(stderr
, "Error: failed to read %s\n", path
);
117 if (set_file_name(path
, entry
))
120 entry
->offset
= offset
;
127 * Allocate memory for archive
129 * count: number of files to add
130 * files: pointer to the array of file names
132 * return: 0 on success or -1 on error
134 static int setup_archive(int count
, const char **files
)
139 size
= sizeof(*archive
);
140 for (i
= 0; i
< count
; i
++) {
141 s
= get_file_size(files
[i
]);
144 size
+= sizeof(struct dentry
);
148 archive
= calloc(size
, 1);
150 fprintf(stderr
, "Error: failed to allocate memory\n");
154 /* install magic string */
155 memcpy(archive
->magic
, CBAR_MAGIC
, sizeof(archive
->magic
));
156 archive
->version
= VERSION
;
157 archive
->size
= size
;
158 archive
->count
= count
;
160 printf("Set up archive: size=%d count=%d\n", size
, count
);
166 * Store files in archive
168 static int archive_files(const char **files
)
170 struct dentry
*entry
;
174 entry
= get_first_dentry(archive
);
175 offset
= get_first_offset(archive
);
176 for (i
= 0; i
< archive
->count
; i
++) {
177 if (add_file(files
[i
], entry
, offset
))
179 offset
+= entry
->size
;
186 static void convert_endian(void)
188 struct dentry
*entry
;
191 entry
= get_first_dentry(archive
);
192 for (i
= 0; i
< archive
->count
; i
++) {
193 entry
[i
].offset
= htole32(entry
[i
].offset
);
194 entry
[i
].size
= htole32(entry
[i
].size
);
197 archive
->version
= htole32(archive
->version
);
198 archive
->size
= htole32(archive
->size
);
199 archive
->count
= htole32(archive
->count
);
203 * Write archive to file
205 static int output_archive(const char *path
)
211 fp
= fopen(path
, "wb");
213 fprintf(stderr
, "Error: failed to open %s\n", path
);
217 if (fwrite(archive
, sizeof(char), archive
->size
, fp
) != archive
->size
) {
218 fprintf(stderr
, "Error: failed to write to %s\n", path
);
223 printf("Wrote archive to %s\n", path
);
228 static int cmd_create(const char *archive_path
, int count
, const char **files
)
230 if (count
< 1 || !files
) {
231 fprintf(stderr
, "Error: no input files specified\n");
235 if (setup_archive(count
, files
))
238 if (archive_files(files
))
241 if (output_archive(archive_path
))
247 int main(int argc
, const char *argv
[])
252 fprintf(stderr
, "Error: invalid number of arguments\n");
259 /* branch by command name */
260 if (!strncmp(command
, "create", sizeof("create"))) {
261 if (cmd_create(argv
[1], argc
- 3, &argv
[3]))
264 fprintf(stderr
, "Error: invalid command: %s\n", command
);