51492079de7d485ad2e35549ed99336fdb22ff6d
[crow/jumpnbump.git] / modify / pack.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <fcntl.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <string.h>
7 #ifndef _MSC_VER
8 #include <getopt.h>
9 #include <unistd.h>
10 #else
11 #include <io.h>
12 typedef unsigned int u_int32_t;
13 #endif
14
15 typedef struct {
16         char filename[12];
17         u_int32_t offset;
18         u_int32_t size;
19 } DirEntry;
20
21 int main(int argc, char **argv)
22 {
23         int fd;
24         DirEntry *datafile;
25         int num_entries, i;
26         int c;
27         char *outfile = NULL;
28         int offset = 0;
29
30 #ifndef _MSC_VER
31         while ((c = getopt(argc, argv, "o:")) != EOF) {
32                 switch (c) {
33                 case 'o':
34                         if (optarg) {
35                                 outfile = strdup(optarg);
36                         }
37                         break;
38                 }
39         }
40         argc -= optind;
41         argv += optind;
42 #else
43         c = 1;
44         while (c<argc) {
45                 if (argv[c][0]=='-') {
46                         if (argv[c][1]=='o') {
47                                 if ( ((c+1)<argc) && (argv[c+1]) ) {
48                                         outfile = strdup(argv[c+1]);
49                                         c++;
50                                 }
51                                 c++;
52                                 break;
53                         }
54                 }
55                 c++;
56         }
57         argc -= c;
58         argv += c;
59 #endif
60
61         if (outfile == NULL) {
62                 printf("You must specify output filename with -o\n");
63                 exit(1);
64         }
65         if (argc == 0) {
66                 printf("You must specify some files to pack, duh\n");
67                 exit(1);
68         }
69         num_entries = argc;
70
71         /* prepare to pack things - get sizes and calculate offsets */
72         printf("%u files to pack\n", num_entries);
73         datafile = calloc(num_entries, sizeof(DirEntry));
74
75         /* skip past the directory structure */
76         offset = 4 + (num_entries * 20);
77
78         for (i = 0; i < num_entries; i++) {
79                 struct stat dummy;
80                 if (stat(argv[i], &dummy)) {
81                         fprintf(stderr, "%s is not accessible: ", argv[i]);
82                         perror("");
83                         exit(1);
84                 }
85                 if (strlen(argv[i]) > 12) {
86                         fprintf(stderr, "filename %s is longer than 12 chars\n", argv[i]);
87                         exit(1);
88                 }
89                 strncpy(datafile[i].filename, argv[i], 12);
90                 datafile[i].size = dummy.st_size;
91                 /* num_entries * (12 + 8) */
92                 datafile[i].offset = offset;
93                 offset += datafile[i].size;
94         }
95
96         /* here, we checked that all files are ok, and ready to roll the packfile */
97         fd = open(outfile, O_RDWR | O_CREAT | O_BINARY, 0644);
98         if (fd == -1) {
99                 perror("opening packfile");
100                 exit(1);
101         }
102         printf("Opened %s\n", outfile);
103
104         /* write number of entries in this data file */
105         write(fd, &num_entries, 4);
106
107         /* write the directory structure */
108         for (i = 0; i < num_entries; i++) {
109                 write(fd, &datafile[i], 20);
110         }
111
112         /* write in the actual files */
113         for (i = 0; i < num_entries; i++) {
114                 int infd;
115                 char *buf;
116
117                 printf("adding %s ", argv[i]);
118
119                 infd = open(argv[i], O_RDONLY | O_BINARY);
120                 if (infd == -1) {
121                         perror("opening file");
122                         exit(1);
123                 }
124                 buf = malloc(datafile[i].size + 16);
125                 read(infd, buf, datafile[i].size);
126                 close(infd);
127                 write(fd, buf, datafile[i].size);
128                 free(buf);
129                 printf(" OK\n");
130         }
131         close(fd);
132         return 0;
133 }