-
Notifications
You must be signed in to change notification settings - Fork 24
/
cospkg.c
138 lines (106 loc) · 2.49 KB
/
cospkg.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright 2010 Sven Peter <[email protected]>
// Licensed under the terms of the GNU GPL, version 2
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
#include "tools.h"
#include "types.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#define MAX_FILES 255
struct pkg_file {
char name[0x20];
u8 *ptr;
u64 size;
u64 offset;
};
static u8 *hdr = NULL;
static u32 hdr_size = 0;
static u32 n_files = 0;
static struct pkg_file files[MAX_FILES];
static void get_files(const char *d)
{
DIR *dir;
struct dirent *de;
struct stat st;
char path[256];
u32 i;
u64 offset;
dir = opendir(d);
if (dir == NULL)
fail("opendir");
offset = 0;
i = 0;
while ((de = readdir(dir))) {
if (n_files == MAX_FILES)
fail("file overflow. increase MAX_FILES");
if (strcmp(de->d_name, ".") == 0)
continue;
if (strcmp(de->d_name, "..") == 0)
continue;
if (strlen(de->d_name) > 0x20)
fail("name too long: %s", de->d_name);
if (de->d_type != DT_REG)
fail("not a file: %s", de->d_name);
snprintf(path, sizeof path, "%s/%s", d, de->d_name);
memset(&files[i], 0, sizeof(*files));
strncpy(files[i].name, de->d_name, 0x19);
if (stat(path, &st) < 0)
fail("cannot stat %s", path);
files[i].size = st.st_size;
files[i].ptr = mmap_file(path);
if (files[i].ptr == NULL)
fail("unable to mmap %s", path);
files[i].offset = offset;
offset = round_up(offset + files[i].size, 0x20);
i++;
n_files++;
}
}
static void build_hdr(void)
{
u8 *p;
u32 i;
u64 file_size;
file_size = files[n_files - 1].offset + files[n_files - 1].size;
hdr_size = 0x10 + n_files * 0x30;
hdr = malloc(hdr_size);
if (hdr == NULL)
fail("out of memory");
memset(hdr, 0, hdr_size);
p = hdr;
wbe32(p + 0x00, 1); // magic
wbe32(p + 0x04, n_files);
wbe32(p + 0x08, hdr_size + file_size);
p += 0x10;
for (i = 0; i < n_files; i++) {
wbe64(p + 0x00, files[i].offset + hdr_size);
wbe64(p + 0x08, files[i].size);
strncpy((char *)(p + 0x10), files[i].name, 0x20);
p += 0x30;
}
}
static void write_pkg(const char *n)
{
FILE *fp;
u32 i;
fp = fopen(n, "wb");
if (fp == NULL)
fail("fopen(%s) failed", n);
fwrite(hdr, hdr_size, 1, fp);
for (i = 0; i < n_files; i++) {
fseek(fp, files[i].offset + hdr_size, SEEK_SET);
fwrite(files[i].ptr, files[i].size, 1, fp);
}
fclose(fp);
}
int main(int argc, char *argv[])
{
if (argc != 3)
fail("usage: cospkg cos.pkg dir");
get_files(argv[2]);
build_hdr();
write_pkg(argv[1]);
return 0;
}