00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011 #include <fcntl.h>
00012 #include <sys/types.h>
00013 #include <sys/uio.h>
00014 #include <unistd.h>
00015 #include <stdlib.h>
00016 #include <strings.h>
00017 #include <errno.h>
00018
00019 #import <Foundation/Foundation.h>
00020
00021
00022 #if defined(__i386__)
00023 # define R__BYTESWAP
00024 #endif
00025 #if defined(__x86_64__)
00026 # define R__BYTESWAP
00027 #endif
00028
00029
00030 struct FileHeader_t {
00031 long long end;
00032 long long seekFree;
00033 long long seekInfo;
00034 long long seekKeys;
00035 int version;
00036 int begin;
00037 int compress;
00038 int nbytesName;
00039 int dateC;
00040 int timeC;
00041 int dateM;
00042 int timeM;
00043 char units;
00044 char *uuid;
00045 char *title;
00046 const char *name;
00047 };
00048
00049
00050 static void FromBufChar(char **buf, char *x)
00051 {
00052
00053
00054 *x = **buf;
00055 *buf += 1;
00056 }
00057
00058 static void FromBufShort(char **buf, short *x)
00059 {
00060
00061
00062 #ifdef R__BYTESWAP
00063 char *sw = (char *)x;
00064 sw = (*buf);
00065 sw = (*buf);
00066 #else
00067 memcpy(x, *buf, sizeof(short));
00068 #endif
00069 *buf += sizeof(short);
00070 }
00071
00072 static void FromBufInt(char **buf, int *x)
00073 {
00074
00075
00076 #ifdef R__BYTESWAP
00077 char *sw = (char *)x;
00078 sw = (*buf);
00079 sw = (*buf);
00080 sw = (*buf);
00081 sw = (*buf);
00082 #else
00083 memcpy(x, *buf, sizeof(int));
00084 #endif
00085 *buf += sizeof(int);
00086 }
00087
00088 static void FromBufLL(char **buf, long long *x)
00089 {
00090
00091
00092 #ifdef R__BYTESWAP
00093 char *sw = (char *)x;
00094 sw = (*buf);
00095 sw = (*buf);
00096 sw = (*buf);
00097 sw = (*buf);
00098 sw = (*buf);
00099 sw = (*buf);
00100 sw = (*buf);
00101 sw = (*buf);
00102 #else
00103 memcpy(x, *buf, sizeof(long long));
00104 #endif
00105 *buf += sizeof(long long);
00106 }
00107
00108 static void FromBufUUID(char **buf, char **uuid, int versiondir)
00109 {
00110
00111
00112
00113
00114 unsigned int timeLow;
00115 unsigned short version, timeMid, timeHiAndVersion;
00116 unsigned char clockSeqHiAndReserved, clockSeqLow, node;
00117
00118 if (versiondir > 2)
00119 FromBufShort(buf, (short*)&version);
00120 FromBufInt(buf, (int*)&timeLow);
00121 FromBufShort(buf, (short*)&timeMid);
00122 FromBufShort(buf, (short*)&timeHiAndVersion);
00123 FromBufChar(buf, (char*)&clockSeqHiAndReserved);
00124 FromBufChar(buf, (char*)&clockSeqLow);
00125 int i;
00126 for (i = 0; i < 6; i++)
00127 FromBufChar(buf, (char*)&node[i]);
00128
00129 *uuid = malloc(40);
00130 sprintf(*uuid, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00131 timeLow, timeMid, timeHiAndVersion, clockSeqHiAndReserved,
00132 clockSeqLow, node[0], node[1], node[2], node[3], node[4],
00133 node[5]);
00134 }
00135
00136 static void FromBufStr(char **buf, char **str)
00137 {
00138
00139
00140
00141 unsigned char nwh;
00142 int nchars;
00143
00144 FromBufChar(buf, (char*)&nwh);
00145 if (nwh == 255)
00146 FromBufInt(buf, &nchars);
00147 else
00148 nchars = nwh;
00149
00150 int i;
00151 *str = malloc(nchars+1);
00152 for (i = 0; i < nchars; i++)
00153 FromBufChar(buf, &(*str)[i]);
00154 (*str) = '\0';
00155 }
00156
00157 static void GetDateAndTime(unsigned int datetime, int *date, int *time)
00158 {
00159
00160
00161
00162
00163
00164 unsigned int year = datetime>>26;
00165 unsigned int month = (datetime<<6)>>28;
00166 unsigned int day = (datetime<<10)>>27;
00167 unsigned int hour = (datetime<<15)>>27;
00168 unsigned int min = (datetime<<20)>>26;
00169 unsigned int sec = (datetime<<26)>>26;
00170 *date = 10000*(year+1995) + 100*month + day;
00171 *time = 10000*hour + 100*min + sec;
00172 }
00173
00174 static int ReadBuffer(int fd, char *buffer, int len)
00175 {
00176 ssize_t siz;
00177 while ((siz = read(fd, buffer, len)) < 0 && errno == EINTR)
00178 errno = 0;
00179 return (int)siz;
00180 }
00181
00182 static int ReadHeader(int fd, struct FileHeader_t *fh, NSMutableSet *titleSet)
00183 {
00184
00185
00186
00187 const int len = 300;
00188 char *header = malloc(len);
00189
00190 if (ReadBuffer(fd, header, len) != len) {
00191 free(header);
00192 return -1;
00193 }
00194
00195 if (strncmp(header, "root", 4)) {
00196 free(header);
00197 return -1;
00198 }
00199
00200 char *buffer = header + 4;
00201
00202 FromBufInt(&buffer, &fh->version);
00203 FromBufInt(&buffer, &fh->begin);
00204
00205 int dummy;
00206 long long dummyll;
00207
00208 if (fh->version < 1000000) {
00209
00210 int seekfree, seekinfo;
00211 FromBufInt(&buffer, &dummy); fh->end = (long long) dummy;
00212 FromBufInt(&buffer, &seekfree); fh->seekFree = (long long) seekfree;
00213 FromBufInt(&buffer, &dummy);
00214 FromBufInt(&buffer, &dummy);
00215 FromBufInt(&buffer, &fh->nbytesName);
00216 FromBufChar(&buffer, &fh->units);
00217 FromBufInt(&buffer, &fh->compress);
00218 FromBufInt(&buffer, &seekinfo); fh->seekInfo = (long long) seekinfo;
00219 FromBufInt(&buffer, &dummy);
00220 } else {
00221
00222 FromBufLL(&buffer, &fh->end);
00223 FromBufLL(&buffer, &fh->seekFree);
00224 FromBufInt(&buffer, &dummy);
00225 FromBufInt(&buffer, &dummy);
00226 FromBufInt(&buffer, &fh->nbytesName);
00227 FromBufChar(&buffer, &fh->units);
00228 FromBufInt(&buffer, &fh->compress);
00229 FromBufLL(&buffer, &fh->seekInfo);
00230 FromBufInt(&buffer, &dummy);
00231 }
00232
00233 int nk = sizeof(int)+sizeof(short)+2*sizeof(int)+2*sizeof(short)+2*sizeof(int);
00234 int nbytes = fh->nbytesName + (22 + 2*sizeof(int) + 18);
00235 if (fh->version >= 40000)
00236 nbytes += 12;
00237
00238 if (nbytes + fh->begin > 300) {
00239 free(header);
00240 header = malloc(nbytes);
00241 lseek(fd, (off_t)fh->begin, SEEK_SET);
00242 if (ReadBuffer(fd, header, nbytes) != nbytes) {
00243 free(header);
00244 return -1;
00245 }
00246 buffer = header + fh->nbytesName;
00247 } else {
00248 buffer = header + fh->begin + fh->nbytesName;
00249 nk += fh->begin;
00250 }
00251
00252 short dversion, versiondir;
00253 FromBufShort(&buffer, &dversion);
00254 versiondir = dversion%1000;
00255 FromBufInt(&buffer, &dummy);
00256 GetDateAndTime((unsigned int)dummy, &fh->dateC, &fh->timeC);
00257 FromBufInt(&buffer, &dummy);
00258 GetDateAndTime((unsigned int)dummy, &fh->dateM, &fh->timeM);
00259 FromBufInt(&buffer, &dummy);
00260 FromBufInt(&buffer, &dummy);
00261 if (dversion > 1000) {
00262 FromBufLL(&buffer, &dummyll);
00263 FromBufLL(&buffer, &dummyll);
00264 FromBufLL(&buffer, &fh->seekKeys);
00265 } else {
00266 int skeys;
00267 FromBufInt(&buffer, &dummy);
00268 FromBufInt(&buffer, &dummy);
00269 FromBufInt(&buffer, &skeys); fh->seekKeys = (long long)skeys;
00270 }
00271 if (versiondir > 1)
00272 FromBufUUID(&buffer, &fh->uuid, versiondir);
00273 else
00274 fh->uuid = strdup("-");
00275
00276 buffer = header + nk;
00277 char *str;
00278 FromBufStr(&buffer, &str); free(str);
00279 FromBufStr(&buffer, &str); free(str);
00280 FromBufStr(&buffer, &fh->title);
00281
00282 #ifdef DEBUG
00283 NSLog(@"%s: version = %d, begin = %d, end = %lld, units = %hhd, compress = %d",
00284 fh->name, fh->version, fh->begin, fh->end, fh->units, fh->compress);
00285 #endif
00286
00287 [titleSet addObject: [NSString stringWithUTF8String: fh->title]];
00288
00289 free(header);
00290
00291 return 0;
00292 }
00293
00294 static int ReadKeys(int fd, struct FileHeader_t *fh, NSMutableSet *nameSet, NSMutableSet *titleSet)
00295 {
00296
00297
00298
00299 int nbytes;
00300 int objlen;
00301 int date;
00302 int time;
00303 short keylen;
00304 short cycle;
00305 char *classname;
00306 char *name;
00307 char *title;
00308
00309 const int len = 256;
00310 int nread, datime;
00311 short versionkey;
00312 char *header, *buffer;
00313
00314 long long idcur = fh->begin;
00315
00316 nread = len;
00317 while (idcur < fh->end) {
00318 again:
00319 header = malloc(nread);
00320 lseek(fd, (off_t)idcur, SEEK_SET);
00321 if (idcur+nread > fh->end) nread = fh->end-idcur-1;
00322 if (ReadBuffer(fd, header, nread) != nread) {
00323 free(header);
00324 return -1;
00325 }
00326 buffer = header;
00327 FromBufInt(&buffer, &nbytes);
00328 if (!nbytes) {
00329
00330 free(header);
00331 break;
00332 }
00333 if (nbytes < 0) {
00334
00335 free(header);
00336 idcur -= nbytes;
00337 continue;
00338 }
00339
00340 FromBufShort(&buffer, &versionkey);
00341 FromBufInt(&buffer, &objlen);
00342 FromBufInt(&buffer, &datime);
00343 GetDateAndTime((unsigned int)datime, &date, &time);
00344 FromBufShort(&buffer, &keylen);
00345 FromBufShort(&buffer, &cycle);
00346 if (versionkey > 1000) {
00347 long long dummyll;
00348 FromBufLL(&buffer, &dummyll);
00349 FromBufLL(&buffer, &dummyll);
00350 } else {
00351 int dummy;
00352 FromBufInt(&buffer, &dummy);
00353 FromBufInt(&buffer, &dummy);
00354 }
00355 if (keylen > nread) {
00356 free(header);
00357 nread = keylen;
00358 goto again;
00359 }
00360 FromBufStr(&buffer, &classname);
00361 FromBufStr(&buffer, &name);
00362 FromBufStr(&buffer, &title);
00363 if (idcur == fh->seekFree) {
00364 free(classname);
00365 classname = strdup("FreeSegments");
00366 name = '\0';
00367 title = '\0';
00368 }
00369 if (idcur == fh->seekInfo) {
00370 free(classname);
00371 classname = strdup("StreamerInfo");
00372 name = '\0';
00373 title = '\0';
00374 }
00375 if (idcur == fh->seekKeys) {
00376 free(classname);
00377 classname = strdup("KeysList");
00378 name = '\0';
00379 title = '\0';
00380 }
00381 float cx;
00382 if (objlen != nbytes-keylen)
00383 cx = (float)(objlen+keylen)/(float)nbytes;
00384 else
00385 cx = 1.0;
00386
00387 if (strlen(name))
00388 [nameSet addObject: [NSString stringWithUTF8String: name]];
00389 if (strlen(title))
00390 [titleSet addObject: [NSString stringWithUTF8String: title]];
00391
00392 free(classname);
00393 free(name);
00394 free(title);
00395 free(header);
00396
00397 nread = len;
00398
00399 idcur += nbytes;
00400 }
00401
00402 return 0;
00403 }
00404
00405 int ReadFile(NSString *fullPath, NSMutableSet *nameSet, NSMutableSet *titleSet)
00406 {
00407
00408
00409
00410 struct FileHeader_t fh;
00411 fh.name = [fullPath UTF8String];
00412 int fd = open(fh.name, O_RDONLY, 0644);
00413 if (fd == -1)
00414 return -1;
00415
00416 if (ReadHeader(fd, &fh, titleSet) == -1) {
00417 close(fd);
00418 return -1;
00419 }
00420
00421 if (ReadKeys(fd, &fh, nameSet, titleSet) == -1) {
00422 free(fh.uuid);
00423 free(fh.title);
00424 close(fd);
00425 return -1;
00426 }
00427
00428 free(fh.uuid);
00429 free(fh.title);
00430
00431 close(fd);
00432
00433 return 0;
00434 }