ReadFile.m

Go to the documentation of this file.
00001 /*
00002  *  ReadFile.m
00003  *  ROOTSL
00004  *
00005  *  Created by Fons Rademakers on 22/05/09.
00006  *  Copyright 2009 CERN. All rights reserved.
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    // Read a char from the buffer and advance the buffer.
00053 
00054    *x = **buf;
00055    *buf += 1;
00056 }
00057 
00058 static void FromBufShort(char **buf, short *x)
00059 {
00060    // Read a short from the buffer and advance the buffer.
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    // Read an int from the buffer and advance the buffer.
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    // Read a long long from the buffer and advance the buffer.
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    // Read UUID from the buffer and return it as string in uuid.
00111    // Returned string must be freed by the caller.
00112    // We'll never come here if version < 2.
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);  //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    // Read string from the buffer and return it as string in str.
00139    // Returned string must be freed by the caller.
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    // Function that returns the date and time. The input is
00160    // in TDatime format (as obtained via TDatime::Get()).
00161    // Date is returned in the format 950223  February 23 1995.
00162    // Time is returned in the format 102459 10h 24m 59s.
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    // Read ROOT file header structure.
00185    // Returns -1 in case of error, 0 otherwise.
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;  // skip the "root" file identifier
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       // < 2GB file
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); // nbytes free
00214       FromBufInt(&buffer, &dummy); // nfree
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); // nbytes info
00220    } else {
00221       // > 2GB file
00222       FromBufLL(&buffer, &fh->end);
00223       FromBufLL(&buffer, &fh->seekFree);
00224       FromBufInt(&buffer, &dummy);  // nbytes free
00225       FromBufInt(&buffer, &dummy);  // nfree
00226       FromBufInt(&buffer, &fh->nbytesName);
00227       FromBufChar(&buffer, &fh->units);
00228       FromBufInt(&buffer, &fh->compress);
00229       FromBufLL(&buffer, &fh->seekInfo);
00230       FromBufInt(&buffer, &dummy);  // nbytes info
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);  //nbytesName + TDirectoryFile::Sizeof();
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);  // nbytes keys
00260    FromBufInt(&buffer, &dummy);  // nbytes name
00261    if (dversion > 1000) {
00262       FromBufLL(&buffer, &dummyll); // seek dir
00263       FromBufLL(&buffer, &dummyll); // seek parent
00264       FromBufLL(&buffer, &fh->seekKeys);
00265    } else {
00266       int skeys;
00267       FromBufInt(&buffer, &dummy); // seek dir
00268       FromBufInt(&buffer, &dummy); // seek parent
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);  // "TFile"
00279    FromBufStr(&buffer, &str); free(str); // orig filename
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    // Loop over all keys and print information.
00297    // Returns -1 in case of error, 0 otherwise.
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          // read error
00330          free(header);
00331          break;
00332       }
00333       if (nbytes < 0) {
00334          // a gap
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); // seekkey
00349          FromBufLL(&buffer, &dummyll); // seekpdir
00350       } else {
00351          int dummy;
00352          FromBufInt(&buffer, &dummy); // seekkey
00353          FromBufInt(&buffer, &dummy); // seekpdir
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    // Read ROOT file structure for specified file.
00408    // Returns -1 in case of error, 0 otherwise.
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 }

Generated on Tue Jul 5 14:44:01 2011 for ROOT_528-00b_version by  doxygen 1.5.1