2 assfile - library for accessing assets with an fopen/fread-like interface
3 Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 #define MAX_NAME_LEN 100
25 #define MAX_PREFIX_LEN 131
28 char name[MAX_NAME_LEN];
38 char uname[32], gname[32];
39 char devmajor[8], devminor[8];
40 char prefix[MAX_PREFIX_LEN];
41 char atime[12], ctime[12];
45 struct tar_entry file;
50 int load_tar(struct tar *tar, const char *fname)
53 struct node *node, *head = 0, *tail = 0;
56 unsigned long offset = 0, size, blksize;
59 if(!(tar->fp = fopen(fname, "rb"))) {
60 fprintf(stderr, "load_tar: failed to open %s: %s\n", fname, strerror(errno));
66 while(fread(buf, 1, sizeof buf, tar->fp) == sizeof buf) {
67 hdr = (struct header*)buf;
70 size = strtol(hdr->size, &endp, 8);
71 if(endp == hdr->size || size <= 0) {
72 continue; /* skip invalid */
74 blksize = ((size - 1) | 0x1ff) + 1; /* round to next 512-block */
76 /* verify filesize reasonable */
77 fseek(tar->fp, size - 1, SEEK_CUR);
78 if(fgetc(tar->fp) == -1) {
79 break; /* invalid and reached EOF */
81 fseek(tar->fp, blksize - size, SEEK_CUR);
83 if(memcmp(hdr->magic, "ustar", 5) == 0) {
84 int nlen = strnlen(hdr->name, MAX_NAME_LEN);
85 int plen = strnlen(hdr->prefix, MAX_PREFIX_LEN);
86 if(!(path = malloc(nlen + plen + 1))) {
87 perror("failed to allocate file path string");
90 memcpy(path, hdr->prefix, plen);
91 memcpy(path + plen, hdr->name, nlen);
92 path[nlen + plen] = 0;
94 int nlen = strnlen(hdr->name, MAX_NAME_LEN);
95 if(!(path = malloc(nlen + 1))) {
96 perror("failed to allocate file path string");
99 memcpy(path, hdr->name, nlen);
103 if(!(node = malloc(sizeof *node))) {
104 perror("failed to allocate file list node");
107 node->file.path = path;
108 node->file.offset = offset;
109 node->file.size = size;
119 /*printf(" %s - size %ld @%ld\n", node->file.path, node->file.size, node->file.offset);*/
124 if(!(tar->files = malloc(tar->num_files * sizeof *tar->files))) {
125 perror("failed to allocate file list");
130 for(i=0; i<tar->num_files; i++) {
131 tar->files[i] = node->file;
135 if(tar->num_files > 0) {
145 free(node->file.path);
154 void close_tar(struct tar *tar)
162 if(tar->files && tar->num_files > 0) {
164 for(i=0; i<tar->num_files; i++) {
165 free(tar->files[i].path);