4 * Tennix Archive File Format
5 * Copyright (C) 2009-2010 Thomas Perl <thp@thpinfo.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
32 #include <sys/types.h>
35 #include <arpa/inet.h>
39 TennixArchive::TennixArchive(const char* filename
)
41 fp
= fopen(filename
, "rb");
44 offset
= sizeof(TennixArchiveHeader
)*fread(&(header
), sizeof(TennixArchiveHeader
), 1, fp
);
45 assert(offset
== sizeof(TennixArchiveHeader
));
46 assert(strncmp(header
.header
, TENNIX_ARCHIVE_HEADER
, TENNIX_ARCHIVE_HEADER_LEN
) == 0);
47 assert(header
.versionmajor
== TENNIX_ARCHIVE_VERSIONMAJOR
);
48 assert(header
.versionminor
== TENNIX_ARCHIVE_VERSIONMINOR
);
50 items
= (TennixArchiveItem
*)calloc(header
.items
, sizeof(TennixArchiveItem
));
51 assert(items
!= NULL
);
52 offset
+= sizeof(TennixArchiveItem
)*fread(items
, sizeof(TennixArchiveItem
), header
.items
, fp
);
53 assert(offset
== sizeof(TennixArchiveHeader
) + header
.items
*sizeof(TennixArchiveItem
));
55 xormem((char*)(items
), header
.items
*sizeof(TennixArchiveItem
), header
.key
);
57 for (int i
=0; i
<header
.items
; i
++) {
58 /* convert offset + length from network byte order */
59 items
[i
].offset
= ntohl(items
[i
].offset
);
60 items
[i
].length
= ntohl(items
[i
].length
);
73 fprintf(stderr
, "Tennix Archive\n");
74 fprintf(stderr
, "Header: %s\n", header
.header
);
75 fprintf(stderr
, "Version: %d.%d\n", header
.versionmajor
, header
.versionminor
);
76 fprintf(stderr
, "Master key: %d\n", header
.key
);
77 fprintf(stderr
, "Items: %d\n", header
.items
);
78 for (x
= 0; x
< header
.items
; x
++) {
79 fprintf(stderr
, "===========\n");
80 fprintf(stderr
, "File: %s (#%d)\n", items
[x
].filename
, x
);
81 fprintf(stderr
, "Size: %d\n", items
[x
].length
);
82 fprintf(stderr
, "Offset: %d\n", items
[x
].offset
);
83 fprintf(stderr
, "Key: %d\n", items
[x
].key
);
88 TennixArchive::setItemFilename(const char* filename
)
92 for (i
=0; i
<header
.items
; i
++) {
93 if (strncmp(items
[i
].filename
, filename
, TENNIX_ARCHIVE_ITEM_MAXNAME
) == 0) {
103 TennixArchive::getItemBytes()
105 size_t size
= getItemSize();
106 char* data
= (char*)malloc(size
+1);
107 /* the last char is a null character, so this works for strings, too */
109 fseek(fp
, items
[current_item
].offset
, SEEK_SET
);
110 assert(fread(data
, size
, 1, fp
) == 1);
111 xormem(data
, size
, items
[current_item
].key
);
116 TennixArchive::xormem(char* mem
, uint32_t length
, char key
)
118 char *i
= mem
, *end
= mem
+length
;
120 for(; i
!= end
; i
++) {
126 TennixArchive::appendItem(char* filename
, char* data
, uint32_t length
)
128 TennixArchiveItem
* item
;
131 items
= (TennixArchiveItem
*)realloc(items
, sizeof(TennixArchiveItem
)*header
.items
);
132 blobs
= (char**)realloc(blobs
, sizeof(char*)*header
.items
);
134 item
= &(items
[header
.items
-1]);
135 blobs
[header
.items
-1] = data
;
136 for (int i
=0; i
<TENNIX_ARCHIVE_ITEM_MAXNAME
; i
++) {
137 item
->filename
[i
] = data
[(i
*2)%length
];
139 strcpy(item
->filename
, filename
);
140 item
->length
= length
;
144 TennixArchive::buildFile(char* filename
)
147 size_t *memsize
= NULL
;
149 memsize
= (size_t*)calloc(header
.items
, sizeof(size_t));
151 fp
= fopen(filename
, "wb");
154 offset
+= sizeof(TennixArchiveHeader
) + header
.items
*sizeof(TennixArchiveItem
);
156 header
.versionmajor
= TENNIX_ARCHIVE_VERSIONMAJOR
;
157 header
.versionminor
= TENNIX_ARCHIVE_VERSIONMINOR
;
159 header
.key
= (0xaa + 0x77*header
.items
*3) % 0xff;
161 fprintf(stderr
, "Packing: ");
162 for (int i
=0; i
<header
.items
; i
++) {
163 fprintf(stderr
, "%s", items
[i
].filename
);
164 items
[i
].offset
= htonl(offset
); /* network byte order */
165 items
[i
].key
= 0xaa ^ ((i
<<2)%0x100);
166 xormem(blobs
[i
], items
[i
].length
, items
[i
].key
);
167 memsize
[i
] = items
[i
].length
;
168 offset
+= items
[i
].length
;
169 items
[i
].length
= htonl(items
[i
].length
); /* network byte order */
170 xormem((char*)(items
+ i
), sizeof(TennixArchiveItem
), header
.key
);
171 if (i
!= header
.items
-1) {
172 fprintf(stderr
, ", ");
177 fprintf(stderr
, "Writing: %s", filename
);
179 assert(fwrite(&(header
), sizeof(TennixArchiveHeader
), 1, fp
) == 1);
181 assert(fwrite(items
, sizeof(TennixArchiveItem
), header
.items
, fp
) == header
.items
);
183 for (int i
=0; i
<header
.items
; i
++) {
184 assert(fwrite(blobs
[i
], memsize
[i
], 1, fp
) == 1);
188 fprintf(stderr
, "OK\n");