Logo ROOT  
Reference Guide
Loading...
Searching...
No Matches
ReadFile.m
Go to the documentation of this file.
1/*
2 * ReadFile.m
3 * ROOTQL
4 *
5 * Created by Fons Rademakers on 22/05/09.
6 * Copyright 2009 CERN. All rights reserved.
7 *
8 */
9
10#include <stdio.h>
11#include <fcntl.h>
12#include <sys/types.h>
13#include <sys/uio.h>
14#include <unistd.h>
15#include <stdlib.h>
16#include <strings.h>
17#include <errno.h>
18
19#import <QuickLook/QuickLook.h>
20#import <Cocoa/Cocoa.h>
21
22
23#if defined(__i386__)
24# define R__BYTESWAP
25#endif
26#if defined(__x86_64__)
27# define R__BYTESWAP
28#endif
29
30
32 long long end;
33 long long seekFree;
34 long long seekInfo;
35 long long seekKeys;
37 int begin;
40 int dateC;
41 int timeC;
42 int dateM;
43 int timeM;
44 char units;
45 char *uuid;
46 char *title;
47 const char *name;
48};
49
50
51static void FromBufChar(char **buf, char *x)
52{
53 // Read a char from the buffer and advance the buffer.
54
55 *x = **buf;
56 *buf += 1;
57}
58
59static void FromBufShort(char **buf, short *x)
60{
61 // Read a short from the buffer and advance the buffer.
62
63#ifdef R__BYTESWAP
64 char *sw = (char *)x;
65 sw[0] = (*buf)[1];
66 sw[1] = (*buf)[0];
67#else
68 memcpy(x, *buf, sizeof(short));
69#endif
70 *buf += sizeof(short);
71}
72
73static void FromBufInt(char **buf, int *x)
74{
75 // Read an int from the buffer and advance the buffer.
76
77#ifdef R__BYTESWAP
78 char *sw = (char *)x;
79 sw[0] = (*buf)[3];
80 sw[1] = (*buf)[2];
81 sw[2] = (*buf)[1];
82 sw[3] = (*buf)[0];
83#else
84 memcpy(x, *buf, sizeof(int));
85#endif
86 *buf += sizeof(int);
87}
88
89static void FromBufLL(char **buf, long long *x)
90{
91 // Read a long long from the buffer and advance the buffer.
92
93#ifdef R__BYTESWAP
94 char *sw = (char *)x;
95 sw[0] = (*buf)[7];
96 sw[1] = (*buf)[6];
97 sw[2] = (*buf)[5];
98 sw[3] = (*buf)[4];
99 sw[4] = (*buf)[3];
100 sw[5] = (*buf)[2];
101 sw[6] = (*buf)[1];
102 sw[7] = (*buf)[0];
103#else
104 memcpy(x, *buf, sizeof(long long));
105#endif
106 *buf += sizeof(long long);
107}
108
109static void FromBufUUID(char **buf, char **uuid, int versiondir)
110{
111 // Read UUID from the buffer and return it as string in uuid.
112 // Returned string must be freed by the caller.
113 // We'll never come here if version < 2.
114
115 unsigned int timeLow;
116 unsigned short version, timeMid, timeHiAndVersion;
117 unsigned char clockSeqHiAndReserved, clockSeqLow, node[6];
118
119 if (versiondir > 2)
120 FromBufShort(buf, (short*)&version); //version
121 FromBufInt(buf, (int*)&timeLow);
122 FromBufShort(buf, (short*)&timeMid);
123 FromBufShort(buf, (short*)&timeHiAndVersion);
124 FromBufChar(buf, (char*)&clockSeqHiAndReserved);
125 FromBufChar(buf, (char*)&clockSeqLow);
126 int i;
127 for (i = 0; i < 6; i++)
128 FromBufChar(buf, (char*)&node[i]);
129
130 *uuid = malloc(40);
131 sprintf(*uuid, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
132 timeLow, timeMid, timeHiAndVersion, clockSeqHiAndReserved,
133 clockSeqLow, node[0], node[1], node[2], node[3], node[4],
134 node[5]);
135}
136
137static void FromBufStr(char **buf, char **str)
138{
139 // Read string from the buffer and return it as string in str.
140 // Returned string must be freed by the caller.
141
142 unsigned char nwh;
143 int nchars;
144
145 FromBufChar(buf, (char*)&nwh);
146 if (nwh == 255)
147 FromBufInt(buf, &nchars);
148 else
149 nchars = nwh;
150
151 int i;
152 *str = malloc(nchars+1);
153 for (i = 0; i < nchars; i++)
154 FromBufChar(buf, &(*str)[i]);
155 (*str)[nchars] = '\0';
156}
157
158static void GetDateAndTime(unsigned int datetime, int *date, int *time)
159{
160 // Function that returns the date and time. The input is
161 // in TDatime format (as obtained via TDatime::Get()).
162 // Date is returned in the format 950223 February 23 1995.
163 // Time is returned in the format 102459 10h 24m 59s.
164
165 unsigned int year = datetime>>26;
166 unsigned int month = (datetime<<6)>>28;
167 unsigned int day = (datetime<<10)>>27;
168 unsigned int hour = (datetime<<15)>>27;
169 unsigned int min = (datetime<<20)>>26;
170 unsigned int sec = (datetime<<26)>>26;
171 *date = 10000*(year+1995) + 100*month + day;
172 *time = 10000*hour + 100*min + sec;
173}
174
175static int ReadBuffer(int fd, char *buffer, int len)
176{
177 ssize_t siz;
178 while ((siz = read(fd, buffer, len)) < 0 && errno == EINTR)
179 errno = 0;
180 return (int)siz;
181}
182
183static int ReadHeader(int fd, struct FileHeader_t *fh, NSMutableString *html)
184{
185 // Read ROOT file header structure.
186 // Returns -1 in case of error, 0 otherwise.
187
188 const int len = 300;
189 char *header = malloc(len);
190
191 if (ReadBuffer(fd, header, len) != len) {
192 free(header);
193 return -1;
194 }
195
196 if (strncmp(header, "root", 4)) {
197 free(header);
198 return -1;
199 }
200
201 char *buffer = header + 4; // skip the "root" file identifier
202
203 FromBufInt(&buffer, &fh->version);
204 FromBufInt(&buffer, &fh->begin);
205
206 int dummy;
207 long long dummyll;
208
209 if (fh->version < 1000000) {
210 // < 2GB file
211 int seekfree, seekinfo;
212 FromBufInt(&buffer, &dummy); fh->end = (long long) dummy;
213 FromBufInt(&buffer, &seekfree); fh->seekFree = (long long) seekfree;
214 FromBufInt(&buffer, &dummy); // nbytes free
215 FromBufInt(&buffer, &dummy); // nfree
216 FromBufInt(&buffer, &fh->nbytesName);
217 FromBufChar(&buffer, &fh->units);
218 FromBufInt(&buffer, &fh->compress);
219 FromBufInt(&buffer, &seekinfo); fh->seekInfo = (long long) seekinfo;
220 FromBufInt(&buffer, &dummy); // nbytes info
221 } else {
222 // > 2GB file
223 FromBufLL(&buffer, &fh->end);
224 FromBufLL(&buffer, &fh->seekFree);
225 FromBufInt(&buffer, &dummy); // nbytes free
226 FromBufInt(&buffer, &dummy); // nfree
227 FromBufInt(&buffer, &fh->nbytesName);
228 FromBufChar(&buffer, &fh->units);
229 FromBufInt(&buffer, &fh->compress);
230 FromBufLL(&buffer, &fh->seekInfo);
231 FromBufInt(&buffer, &dummy); // nbytes info
232 }
233
234 int nk = sizeof(int)+sizeof(short)+2*sizeof(int)+2*sizeof(short)+2*sizeof(int);
235 int nbytes = fh->nbytesName + (22 + 2*sizeof(int) + 18); //nbytesName + TDirectoryFile::Sizeof();
236 if (fh->version >= 40000)
237 nbytes += 12;
238
239 if (nbytes + fh->begin > 300) {
240 free(header);
241 header = malloc(nbytes);
242 lseek(fd, (off_t)fh->begin, SEEK_SET);
243 if (ReadBuffer(fd, header, nbytes) != nbytes) {
244 free(header);
245 return -1;
246 }
247 buffer = header + fh->nbytesName;
248 } else {
249 buffer = header + fh->begin + fh->nbytesName;
250 nk += fh->begin;
251 }
252
253 short dversion, versiondir;
254 FromBufShort(&buffer, &dversion);
255 versiondir = dversion%1000;
256 FromBufInt(&buffer, &dummy);
257 GetDateAndTime((unsigned int)dummy, &fh->dateC, &fh->timeC);
258 FromBufInt(&buffer, &dummy);
259 GetDateAndTime((unsigned int)dummy, &fh->dateM, &fh->timeM);
260 FromBufInt(&buffer, &dummy); // nbytes keys
261 FromBufInt(&buffer, &dummy); // nbytes name
262 if (dversion > 1000) {
263 FromBufLL(&buffer, &dummyll); // seek dir
264 FromBufLL(&buffer, &dummyll); // seek parent
265 FromBufLL(&buffer, &fh->seekKeys);
266 } else {
267 int skeys;
268 FromBufInt(&buffer, &dummy); // seek dir
269 FromBufInt(&buffer, &dummy); // seek parent
270 FromBufInt(&buffer, &skeys); fh->seekKeys = (long long)skeys;
271 }
272 if (versiondir > 1)
273 FromBufUUID(&buffer, &fh->uuid, versiondir);
274 else
275 fh->uuid = strdup("-");
276
277 buffer = header + nk;
278 char *str;
279 FromBufStr(&buffer, &str); free(str); // "TFile"
280 FromBufStr(&buffer, &str); free(str); // orig filename
281 FromBufStr(&buffer, &fh->title);
282
283#ifdef DEBUG
284 NSLog(@"ReadHeader: %s, version = %d, begin = %d, end = %lld, units = %hhd, compress = %d",
285 fh->name, fh->version, fh->begin, fh->end, fh->units, fh->compress);
286#endif
287
288 [html appendFormat: @"<center><h3>%s</h3></center>\n", fh->name];
289 [html appendString: @"<center>Header Summary</center><p>\n"];
290 [html appendString: @"<table width=\"80%\" border=\"0\" cellpadding=\"2\" cellspacing=\"0\">\n"];
291 [html appendFormat: @"<tr><td>Title:</td><td><b>%s</b></td></tr>\n", fh->title];
292 [html appendFormat: @"<tr><td>Creation date:</td><td><b>%d/%d</b></td></tr>\n", fh->dateC, fh->timeC];
293 [html appendFormat: @"<tr><td>Modification date:</td><td><b>%d/%d</b></td></tr>\n", fh->dateM, fh->timeM];
294 [html appendFormat: @"<tr><td>File size (bytes):</td><td><b>%lld</b></td></tr>\n", fh->end];
295 [html appendFormat: @"<tr><td>Compression level:</td><td><b>%d</b></td></tr>\n", fh->compress];
296 [html appendFormat: @"<tr><td>UUID:</td><td><b>%s</b></td></tr>\n", fh->uuid];
297 [html appendFormat: @"<tr><td>File version:</td><td><b>%d</b></td></tr>\n", fh->version];
298 [html appendString: @"</table>\n"];
299
300 free(header);
301
302 return 0;
303}
304
305static int ReadKeys(int fd, struct FileHeader_t *fh, NSMutableString *html, QLPreviewRequestRef preview)
306{
307 // Loop over all keys and print information.
308 // Returns -1 in case of error, 0 otherwise.
309
310 int nbytes;
311 int objlen;
312 int date;
313 int time;
314 short keylen;
315 short cycle;
316 char *classname;
317 char *name;
318 char *title;
319
320 const int len = 256;
321 int nread, datime;
322 short versionkey;
323 char *header, *buffer;
324
325 NSDate *startDate = [NSDate date];
326
327 long long idcur = fh->begin;
328
329 [html appendString: @"<br>\n"];
330 [html appendString: @"<table width=\"100%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">\n"];
331 [html appendString: @"<tr>\n"];
332 [html appendString: @"<th colspan=\"7\">List of Keys</th>\n"];
333 [html appendString: @"</tr>\n"];
334 [html appendString: @"<tr>\n"];
335 [html appendString: @"<th>Name</th>\n"];
336 [html appendString: @"<th>Title</th>\n"];
337 [html appendString: @"<th>Class</th>\n"];
338 [html appendString: @"<th>Date</th>\n"];
339 [html appendString: @"<th>Offset</th>\n"];
340 [html appendString: @"<th>Size</th>\n"];
341 [html appendString: @"<th>CX</th>\n"];
342 [html appendString: @"</tr>\n"];
343
344 nread = len;
345 while (idcur < fh->end) {
346 again:
347 header = malloc(nread);
348 lseek(fd, (off_t)idcur, SEEK_SET);
349 if (idcur+nread > fh->end) nread = fh->end-idcur-1;
350 if (ReadBuffer(fd, header, nread) != nread) {
351 free(header);
352 return -1;
353 }
354 buffer = header;
355 FromBufInt(&buffer, &nbytes);
356 if (!nbytes) {
357 [html appendString: @"<tr>\n"];
358 [html appendString: @"<td colspan=\"7\" style=\"color:red\"><center><b>ERROR</b></center></td>\n"];
359 [html appendString: @"</tr>\n"];
360 free(header);
361 break;
362 }
363 if (nbytes < 0) {
364 [html appendString: @"<tr>\n"];
365 [html appendString: @"<td colspan=\"4\" style=\"color:red\"><center><b>GAP</b></center></td>\n"];
366 [html appendFormat: @"<td>%lld</td>\n", idcur];
367 [html appendFormat: @"<td>%d</td>\n", -nbytes];
368 [html appendFormat: @"<td>%5.2f</td>\n", 1.0];
369 [html appendString: @"<tr>\n"];
370 free(header);
371 idcur -= nbytes;
372 continue;
373 }
374
375 FromBufShort(&buffer, &versionkey);
376 FromBufInt(&buffer, &objlen);
377 FromBufInt(&buffer, &datime);
378 GetDateAndTime((unsigned int)datime, &date, &time);
379 FromBufShort(&buffer, &keylen);
380 FromBufShort(&buffer, &cycle);
381 if (versionkey > 1000) {
382 long long dummyll;
383 FromBufLL(&buffer, &dummyll); // seekkey
384 FromBufLL(&buffer, &dummyll); // seekpdir
385 } else {
386 int dummy;
387 FromBufInt(&buffer, &dummy); // seekkey
388 FromBufInt(&buffer, &dummy); // seekpdir
389 }
390 if (keylen > nread) {
391 free(header);
392 nread = keylen;
393 goto again;
394 }
395 FromBufStr(&buffer, &classname);
396 FromBufStr(&buffer, &name);
397 FromBufStr(&buffer, &title);
398 if (idcur == fh->seekFree) {
399 free(classname);
400 classname = strdup("FreeSegments");
401 name[0] = '\0';
402 title[0] = '\0';
403 }
404 if (idcur == fh->seekInfo) {
405 free(classname);
406 classname = strdup("StreamerInfo");
407 name[0] = '\0';
408 title[0] = '\0';
409 }
410 if (idcur == fh->seekKeys) {
411 free(classname);
412 classname = strdup("KeysList");
413 name[0] = '\0';
414 title[0] = '\0';
415 }
416 float cx;
417 if (objlen != nbytes-keylen)
418 cx = (float)(objlen+keylen)/(float)nbytes;
419 else
420 cx = 1.0;
421
422 [html appendString: @"<tr>\n"];
423 [html appendFormat: @"<td>%s</td>\n", name];
424 [html appendFormat: @"<td>%s</td>\n", title];
425 [html appendFormat: @"<td>%s</td>\n", classname];
426 [html appendFormat: @"<td>%d/%d</td>\n", date, time];
427 [html appendFormat: @"<td>%lld</td>\n", idcur];
428 [html appendFormat: @"<td>%d</td>\n", nbytes];
429 [html appendFormat: @"<td>%5.2f</td>\n", cx];
430 [html appendString: @"</tr>\n"];
431
432 free(classname);
433 free(name);
434 free(title);
435 free(header);
436
437 nread = len;
438
439 idcur += nbytes;
440
441 if ([startDate timeIntervalSinceNow] < -0.1) {
442 // Check for cancel once per second
443#ifdef DEBUG
444 NSLog(@"ReadKeys: checking for cancel %.3f", [startDate timeIntervalSinceNow]);
445#endif
446 if (QLPreviewRequestIsCancelled(preview)) {
447#ifdef DEBUG
448 NSLog(@"ReadKeys: cancelled");
449#endif
450 return -1;
451 }
452 startDate = [startDate dateByAddingTimeInterval: 0.1];
453 }
454 }
455
456 [html appendString: @"</table>\n"];
457
458 return 0;
459}
460
461int ReadFile(NSString *fullPath, NSMutableString *html, QLPreviewRequestRef preview)
462{
463 // Read ROOT file structure for specified file.
464 // Returns -1 in case of error, 0 otherwise.
465
466 struct FileHeader_t fh;
467 fh.name = [fullPath UTF8String];
468 int fd = open(fh.name, O_RDONLY, 0644);
469 if (fd == -1)
470 return -1;
471
472 if (ReadHeader(fd, &fh, html) == -1) {
473 close(fd);
474 return -1;
475 }
476
477 // Check for cancel
478 if (QLPreviewRequestIsCancelled(preview)) {
479 free(fh.uuid);
480 free(fh.title);
481 close(fd);
482 return -1;
483 }
484
485 if (ReadKeys(fd, &fh, html, preview) == -1) {
486 free(fh.uuid);
487 free(fh.title);
488 close(fd);
489 return -1;
490 }
491
492 free(fh.uuid);
493 free(fh.title);
494
495 close(fd);
496
497 return 0;
498}
char name[80]
Definition TGX11.cxx:148
#define SEEK_SET
Definition ZIP.h:47
#define free
Definition civetweb.c:1578
#define malloc
Definition civetweb.c:1575
subroutine node(ivo, nuserm, iposp)
Definition g2root.f:833
Double_t x[n]
Definition legend1.C:17
double read()
TPaveLabel title(3, 27.1, 15, 28.7,"ROOT Environment and Tools")
static void FromBufInt(char **buf, int *x)
Definition ReadFile.m:73
static void FromBufChar(char **buf, char *x)
Definition ReadFile.m:51
static void FromBufShort(char **buf, short *x)
Definition ReadFile.m:59
static void FromBufUUID(char **buf, char **uuid, int versiondir)
Definition ReadFile.m:109
static int ReadHeader(int fd, struct FileHeader_t *fh, NSMutableString *html)
Definition ReadFile.m:183
static void GetDateAndTime(unsigned int datetime, int *date, int *time)
Definition ReadFile.m:158
static void FromBufLL(char **buf, long long *x)
Definition ReadFile.m:89
static int ReadBuffer(int fd, char *buffer, int len)
Definition ReadFile.m:175
static void FromBufStr(char **buf, char **str)
Definition ReadFile.m:137
int ReadFile(NSString *fullPath, NSMutableSet *nameSet, NSMutableSet *titleSet)
Definition ReadFile.m:405
static int ReadKeys(int fd, struct FileHeader_t *fh, NSMutableSet *nameSet, NSMutableSet *titleSet)
Definition ReadFile.m:294
long long end
Definition ReadFile.m:32
long long seekFree
Definition ReadFile.m:33
char * uuid
Definition ReadFile.m:45
int nbytesName
Definition ReadFile.m:39
char * title
Definition ReadFile.m:46
long long seekInfo
Definition ReadFile.m:34
long long seekKeys
Definition ReadFile.m:35
const char * name
Definition ReadFile.m:47
Int_t year
Int_t month
Int_t day