1 /*-
2 ***********************************************************************
3 *
4 * $Id: decode.c,v 1.54 2014/07/18 06:40:44 mavrik Exp $
5 *
6 ***********************************************************************
7 *
8 * Copyright 2000-2014 The FTimes Project, All Rights Reserved.
9 *
10 ***********************************************************************
11 */
12 #include "all-includes.h"
13
14 /*-
15 ***********************************************************************
16 *
17 * Globals
18 *
19 ***********************************************************************
20 */
21 static unsigned char gaucBase64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
22 static int giFromBase64[256];
23
24 #ifdef WIN32
25 static char gacNewLine[NEWLINE_LENGTH] = CRLF;
26 #else
27 static char gacNewLine[NEWLINE_LENGTH] = LF;
28 #endif
29 static FILE *gpFile;
30
31 /*-
32 ***********************************************************************
33 *
34 * NOTE: The field order in this table must exactly match the order in
35 * gasCmpMaskTable (mask.c). Mask calculations rely on this.
36 *
37 ***********************************************************************
38 */
39 static DECODE_TABLE gasDecodeTable[] = {
40 { "z_name", "name", DecodeProcessName },
41 { "z_dev", "dev", DecodeProcessDevice },
42 { "z_inode", "inode", DecodeProcessInode },
43 { "z_volume", "volume", DecodeProcessVolume },
44 { "z_findex", "findex", DecodeProcessFileIndex },
45 { "z_mode", "mode", DecodeProcessMode },
46 { "z_attributes", "attributes", DecodeProcessAttributes },
47 { "z_nlink", "nlink", DecodeProcessLinkCount },
48 { "z_uid", "uid", DecodeProcessUserId },
49 { "z_gid", "gid", DecodeProcessGroupId },
50 { "z_rdev", "rdev", DecodeProcessRDevice },
51 { "z_atime", "atime", DecodeProcessATime },
52 { "z_ams", "ams", DecodeProcessATimeMs },
53 { "z_mtime", "mtime", DecodeProcessMTime },
54 { "z_mms", "mms", DecodeProcessMTimeMs },
55 { "z_ctime", "ctime", DecodeProcessCTime },
56 { "z_cms", "cms", DecodeProcessCTimeMs },
57 { "z_chtime", "chtime", DecodeProcessChTime },
58 { "z_chms", "chms", DecodeProcessChTimeMs },
59 { "z_size", "size", DecodeProcessSize },
60 { "z_altstreams", "altstreams", DecodeProcessAlternateDataStreams },
61 { "z_md5", "md5", DecodeProcessMd5 },
62 { "z_sha1", "sha1", DecodeProcessSha1 },
63 { "z_sha256", "sha256", DecodeProcessSha256 },
64 { "z_magic", "magic", DecodeProcessMagic },
65 { "z_osid", "osid", DecodeProcessNada },
66 { "z_gsid", "gsid", DecodeProcessNada },
67 { "z_dacl", "dacl", DecodeProcessNada },
68 };
69 #define DECODE_TABLE_SIZE sizeof(gasDecodeTable) / sizeof(gasDecodeTable[0])
70
71
72 /*-
73 ***********************************************************************
74 *
75 * Decode32BitHexToDecimal
76 *
77 ***********************************************************************
78 */
79 int
Decode32BitHexToDecimal(char * pcData,int iLength,APP_UI32 * pui32ValueNew,APP_UI32 * pui32ValueOld,char * pcError)80 Decode32BitHexToDecimal(char *pcData, int iLength, APP_UI32 *pui32ValueNew, APP_UI32 *pui32ValueOld, char *pcError)
81 {
82 const char acRoutine[] = "Decode32BitHexToDecimal()";
83 int i = 0;
84 int iSign = 0;
85 APP_UI32 ui32 = 0;
86
87 /*-
88 *********************************************************************
89 *
90 * Read hex number from pcData and store result in *pui32ValueNew.
91 * If hex number preceeded by +, then read hex number, add to
92 * pui32ValueOld and store result in *pui32ValueNew. If hex number
93 * preceeded by -, then read hex number, subtract from pui32ValueOld
94 * and store result in *pui32ValueNew. Hex number must be null
95 * terminated.
96 *
97 *********************************************************************
98 */
99 if (pui32ValueOld == NULL && (pcData[0] == '#' || pcData[0] == '+' || pcData[0] == '-'))
100 {
101 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
102 return ER;
103 }
104
105 if (pcData[0] == '#')
106 {
107 ui32 = *pui32ValueOld;
108 i++;
109 }
110 else
111 {
112 if (pcData[0] == '+')
113 {
114 iSign = 1;
115 i++;
116 }
117 else if (pcData[0] == '-')
118 {
119 iSign = (-1);
120 i++;
121 }
122
123 if (iLength <= 8)
124 {
125 while (i < iLength)
126 {
127 pcData[i] = tolower(pcData[i]);
128 if ((pcData[i] >= '0') && (pcData[i] <= '9'))
129 {
130 ui32 = (ui32 << 4) | (pcData[i] - '0');
131 }
132 else if ((pcData[i] >= 'a') && (pcData[i] <= 'f'))
133 {
134 ui32 = (ui32 << 4) | ((pcData[i] - 'a') + 10);
135 }
136 else
137 {
138 snprintf(pcError, MESSAGE_SIZE, "%s: Bad hex digit.", acRoutine);
139 return ER;
140 }
141 i++;
142 }
143 }
144 else
145 {
146 snprintf(pcError, MESSAGE_SIZE, "%s: Field length exceeds 8 digits!", acRoutine);
147 return ER;
148 }
149 if (iSign != 0)
150 {
151 ui32 = (*pui32ValueOld) + iSign * ui32;
152 }
153 }
154
155 *pui32ValueNew = ui32;
156
157 return ER_OK;
158 }
159
160
161 /*-
162 ***********************************************************************
163 *
164 * Decode64BitHexToDecimal
165 *
166 ***********************************************************************
167 */
168 int
Decode64BitHexToDecimal(char * pcData,int iLength,APP_UI64 * pui64ValueNew,APP_UI64 * pui64ValueOld,char * pcError)169 Decode64BitHexToDecimal(char *pcData, int iLength, APP_UI64 *pui64ValueNew, APP_UI64 *pui64ValueOld, char *pcError)
170 {
171 const char acRoutine[] = "Decode64BitHexToDecimal()";
172 char acLocalError[MESSAGE_SIZE] = "";
173 int i = 0;
174 int iError = 0;
175 APP_UI32 ui32UpperNew = 0;
176 APP_UI32 ui32LowerNew = 0;
177 APP_UI32 ui32LowerOld = 0;
178 APP_UI64 ui64 = 0;
179
180 if (pui64ValueOld == NULL && pcData[0] == '#')
181 {
182 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
183 return ER;
184 }
185
186 if (pcData[0] == '#')
187 {
188 ui32UpperNew = (APP_UI32) (*pui64ValueOld >> 32);
189 ui32LowerOld = (APP_UI32) (*pui64ValueOld & 0xffffff);
190 i++;
191 iLength--;
192 iError = Decode32BitHexToDecimal(&pcData[i], iLength, &ui32LowerNew, &ui32LowerOld, acLocalError);
193 if (iError == ER)
194 {
195 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
196 return ER;
197 }
198
199 *pui64ValueNew = (((APP_UI64) ui32UpperNew) << 32) | ui32LowerNew;
200 return ER_OK;
201 }
202
203 if (iLength <= 16)
204 {
205 while (i < iLength)
206 {
207 pcData[i] = tolower(pcData[i]);
208 if ((pcData[i] >= '0') && (pcData[i] <= '9'))
209 {
210 ui64 = (ui64 << 4) | (pcData[i] - '0');
211 }
212 else if ((pcData[i] >= 'a') && (pcData[i] <= 'f'))
213 {
214 ui64 = (ui64 << 4) | ((pcData[i] - 'a') + 10);
215 }
216 else
217 {
218 snprintf(pcError, MESSAGE_SIZE, "%s: Bad hex digit.", acRoutine);
219 return ER;
220 }
221 i++;
222 }
223 }
224 else
225 {
226 snprintf(pcError, MESSAGE_SIZE, "%s: Field length exceeds 16 digits!", acRoutine);
227 return ER;
228 }
229
230 *pui64ValueNew = ui64;
231
232 return ER_OK;
233 }
234
235
236 /*-
237 ***********************************************************************
238 *
239 * DecodeBuildFromBase64Table
240 *
241 ***********************************************************************
242 */
243 void
DecodeBuildFromBase64Table(void)244 DecodeBuildFromBase64Table(void)
245 {
246 int i = 0;
247
248 for (i = 0; i < 256; i++)
249 {
250 giFromBase64[i] = (-1);
251 }
252
253 for (i = 0; gaucBase64[i] != '\0'; i++)
254 {
255 giFromBase64[gaucBase64[i]] = i;
256 }
257 }
258
259
260 /*-
261 ***********************************************************************
262 *
263 * DecodeClearRecord
264 *
265 ***********************************************************************
266 */
267 void
DecodeClearRecord(DECODE_RECORD * psRecord,int iFieldCount)268 DecodeClearRecord(DECODE_RECORD *psRecord, int iFieldCount)
269 {
270 int i = 0;
271
272 psRecord->acLine[0] = 0;
273 psRecord->iLineLength = 0;
274 for (i = 0; i < iFieldCount; i++)
275 {
276 psRecord->ppcFields[i][0] = 0;
277 }
278 }
279
280
281 /*-
282 ***********************************************************************
283 *
284 * DecodeFormatOutOfBandTime
285 *
286 ***********************************************************************
287 */
288 int
DecodeFormatOutOfBandTime(char * pcToken,int iLength,char * pcOutput,char * pcError)289 DecodeFormatOutOfBandTime(char *pcToken, int iLength, char *pcOutput, char *pcError)
290 {
291 const char acRoutine[] = "DecodeFormatOutOfBandTime()";
292 int i = 0;
293 int n = 0;
294
295 /*-
296 *********************************************************************
297 *
298 * Input: YYYYMMDDHHMMSS --> Output: YYYY-MM-DD HH:MM:SS
299 *
300 *********************************************************************
301 */
302 if (iLength != (int) strlen("YYYYMMDDHHMMSS"))
303 {
304 snprintf(pcError, MESSAGE_SIZE, "%s: Field length != %d!", acRoutine, (int) strlen("YYYYMMDDHHMMSS"));
305 return ER;
306 }
307
308 for (i = n = 0; i < iLength; i++)
309 {
310 if (i == 4 || i == 6)
311 {
312 pcOutput[n++] = '-';
313 }
314 else if (i == 8)
315 {
316 pcOutput[n++] = ' ';
317 }
318 else if (i == 10 || i == 12)
319 {
320 pcOutput[n++] = ':';
321 }
322 pcOutput[n++] = pcToken[i];
323 }
324 pcOutput[n] = 0;
325
326 return n;
327 }
328
329
330 /*-
331 ***********************************************************************
332 *
333 * DecodeFormatTime
334 *
335 ***********************************************************************
336 */
337 int
DecodeFormatTime(APP_UI32 * pui32Time,char * pcTime)338 DecodeFormatTime(APP_UI32 *pui32Time, char *pcTime)
339 {
340 #ifdef WIN32
341 FILETIME sFileTime;
342 int iCount = 0;
343 APP_UI64 ui64Time = 0;
344 SYSTEMTIME sSystemTime;
345 #else
346 int iError = 0;
347 time_t tTime = (time_t) *pui32Time;
348 #endif
349
350 pcTime[0] = 0;
351
352 #ifdef WIN32
353 ui64Time = (((((APP_UI64) *pui32Time) * 1000)) * 10000) + UNIX_EPOCH_IN_NT_TIME;
354 sFileTime.dwLowDateTime = (APP_UI32) (ui64Time & (APP_UI32) 0xffffffff);
355 sFileTime.dwHighDateTime = (DWORD) (ui64Time >> 32);
356 if (!FileTimeToSystemTime(&sFileTime, &sSystemTime))
357 {
358 /* FIXME Return an error message. */
359 return ER;
360 }
361 iCount = snprintf(
362 pcTime,
363 DECODE_TIME_FORMAT_SIZE,
364 DECODE_TIME_FORMAT,
365 sSystemTime.wYear,
366 sSystemTime.wMonth,
367 sSystemTime.wDay,
368 sSystemTime.wHour,
369 sSystemTime.wMinute,
370 sSystemTime.wSecond
371 );
372 if (iCount != DECODE_TIME_FORMAT_SIZE - 1)
373 {
374 /* FIXME Return an error message. */
375 return ER;
376 }
377 #else
378 iError = TimeFormatTime(&tTime, pcTime);
379 if (iError == ER)
380 {
381 /* FIXME Return an error message. */
382 return ER;
383 }
384 #endif
385
386 return ER_OK;
387 }
388
389
390 /*-
391 ***********************************************************************
392 *
393 * DecodeFreeSnapshotContext
394 *
395 ***********************************************************************
396 */
397 void
DecodeFreeSnapshotContext(SNAPSHOT_CONTEXT * psSnapshot)398 DecodeFreeSnapshotContext(SNAPSHOT_CONTEXT *psSnapshot)
399 {
400 int i = 0;
401 int j = 0;
402
403 if (psSnapshot != NULL)
404 {
405 if (psSnapshot->psDecodeMap != NULL)
406 {
407 free(psSnapshot->psDecodeMap);
408 }
409 for (i = 0; i < DECODE_RECORD_COUNT; i++)
410 {
411 if (psSnapshot->asRecords[i].ppcFields != NULL)
412 {
413 for (j = 0; j < psSnapshot->iFieldCount; j++)
414 {
415 if (psSnapshot->asRecords[i].ppcFields[j] != NULL)
416 {
417 free(psSnapshot->asRecords[i].ppcFields[j]);
418 }
419 }
420 free(psSnapshot->asRecords[i].ppcFields);
421 }
422 }
423 free(psSnapshot);
424 }
425 }
426
427
428 /*-
429 ***********************************************************************
430 *
431 * DecodeGetBase64Hash
432 *
433 ***********************************************************************
434 */
435 int
DecodeGetBase64Hash(char * pcData,unsigned char * pucHash,int iLength,char * pcError)436 DecodeGetBase64Hash(char *pcData, unsigned char *pucHash, int iLength, char *pcError)
437 {
438 const char acRoutine[] = "DecodeGetBase64Hash()";
439 int i = 0;
440 int j = 0;
441 int iLeft = 0;
442 APP_UI32 ui32 = 0;
443
444 for (i = j = iLeft = 0, ui32 = 0; i < iLength; i++)
445 {
446 if (giFromBase64[(int) pcData[i]] < 0)
447 {
448 snprintf(pcError, MESSAGE_SIZE, "%s: Illegal base64 character", acRoutine);
449 return ER;
450 }
451 ui32 = (ui32 << 6) | giFromBase64[(int) pcData[i]];
452 iLeft += 6;
453 while (iLeft >= 8)
454 {
455 pucHash[j++] = (unsigned char) ((ui32 >> (iLeft - 8)) & 0xff);
456 iLeft -= 8;
457 }
458 }
459
460 return i;
461 }
462
463
464 /*-
465 ***********************************************************************
466 *
467 * DecodeGetTableLength
468 *
469 ***********************************************************************
470 */
471 int
DecodeGetTableLength(void)472 DecodeGetTableLength(void)
473 {
474 return DECODE_TABLE_SIZE;
475 }
476
477
478 /*-
479 ***********************************************************************
480 *
481 * DecodeNewSnapshotContext
482 *
483 ***********************************************************************
484 */
485 SNAPSHOT_CONTEXT *
DecodeNewSnapshotContext(char * pcError)486 DecodeNewSnapshotContext(char *pcError)
487 {
488 const char acRoutine[] = "DecodeNewSnapshotContext()";
489 SNAPSHOT_CONTEXT *psSnapshot = NULL;
490 int i = 0;
491 int j = 0;
492
493 psSnapshot = (SNAPSHOT_CONTEXT *) calloc(sizeof(SNAPSHOT_CONTEXT), 1);
494 if (psSnapshot == NULL)
495 {
496 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
497 return NULL;
498 }
499
500 psSnapshot->psDecodeMap = (DECODE_TABLE *) calloc(sizeof(DECODE_TABLE), DECODE_TABLE_SIZE);
501 if (psSnapshot->psDecodeMap == NULL)
502 {
503 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
504 DecodeFreeSnapshotContext(psSnapshot);
505 return NULL;
506 }
507
508 for (i = 0; i < DECODE_RECORD_COUNT; i++)
509 {
510 psSnapshot->asRecords[i].ppcFields = (char **) calloc(DECODE_TABLE_SIZE, sizeof(char **));
511 if (psSnapshot->asRecords[i].ppcFields == NULL)
512 {
513 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
514 DecodeFreeSnapshotContext(psSnapshot);
515 return NULL;
516 }
517
518 for (j = 0; j < DECODE_TABLE_SIZE; j++)
519 {
520 psSnapshot->asRecords[i].ppcFields[j] = (char *) calloc(DECODE_MAX_LINE, 1);
521 if (psSnapshot->asRecords[i].ppcFields[j] == NULL)
522 {
523 snprintf(pcError, MESSAGE_SIZE, "%s: calloc(): %s", acRoutine, strerror(errno));
524 DecodeFreeSnapshotContext(psSnapshot);
525 return NULL;
526 }
527 }
528 }
529
530 return psSnapshot;
531 }
532
533
534 /*-
535 ***********************************************************************
536 *
537 * DecodeOpenSnapshot
538 *
539 ***********************************************************************
540 */
541 int
DecodeOpenSnapshot(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)542 DecodeOpenSnapshot(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
543 {
544 const char acRoutine[] = "DecodeOpenSnapshot()";
545 char acLocalError[MESSAGE_SIZE] = "";
546 int iError = 0;
547
548 psSnapshot->pFile = SupportGetFileHandle(psSnapshot->pcFile, acLocalError);
549 if (psSnapshot->pFile == NULL)
550 {
551 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s], Line = [%d]: %s", acRoutine, psSnapshot->pcFile, psSnapshot->iLineNumber, acLocalError);
552 return ER;
553 }
554
555 if (DecodeReadLine(psSnapshot, acLocalError) == NULL && ferror(psSnapshot->pFile))
556 {
557 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s], Line = [%d]: %s", acRoutine, psSnapshot->pcFile, psSnapshot->iLineNumber, acLocalError);
558 fclose(psSnapshot->pFile);
559 return ER;
560 }
561
562 iError = DecodeParseHeader(psSnapshot, acLocalError);
563 if (iError != ER_OK)
564 {
565 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s], Line = [%d]: %s", acRoutine, psSnapshot->pcFile, psSnapshot->iLineNumber, acLocalError);
566 fclose(psSnapshot->pFile);
567 return ER;
568 }
569
570 return ER_OK;
571 }
572
573
574 /*-
575 ***********************************************************************
576 *
577 * DecodeParseHeader
578 *
579 ***********************************************************************
580 */
581 int
DecodeParseHeader(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)582 DecodeParseHeader(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
583 {
584 const char acRoutine[] = "DecodeParseHeader()";
585 char acLegacyName[DECODE_FIELDNAME_SIZE] = { 0 };
586 char *pc = NULL;
587 int i = 0;
588 int iIndex = 0;
589
590 /*-
591 *********************************************************************
592 *
593 * First, check to see that there's at least a name field.
594 *
595 *********************************************************************
596 */
597 if (strcmp(psSnapshot->psCurrRecord->acLine, "name") == 0 || strncmp(psSnapshot->psCurrRecord->acLine, "name|", 5) == 0)
598 {
599 psSnapshot->iCompressed = 0;
600 psSnapshot->iLegacyFile = 0;
601 }
602 else if (strcmp(psSnapshot->psCurrRecord->acLine, "z_name") == 0 || strncmp(psSnapshot->psCurrRecord->acLine, "z_name|", 7) == 0)
603 {
604 psSnapshot->iCompressed = 1;
605 psSnapshot->iLegacyFile = 0;
606 }
607 else if (strcmp(psSnapshot->psCurrRecord->acLine, "zname") == 0 || strncmp(psSnapshot->psCurrRecord->acLine, "zname|", 6) == 0)
608 {
609 psSnapshot->iCompressed = 1;
610 psSnapshot->iLegacyFile = 1;
611 }
612 else
613 {
614 snprintf(pcError, MESSAGE_SIZE, "%s: Header magic is not recognized.", acRoutine);
615 return ER;
616 }
617
618 /*-
619 *********************************************************************
620 *
621 * Then, parse the header, and construct a decode table.
622 *
623 *********************************************************************
624 */
625 for (iIndex = 0, pc = strtok(psSnapshot->psCurrRecord->acLine, DECODE_SEPARATOR_S); pc != NULL; pc = strtok(NULL, DECODE_SEPARATOR_S), iIndex++)
626 {
627 for (i = 0; i < DECODE_TABLE_SIZE; i++)
628 {
629 if (psSnapshot->iCompressed)
630 {
631 if (strcmp(gasDecodeTable[i].acZName, pc) == 0)
632 {
633 psSnapshot->aiIndex2Map[iIndex] = i;
634 psSnapshot->psDecodeMap[i] = gasDecodeTable[i]; /* This initializes all elements at the given index. */
635 PUTBIT(psSnapshot->ulFieldMask, 1, i);
636 break;
637 }
638 if (psSnapshot->iLegacyFile)
639 {
640 snprintf(acLegacyName, DECODE_FIELDNAME_SIZE - 1, "z_%s", pc);
641 acLegacyName[DECODE_FIELDNAME_SIZE - 1] = 0;
642 if (strcmp(gasDecodeTable[i].acZName, acLegacyName) == 0 || strcmp("zname", pc) == 0)
643 {
644 psSnapshot->aiIndex2Map[iIndex] = i;
645 psSnapshot->psDecodeMap[i] = gasDecodeTable[i]; /* This initializes all elements at the given index. */
646 PUTBIT(psSnapshot->ulFieldMask, 1, i);
647 break;
648 }
649 }
650 }
651 else
652 {
653 if (strcmp(gasDecodeTable[i].acUName, pc) == 0)
654 {
655 psSnapshot->aiIndex2Map[iIndex] = i;
656 psSnapshot->psDecodeMap[i] = gasDecodeTable[i]; /* This initializes all elements at the given index. */
657 psSnapshot->psDecodeMap[i].piRoutine = DecodeProcessNada; /* Override the normal decode routine. */
658 PUTBIT(psSnapshot->ulFieldMask, 1, i);
659 break;
660 }
661 }
662 }
663 if (i == DECODE_TABLE_SIZE)
664 {
665 snprintf(pcError, MESSAGE_SIZE, "%s: Field = [%s]: Unrecognized field.", acRoutine, pc);
666 return ER;
667 }
668 }
669
670 /*-
671 *********************************************************************
672 *
673 * Finally, record the last field index -- it's used to represent the
674 * length of the decode table.
675 *
676 *********************************************************************
677 */
678 psSnapshot->iFieldCount = iIndex;
679
680 return ER_OK;
681 }
682
683
684 /*-
685 ***********************************************************************
686 *
687 * DecodeParseRecord
688 *
689 ***********************************************************************
690 */
691 int
DecodeParseRecord(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)692 DecodeParseRecord(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
693 {
694 char acLocalError[MESSAGE_SIZE] = "";
695 char acName[DECODE_MAX_LINE] = { 0 };
696 char *pcName = NULL;
697 char *pcToken = NULL;
698 int i = 0;
699 int iDone = 0;
700 int iError = 0;
701 int iLength = 0;
702 int iOffset = 0;
703 int iFieldCount = 1;
704 int iFieldIndex = 0;
705
706 /*-
707 *********************************************************************
708 *
709 * Scan the line -- stopping at each delimiter to decode the field.
710 *
711 *********************************************************************
712 */
713 pcToken = psSnapshot->psCurrRecord->acLine;
714 while (!iDone)
715 {
716 if (psSnapshot->psCurrRecord->acLine[iOffset] == DECODE_SEPARATOR_C || psSnapshot->psCurrRecord->acLine[iOffset] == 0)
717 {
718 if (iFieldCount > psSnapshot->iFieldCount)
719 {
720 snprintf(pcError, MESSAGE_SIZE, "File = [%s], Line = [%d], FieldCount = [%d] > [%d]: FieldCount exceeds expected value.",
721 psSnapshot->pcFile,
722 psSnapshot->iLineNumber,
723 iFieldCount,
724 psSnapshot->iFieldCount
725 );
726 ErrorHandler(ER_Failure, pcError, ERROR_FAILURE);
727 return ER;
728 }
729 if (psSnapshot->psCurrRecord->acLine[iOffset] == 0)
730 {
731 iDone = 1;
732 }
733 psSnapshot->psCurrRecord->acLine[iOffset] = 0; /* Terminate the field value. */
734 iError = psSnapshot->psDecodeMap[psSnapshot->aiIndex2Map[iFieldIndex]].piRoutine(
735 &psSnapshot->sDecodeState,
736 pcToken,
737 iLength,
738 psSnapshot->psCurrRecord->ppcFields[psSnapshot->aiIndex2Map[iFieldIndex]],
739 acLocalError
740 );
741 if (iError == ER)
742 {
743 snprintf(pcError, MESSAGE_SIZE, "File = [%s], Line = [%d], Field = [%s]: %s",
744 psSnapshot->pcFile,
745 psSnapshot->iLineNumber,
746 (psSnapshot->iCompressed) ? psSnapshot->psDecodeMap[psSnapshot->aiIndex2Map[iFieldIndex]].acZName : psSnapshot->psDecodeMap[psSnapshot->aiIndex2Map[iFieldIndex]].acUName,
747 acLocalError
748 );
749 ErrorHandler(ER_Failure, pcError, ERROR_FAILURE);
750 return ER;
751 }
752 if (!iDone)
753 {
754 iOffset++;
755 iFieldCount++;
756 iFieldIndex++;
757 pcToken = &psSnapshot->psCurrRecord->acLine[iOffset];
758 iLength = 0;
759 }
760 }
761 else
762 {
763 iOffset++;
764 iLength++;
765 }
766 }
767 if (iFieldCount != psSnapshot->iFieldCount)
768 {
769 snprintf(pcError, MESSAGE_SIZE, "File = [%s], Line = [%d], FieldCount = [%d] != [%d]: FieldCount mismatch!",
770 psSnapshot->pcFile,
771 psSnapshot->iLineNumber,
772 iFieldCount,
773 psSnapshot->iFieldCount
774 );
775 ErrorHandler(ER_Failure, pcError, ERROR_FAILURE);
776 return ER;
777 }
778
779 /*-
780 *********************************************************************
781 *
782 * Compute the MD5 hash of the name field. If the user has declared
783 * names to be case insensitive or the name begins with a WINX drive
784 * specification, convert it to lower case before computing its
785 * hash. Note that WINX-based names are not case sensitive. Usually,
786 * the original case is preserved at file creation, but there is no
787 * guarantee that the case for a given file will be the same from
788 * snapshot to snapshot. Therefore, WINX-based names must always be
789 * converted to lower case before computing their hash.
790 *
791 *********************************************************************
792 */
793 pcName = psSnapshot->psCurrRecord->ppcFields[0];
794 iLength = strlen(pcName);
795 if (psSnapshot->iNamesAreCaseInsensitive || (isalpha((int) pcName[1]) && pcName[2] == ':'))
796 {
797 snprintf(acName, DECODE_MAX_LINE, "%s", pcName);
798 for (i = 0; i < iLength; i++)
799 {
800 acName[i] = tolower((int) acName[i]);
801 }
802 pcName = acName;
803 }
804 MD5HashString((unsigned char *) pcName, iLength, psSnapshot->psCurrRecord->aucHash);
805
806 return ER_OK;
807 }
808
809
810 /*-
811 ***********************************************************************
812 *
813 * DecodeProcessATime
814 *
815 ***********************************************************************
816 */
817 int
DecodeProcessATime(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)818 DecodeProcessATime(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
819 {
820 const char acRoutine[] = "DecodeProcessATime()";
821 char acLocalError[MESSAGE_SIZE] = "";
822 char acTimeString[DECODE_TIME_FORMAT_SIZE] = { 0 };
823 int iError = 0;
824 APP_UI32 ui32Value = 0;
825
826 if (iLength <= 0)
827 {
828 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->atime, psDecodeState->patime);
829 pcOutput[0] = 0;
830 return ER_OK; /* It's not an error if a value is missing. */
831 }
832
833 if (pcToken[0] == '~')
834 {
835 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->atime, psDecodeState->patime);
836 iError = DecodeFormatOutOfBandTime(&pcToken[1], iLength - 1, acTimeString, acLocalError);
837 if (iError == ER)
838 {
839 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
840 return ER;
841 }
842 snprintf(pcOutput, DECODE_TIME_FORMAT_SIZE, "%s", acTimeString);
843 return ER_OK;
844 }
845
846 switch (pcToken[0])
847 {
848 case '#':
849 if (psDecodeState->patime != NULL)
850 {
851 ui32Value = *psDecodeState->patime;
852 }
853 else
854 {
855 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
856 return ER;
857 }
858 break;
859 default:
860 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->patime, acLocalError);
861 if (iError == ER)
862 {
863 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
864 return ER;
865 }
866 break;
867 }
868
869 iError = DecodeFormatTime(&ui32Value, pcOutput);
870 if (iError == ER)
871 {
872 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
873 return ER;
874 }
875
876 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->atime, psDecodeState->patime, ui32Value);
877
878 return ER_OK;
879 }
880
881
882 /*-
883 ***********************************************************************
884 *
885 * DecodeProcessATimeMs
886 *
887 ***********************************************************************
888 */
889 int
DecodeProcessATimeMs(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)890 DecodeProcessATimeMs(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
891 {
892 const char acRoutine[] = "DecodeProcessATimeMs()";
893 char acLocalError[MESSAGE_SIZE] = "";
894 int iError = 0;
895 APP_UI32 ui32Value = 0;
896
897 if (iLength <= 0)
898 {
899 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
900 pcOutput[0] = 0;
901 return ER_OK; /* It's not an error if a value is missing. */
902 }
903
904 switch (pcToken[0])
905 {
906 case '#':
907 if (psDecodeState->pams != NULL)
908 {
909 ui32Value = *psDecodeState->pams;
910 }
911 else
912 {
913 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
914 return ER;
915 }
916 break;
917 default:
918 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pams, acLocalError);
919 if (iError == ER)
920 {
921 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
922 return ER;
923 }
924 break;
925 }
926
927 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
928
929 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->ams, psDecodeState->pams, ui32Value);
930
931 return ER_OK;
932 }
933
934
935 /*-
936 ***********************************************************************
937 *
938 * DecodeProcessAlternateDataStreams
939 *
940 ***********************************************************************
941 */
942 int
DecodeProcessAlternateDataStreams(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)943 DecodeProcessAlternateDataStreams(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
944 {
945 const char acRoutine[] = "DecodeProcessAlternateDataStreams()";
946 char acLocalError[MESSAGE_SIZE] = "";
947 int iError = 0;
948 APP_UI32 ui32Value = 0;
949
950 if (iLength <= 0)
951 {
952 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->altstreams, psDecodeState->paltstreams);
953 pcOutput[0] = 0;
954 return ER_OK; /* It's not an error if a value is missing. */
955 }
956
957 /*-
958 *********************************************************************
959 *
960 * If the decode routine returns an error, clear the previous value
961 * and NULLify its pointer. A NULL pointer signifies that the value
962 * is undefined (and, therefore, not to be used). If the decode
963 * routine returns success, record the decoded value in the output
964 * buffer, save it as the new previous value, and update its pointer
965 * as it may have been NULLified in a previous round.
966 *
967 *********************************************************************
968 */
969 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->paltstreams, acLocalError);
970 if (iError == ER)
971 {
972 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->altstreams, psDecodeState->paltstreams);
973 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
974 return iError;
975 }
976 else
977 {
978 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->altstreams, psDecodeState->paltstreams, ui32Value);
979 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
980 }
981
982 return ER_OK;
983 }
984
985
986 /*-
987 ***********************************************************************
988 *
989 * DecodeProcessAttributes
990 *
991 ***********************************************************************
992 */
993 int
DecodeProcessAttributes(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)994 DecodeProcessAttributes(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
995 {
996 const char acRoutine[] = "DecodeProcessAttributes()";
997 char acLocalError[MESSAGE_SIZE] = "";
998 int iError = 0;
999 APP_UI32 ui32Value = 0;
1000
1001 if (iLength <= 0)
1002 {
1003 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->attributes, psDecodeState->pattributes);
1004 pcOutput[0] = 0;
1005 return ER_OK; /* It's not an error if a value is missing. */
1006 }
1007
1008 /*-
1009 *********************************************************************
1010 *
1011 * If the decode routine returns an error, clear the previous value
1012 * and NULLify its pointer. A NULL pointer signifies that the value
1013 * is undefined (and, therefore, not to be used). If the decode
1014 * routine returns success, record the decoded value in the output
1015 * buffer, save it as the new previous value, and update its pointer
1016 * as it may have been NULLified in a previous round.
1017 *
1018 *********************************************************************
1019 */
1020 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pattributes, acLocalError);
1021 if (iError == ER)
1022 {
1023 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->attributes, psDecodeState->pattributes);
1024 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1025 return iError;
1026 }
1027 else
1028 {
1029 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->attributes, psDecodeState->pattributes, ui32Value);
1030 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1031 }
1032
1033 return ER_OK;
1034 }
1035
1036
1037 /*-
1038 ***********************************************************************
1039 *
1040 * DecodeProcessCTime
1041 *
1042 ***********************************************************************
1043 */
1044 int
DecodeProcessCTime(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1045 DecodeProcessCTime(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1046 {
1047 const char acRoutine[] = "DecodeProcessCTime()";
1048 char acLocalError[MESSAGE_SIZE] = "";
1049 char acTimeString[DECODE_TIME_FORMAT_SIZE] = { 0 };
1050 int iError = 0;
1051 APP_UI32 ui32Value = 0;
1052
1053 if (iLength <= 0)
1054 {
1055 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->ctime, psDecodeState->pctime);
1056 pcOutput[0] = 0;
1057 return ER_OK; /* It's not an error if a value is missing. */
1058 }
1059
1060 if (pcToken[0] == '~')
1061 {
1062 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->ctime, psDecodeState->pctime);
1063 iError = DecodeFormatOutOfBandTime(&pcToken[1], iLength - 1, acTimeString, acLocalError);
1064 if (iError == ER)
1065 {
1066 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1067 return ER;
1068 }
1069 snprintf(pcOutput, DECODE_TIME_FORMAT_SIZE, "%s", acTimeString);
1070 return ER_OK;
1071 }
1072
1073 switch (pcToken[0])
1074 {
1075 case '#':
1076 if (psDecodeState->pctime != NULL)
1077 {
1078 ui32Value = *psDecodeState->pctime;
1079 }
1080 else
1081 {
1082 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1083 return ER;
1084 }
1085 break;
1086 case 'X':
1087 if (psDecodeState->patime != NULL)
1088 {
1089 ui32Value = *psDecodeState->patime;
1090 }
1091 else
1092 {
1093 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current atime value to be defined!", acRoutine);
1094 return ER;
1095 }
1096 break;
1097 case 'Y':
1098 if (psDecodeState->pmtime != NULL)
1099 {
1100 ui32Value = *psDecodeState->pmtime;
1101 }
1102 else
1103 {
1104 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current mtime value to be defined!", acRoutine);
1105 return ER;
1106 }
1107 break;
1108 case 'Z':
1109 if (psDecodeState->pctime != NULL)
1110 {
1111 ui32Value = *psDecodeState->pctime;
1112 }
1113 else
1114 {
1115 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current ctime value to be defined!", acRoutine);
1116 return ER;
1117 }
1118 break;
1119 default:
1120 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pctime, acLocalError);
1121 if (iError == ER)
1122 {
1123 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1124 return ER;
1125 }
1126 break;
1127 }
1128
1129 iError = DecodeFormatTime(&ui32Value, pcOutput);
1130 if (iError == ER)
1131 {
1132 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1133 return ER;
1134 }
1135
1136 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->ctime, psDecodeState->pctime, ui32Value);
1137
1138 return ER_OK;
1139 }
1140
1141
1142 /*-
1143 ***********************************************************************
1144 *
1145 * DecodeProcessCTimeMs
1146 *
1147 ***********************************************************************
1148 */
1149 int
DecodeProcessCTimeMs(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1150 DecodeProcessCTimeMs(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1151 {
1152 const char acRoutine[] = "DecodeProcessCTimeMs()";
1153 char acLocalError[MESSAGE_SIZE] = "";
1154 int iError = 0;
1155 APP_UI32 ui32Value = 0;
1156
1157 if (iLength <= 0)
1158 {
1159 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
1160 pcOutput[0] = 0;
1161 return ER_OK; /* It's not an error if a value is missing. */
1162 }
1163
1164 switch (pcToken[0])
1165 {
1166 case '#':
1167 if (psDecodeState->pcms != NULL)
1168 {
1169 ui32Value = *psDecodeState->pcms;
1170 }
1171 else
1172 {
1173 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1174 return ER;
1175 }
1176 break;
1177 case 'X':
1178 if (psDecodeState->pams != NULL)
1179 {
1180 ui32Value = *psDecodeState->pams;
1181 }
1182 else
1183 {
1184 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current ams value to be defined!", acRoutine);
1185 return ER;
1186 }
1187 break;
1188 case 'Y':
1189 if (psDecodeState->pmms != NULL)
1190 {
1191 ui32Value = *psDecodeState->pmms;
1192 }
1193 else
1194 {
1195 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current mms value to be defined!", acRoutine);
1196 return ER;
1197 }
1198 break;
1199 default:
1200 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pcms, acLocalError);
1201 if (iError == ER)
1202 {
1203 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1204 return ER;
1205 }
1206 break;
1207 }
1208
1209 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1210
1211 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->cms, psDecodeState->pcms, ui32Value);
1212
1213 return ER_OK;
1214 }
1215
1216
1217 /*-
1218 ***********************************************************************
1219 *
1220 * DecodeProcessChTime
1221 *
1222 ***********************************************************************
1223 */
1224 int
DecodeProcessChTime(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1225 DecodeProcessChTime(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1226 {
1227 const char acRoutine[] = "DecodeProcessChTime()";
1228 char acLocalError[MESSAGE_SIZE] = "";
1229 char acTimeString[DECODE_TIME_FORMAT_SIZE] = { 0 };
1230 int iError = 0;
1231 APP_UI32 ui32Value = 0;
1232
1233 if (iLength <= 0)
1234 {
1235 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
1236 pcOutput[0] = 0;
1237 return ER_OK; /* It's not an error if a value is missing. */
1238 }
1239
1240 if (pcToken[0] == '~')
1241 {
1242 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
1243 iError = DecodeFormatOutOfBandTime(&pcToken[1], iLength - 1, acTimeString, acLocalError);
1244 if (iError == ER)
1245 {
1246 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1247 return ER;
1248 }
1249 snprintf(pcOutput, DECODE_TIME_FORMAT_SIZE, "%s", acTimeString);
1250 return ER_OK;
1251 }
1252
1253 switch (pcToken[0])
1254 {
1255 case '#':
1256 if (psDecodeState->pchtime != NULL)
1257 {
1258 ui32Value = *psDecodeState->pchtime;
1259 }
1260 else
1261 {
1262 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1263 return ER;
1264 }
1265 break;
1266 case 'X':
1267 if (psDecodeState->patime != NULL)
1268 {
1269 ui32Value = *psDecodeState->patime;
1270 }
1271 else
1272 {
1273 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current atime value to be defined!", acRoutine);
1274 return ER;
1275 }
1276 break;
1277 case 'Y':
1278 if (psDecodeState->pmtime != NULL)
1279 {
1280 ui32Value = *psDecodeState->pmtime;
1281 }
1282 else
1283 {
1284 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current mtime value to be defined!", acRoutine);
1285 return ER;
1286 }
1287 break;
1288 case 'Z':
1289 if (psDecodeState->pctime != NULL)
1290 {
1291 ui32Value = *psDecodeState->pctime;
1292 }
1293 else
1294 {
1295 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current ctime value to be defined!", acRoutine);
1296 return ER;
1297 }
1298 break;
1299 default:
1300 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pchtime, acLocalError);
1301 if (iError == ER)
1302 {
1303 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1304 return ER;
1305 }
1306 break;
1307 }
1308
1309 iError = DecodeFormatTime(&ui32Value, pcOutput);
1310 if (iError == ER)
1311 {
1312 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1313 return ER;
1314 }
1315
1316 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime, ui32Value);
1317
1318 return ER_OK;
1319 }
1320
1321
1322 /*-
1323 ***********************************************************************
1324 *
1325 * DecodeProcessChTimeMs
1326 *
1327 ***********************************************************************
1328 */
1329 int
DecodeProcessChTimeMs(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1330 DecodeProcessChTimeMs(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1331 {
1332 const char acRoutine[] = "DecodeProcessChTimeMs()";
1333 char acLocalError[MESSAGE_SIZE] = "";
1334 int iError = 0;
1335 APP_UI32 ui32Value = 0;
1336
1337 if (iLength <= 0)
1338 {
1339 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
1340 pcOutput[0] = 0;
1341 return ER_OK; /* It's not an error if a value is missing. */
1342 }
1343
1344 switch (pcToken[0])
1345 {
1346 case '#':
1347 if (psDecodeState->pchms != NULL)
1348 {
1349 ui32Value = *psDecodeState->pchms;
1350 }
1351 else
1352 {
1353 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1354 return ER;
1355 }
1356 break;
1357 case 'X':
1358 if (psDecodeState->pams != NULL)
1359 {
1360 ui32Value = *psDecodeState->pams;
1361 }
1362 else
1363 {
1364 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current ams value to be defined!", acRoutine);
1365 return ER;
1366 }
1367 break;
1368 case 'Y':
1369 if (psDecodeState->pmms != NULL)
1370 {
1371 ui32Value = *psDecodeState->pmms;
1372 }
1373 else
1374 {
1375 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current mms value to be defined!", acRoutine);
1376 return ER;
1377 }
1378 break;
1379 case 'Z':
1380 if (psDecodeState->pcms != NULL)
1381 {
1382 ui32Value = *psDecodeState->pcms;
1383 }
1384 else
1385 {
1386 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current cms value to be defined!", acRoutine);
1387 return ER;
1388 }
1389 break;
1390 default:
1391 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pchms, acLocalError);
1392 if (iError == ER)
1393 {
1394 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1395 return ER;
1396 }
1397 break;
1398 }
1399
1400 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1401
1402 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->chms, psDecodeState->pchms, ui32Value);
1403
1404 return ER_OK;
1405 }
1406
1407
1408 /*-
1409 ***********************************************************************
1410 *
1411 * DecodeProcessDevice
1412 *
1413 ***********************************************************************
1414 */
1415 int
DecodeProcessDevice(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1416 DecodeProcessDevice(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1417 {
1418 const char acRoutine[] = "DecodeProcessDevice()";
1419 char acLocalError[MESSAGE_SIZE] = "";
1420 int iError = 0;
1421 APP_UI32 ui32Value = 0;
1422
1423 if (iLength <= 0)
1424 {
1425 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->dev, psDecodeState->pdev);
1426 pcOutput[0] = 0;
1427 return ER_OK; /* It's not an error if a value is missing. */
1428 }
1429
1430 /*-
1431 *********************************************************************
1432 *
1433 * If the decode routine returns an error, clear the previous value
1434 * and NULLify its pointer. A NULL pointer signifies that the value
1435 * is undefined (and, therefore, not to be used). If the decode
1436 * routine returns success, record the decoded value in the output
1437 * buffer, save it as the new previous value, and update its pointer
1438 * as it may have been NULLified in a previous round.
1439 *
1440 *********************************************************************
1441 */
1442 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pdev, acLocalError);
1443 if (iError == ER)
1444 {
1445 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->dev, psDecodeState->pdev);
1446 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1447 return iError;
1448 }
1449 else
1450 {
1451 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->dev, psDecodeState->pdev, ui32Value);
1452 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1453 }
1454
1455 return ER_OK;
1456 }
1457
1458
1459 /*-
1460 ***********************************************************************
1461 *
1462 * DecodeProcessFileIndex
1463 *
1464 ***********************************************************************
1465 */
1466 int
DecodeProcessFileIndex(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1467 DecodeProcessFileIndex(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1468 {
1469 const char acRoutine[] = "DecodeProcessFileIndex()";
1470 char acLocalError[MESSAGE_SIZE] = "";
1471 int iError = 0;
1472 APP_UI64 ui64Value = 0;
1473
1474 if (iLength <= 0)
1475 {
1476 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->findex, psDecodeState->pfindex);
1477 pcOutput[0] = 0;
1478 return ER_OK; /* It's not an error if a value is missing. */
1479 }
1480
1481 /*-
1482 *********************************************************************
1483 *
1484 * If the decode routine returns an error, clear the previous value
1485 * and NULLify its pointer. A NULL pointer signifies that the value
1486 * is undefined (and, therefore, not to be used). If the decode
1487 * routine returns success, record the decoded value in the output
1488 * buffer, save it as the new previous value, and update its pointer
1489 * as it may have been NULLified in a previous round.
1490 *
1491 *********************************************************************
1492 */
1493 iError = Decode64BitHexToDecimal(pcToken, iLength, &ui64Value, psDecodeState->pfindex, acLocalError);
1494 if (iError == ER)
1495 {
1496 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->findex, psDecodeState->pfindex);
1497 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1498 return iError;
1499 }
1500 else
1501 {
1502 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->findex, psDecodeState->pfindex, ui64Value);
1503 #ifdef WIN32
1504 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%I64u", ui64Value);
1505 #else
1506 #ifdef USE_AP_SNPRINTF
1507 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%qu", (unsigned long long) ui64Value);
1508 #else
1509 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%llu", (unsigned long long) ui64Value);
1510 #endif
1511 #endif
1512 }
1513
1514 return ER_OK;
1515 }
1516
1517
1518 /*-
1519 ***********************************************************************
1520 *
1521 * DecodeProcessGroupId
1522 *
1523 ***********************************************************************
1524 */
1525 int
DecodeProcessGroupId(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1526 DecodeProcessGroupId(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1527 {
1528 const char acRoutine[] = "DecodeProcessGroupId()";
1529 char acLocalError[MESSAGE_SIZE] = "";
1530 int iError = 0;
1531 APP_UI32 ui32Value = 0;
1532
1533 if (iLength <= 0)
1534 {
1535 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->gid, psDecodeState->pgid);
1536 pcOutput[0] = 0;
1537 return ER_OK; /* It's not an error if a value is missing. */
1538 }
1539
1540 /*-
1541 *********************************************************************
1542 *
1543 * If the decode routine returns an error, clear the previous value
1544 * and NULLify its pointer. A NULL pointer signifies that the value
1545 * is undefined (and, therefore, not to be used). If the decode
1546 * routine returns success, record the decoded value in the output
1547 * buffer, save it as the new previous value, and update its pointer
1548 * as it may have been NULLified in a previous round.
1549 *
1550 *********************************************************************
1551 */
1552 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pgid, acLocalError);
1553 if (iError == ER)
1554 {
1555 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->gid, psDecodeState->pgid);
1556 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1557 return iError;
1558 }
1559 else
1560 {
1561 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->gid, psDecodeState->pgid, ui32Value);
1562 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1563 }
1564
1565 return ER_OK;
1566 }
1567
1568
1569 /*-
1570 ***********************************************************************
1571 *
1572 * DecodeProcessInode
1573 *
1574 ***********************************************************************
1575 */
1576 int
DecodeProcessInode(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1577 DecodeProcessInode(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1578 {
1579 const char acRoutine[] = "DecodeProcessInode()";
1580 char acLocalError[MESSAGE_SIZE] = "";
1581 int iError = 0;
1582 APP_UI32 ui32Value = 0;
1583
1584 if (iLength <= 0)
1585 {
1586 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->inode, psDecodeState->pinode);
1587 pcOutput[0] = 0;
1588 return ER_OK; /* It's not an error if a value is missing. */
1589 }
1590
1591 /*-
1592 *********************************************************************
1593 *
1594 * If the decode routine returns an error, clear the previous value
1595 * and NULLify its pointer. A NULL pointer signifies that the value
1596 * is undefined (and, therefore, not to be used). If the decode
1597 * routine returns success, record the decoded value in the output
1598 * buffer, save it as the new previous value, and update its pointer
1599 * as it may have been NULLified in a previous round.
1600 *
1601 *********************************************************************
1602 */
1603 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pinode, acLocalError);
1604 if (iError == ER)
1605 {
1606 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->inode, psDecodeState->pinode);
1607 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1608 return iError;
1609 }
1610 else
1611 {
1612 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->inode, psDecodeState->pinode, ui32Value);
1613 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1614 }
1615
1616 return ER_OK;
1617 }
1618
1619
1620 /*-
1621 ***********************************************************************
1622 *
1623 * DecodeProcessLinkCount
1624 *
1625 ***********************************************************************
1626 */
1627 int
DecodeProcessLinkCount(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1628 DecodeProcessLinkCount(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1629 {
1630 const char acRoutine[] = "DecodeProcessLinkCount()";
1631 char acLocalError[MESSAGE_SIZE] = "";
1632 int iError = 0;
1633 APP_UI32 ui32Value = 0;
1634
1635 if (iLength <= 0)
1636 {
1637 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->nlink, psDecodeState->pnlink);
1638 pcOutput[0] = 0;
1639 return ER_OK; /* It's not an error if a value is missing. */
1640 }
1641
1642 /*-
1643 *********************************************************************
1644 *
1645 * If the decode routine returns an error, clear the previous value
1646 * and NULLify its pointer. A NULL pointer signifies that the value
1647 * is undefined (and, therefore, not to be used). If the decode
1648 * routine returns success, record the decoded value in the output
1649 * buffer, save it as the new previous value, and update its pointer
1650 * as it may have been NULLified in a previous round.
1651 *
1652 *********************************************************************
1653 */
1654 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pnlink, acLocalError);
1655 if (iError == ER)
1656 {
1657 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->nlink, psDecodeState->pnlink);
1658 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1659 return iError;
1660 }
1661 else
1662 {
1663 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->nlink, psDecodeState->pnlink, ui32Value);
1664 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1665 }
1666
1667 return ER_OK;
1668 }
1669
1670
1671 /*-
1672 ***********************************************************************
1673 *
1674 * DecodeProcessMTime
1675 *
1676 ***********************************************************************
1677 */
1678 int
DecodeProcessMTime(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1679 DecodeProcessMTime(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1680 {
1681 const char acRoutine[] = "DecodeProcessMTime()";
1682 char acLocalError[MESSAGE_SIZE] = "";
1683 char acTimeString[DECODE_TIME_FORMAT_SIZE] = { 0 };
1684 int iError = 0;
1685 APP_UI32 ui32Value = 0;
1686
1687 if (iLength <= 0)
1688 {
1689 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->mtime, psDecodeState->pmtime);
1690 pcOutput[0] = 0;
1691 return ER_OK; /* It's not an error if a value is missing. */
1692 }
1693
1694 if (pcToken[0] == '~')
1695 {
1696 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->mtime, psDecodeState->pmtime);
1697 iError = DecodeFormatOutOfBandTime(&pcToken[1], iLength - 1, acTimeString, acLocalError);
1698 if (iError == ER)
1699 {
1700 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1701 return ER;
1702 }
1703 snprintf(pcOutput, DECODE_TIME_FORMAT_SIZE, "%s", acTimeString);
1704 return ER_OK;
1705 }
1706
1707 switch (pcToken[0])
1708 {
1709 case '#':
1710 if (psDecodeState->pmtime != NULL)
1711 {
1712 ui32Value = *psDecodeState->pmtime;
1713 }
1714 else
1715 {
1716 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1717 return ER;
1718 }
1719 break;
1720 case 'X':
1721 if (psDecodeState->patime != NULL)
1722 {
1723 ui32Value = *psDecodeState->patime;
1724 }
1725 else
1726 {
1727 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current atime value to be defined!", acRoutine);
1728 return ER;
1729 }
1730 break;
1731 default:
1732 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pmtime, acLocalError);
1733 if (iError == ER)
1734 {
1735 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1736 return ER;
1737 }
1738 break;
1739 }
1740
1741 iError = DecodeFormatTime(&ui32Value, pcOutput);
1742 if (iError == ER)
1743 {
1744 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1745 return ER;
1746 }
1747
1748 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->mtime, psDecodeState->pmtime, ui32Value);
1749
1750 return ER_OK;
1751 }
1752
1753
1754 /*-
1755 ***********************************************************************
1756 *
1757 * DecodeProcessMTimeMs
1758 *
1759 ***********************************************************************
1760 */
1761 int
DecodeProcessMTimeMs(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1762 DecodeProcessMTimeMs(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1763 {
1764 const char acRoutine[] = "DecodeProcessMTimeMs()";
1765 char acLocalError[MESSAGE_SIZE] = "";
1766 int iError = 0;
1767 APP_UI32 ui32Value = 0;
1768
1769 if (iLength <= 0)
1770 {
1771 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->chtime, psDecodeState->pchtime);
1772 pcOutput[0] = 0;
1773 return ER_OK; /* It's not an error if a value is missing. */
1774 }
1775
1776 switch (pcToken[0])
1777 {
1778 case '#':
1779 if (psDecodeState->pmms != NULL)
1780 {
1781 ui32Value = *psDecodeState->pmms;
1782 }
1783 else
1784 {
1785 snprintf(pcError, MESSAGE_SIZE, "%s: Expected previous value to be defined!", acRoutine);
1786 return ER;
1787 }
1788 break;
1789 case 'X':
1790 if (psDecodeState->pams != NULL)
1791 {
1792 ui32Value = *psDecodeState->pams;
1793 }
1794 else
1795 {
1796 snprintf(pcError, MESSAGE_SIZE, "%s: Expected current ams value to be defined!", acRoutine);
1797 return ER;
1798 }
1799 break;
1800 default:
1801 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pmms, acLocalError);
1802 if (iError == ER)
1803 {
1804 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1805 return ER;
1806 }
1807 break;
1808 }
1809
1810 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
1811
1812 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->mms, psDecodeState->pmms, ui32Value);
1813
1814 return ER_OK;
1815 }
1816
1817
1818 /*-
1819 ***********************************************************************
1820 *
1821 * DecodeProcessMagic
1822 *
1823 ***********************************************************************
1824 */
1825 int
DecodeProcessMagic(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1826 DecodeProcessMagic(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1827 {
1828 snprintf(pcOutput, DECODE_MAX_LINE, "%s", pcToken);
1829
1830 return ER_OK;
1831 }
1832
1833
1834 /*-
1835 ***********************************************************************
1836 *
1837 * DecodeProcessMd5
1838 *
1839 ***********************************************************************
1840 */
1841 int
DecodeProcessMd5(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1842 DecodeProcessMd5(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1843 {
1844 const char acRoutine[] = "DecodeProcessMd5()";
1845 char acLocalError[MESSAGE_SIZE] = "";
1846 int iError = 0;
1847 unsigned char aucFileMd5[MD5_HASH_SIZE] = { 0 };
1848
1849 if (iLength <= 0)
1850 {
1851 pcOutput[0] = 0;
1852 return ER_OK; /* It's not an error if a value is missing. */
1853 }
1854
1855 if (pcToken[0] == 'D' && pcToken[1] == 0)
1856 {
1857 snprintf(pcOutput, DECODE_MAX_LINE, "DIRECTORY");
1858 }
1859 else if (pcToken[0] == 'L' && pcToken[1] == 0)
1860 {
1861 snprintf(pcOutput, DECODE_MAX_LINE, "SYMLINK");
1862 }
1863 else if (pcToken[0] == 'S' && pcToken[1] == 0)
1864 {
1865 snprintf(pcOutput, DECODE_MAX_LINE, "SPECIAL");
1866 }
1867 else
1868 {
1869 iError = DecodeGetBase64Hash(pcToken, aucFileMd5, iLength, acLocalError);
1870 if (iError == ER)
1871 {
1872 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1873 return ER;
1874 }
1875 MD5HashToHex(aucFileMd5, pcOutput);
1876 }
1877
1878 return ER_OK;
1879 }
1880
1881
1882 /*-
1883 ***********************************************************************
1884 *
1885 * DecodeProcessMode
1886 *
1887 ***********************************************************************
1888 */
1889 int
DecodeProcessMode(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1890 DecodeProcessMode(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1891 {
1892 const char acRoutine[] = "DecodeProcessMode()";
1893 char acLocalError[MESSAGE_SIZE] = "";
1894 int iError = 0;
1895 APP_UI32 ui32Value = 0;
1896
1897 if (iLength <= 0)
1898 {
1899 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->mode, psDecodeState->pmode);
1900 pcOutput[0] = 0;
1901 return ER_OK; /* It's not an error if a value is missing. */
1902 }
1903
1904 /*-
1905 *********************************************************************
1906 *
1907 * If the decode routine returns an error, clear the previous value
1908 * and NULLify its pointer. A NULL pointer signifies that the value
1909 * is undefined (and, therefore, not to be used). If the decode
1910 * routine returns success, record the decoded value in the output
1911 * buffer, save it as the new previous value, and update its pointer
1912 * as it may have been NULLified in a previous round.
1913 *
1914 *********************************************************************
1915 */
1916 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pmode, acLocalError);
1917 if (iError == ER)
1918 {
1919 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->mode, psDecodeState->pmode);
1920 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
1921 return iError;
1922 }
1923 else
1924 {
1925 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->mode, psDecodeState->pmode, ui32Value);
1926 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%o", ui32Value);
1927 }
1928
1929 return ER_OK;
1930 }
1931
1932
1933 /*-
1934 ***********************************************************************
1935 *
1936 * DecodeProcessNada
1937 *
1938 ***********************************************************************
1939 */
1940 int
DecodeProcessNada(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1941 DecodeProcessNada(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1942 {
1943 snprintf(pcOutput, DECODE_MAX_LINE, "%s", pcToken);
1944
1945 return ER_OK;
1946 }
1947
1948
1949 /*-
1950 ***********************************************************************
1951 *
1952 * DecodeProcessName
1953 *
1954 ***********************************************************************
1955 */
1956 int
DecodeProcessName(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)1957 DecodeProcessName(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
1958 {
1959 const char acRoutine[] = "DecodeProcessName()";
1960 int i = 0;
1961 int j = 0;
1962 unsigned int iFromLastLine = 0;
1963
1964 if (iLength < 2)
1965 {
1966 pcOutput[0] = 0;
1967 snprintf(pcError, MESSAGE_SIZE, "%s: Name length must be >= 2.", acRoutine);
1968 return ER;
1969 }
1970
1971 /*
1972 *********************************************************************
1973 *
1974 * Get 2-byte prefix (i.e., the number of repeated bytes in name)
1975 *
1976 *********************************************************************
1977 */
1978 for (i = iFromLastLine = 0; i < 2; i++)
1979 {
1980 iFromLastLine <<= 4;
1981 if ((pcToken[i] >= '0') && (pcToken[i] <= '9'))
1982 {
1983 iFromLastLine |= pcToken[i] - '0';
1984 }
1985 else if ((pcToken[i] >= 'a') && (pcToken[i] <= 'f'))
1986 {
1987 iFromLastLine |= (pcToken[i] - 'a') + 10;
1988 }
1989 else
1990 {
1991 snprintf(pcError, MESSAGE_SIZE, "%s: Illegal 2-byte prefix.", acRoutine);
1992 return ER;
1993 }
1994 }
1995 if (iFromLastLine > strlen(psDecodeState->name))
1996 {
1997 snprintf(pcError, MESSAGE_SIZE, "%s: Not enough bytes available to perform decode.", acRoutine);
1998 return ER;
1999 }
2000
2001 /*
2002 *********************************************************************
2003 *
2004 * Copy the rest of the current name to the previous name.
2005 *
2006 *********************************************************************
2007 */
2008 if (iFromLastLine == 0)
2009 {
2010 psDecodeState->name[0] = '"';
2011 j = 1;
2012 i = 3;
2013 }
2014 else
2015 {
2016 j = iFromLastLine;
2017 i = 2;
2018 }
2019 while (pcToken[i] != 0 && pcToken[i] != '"')
2020 {
2021 psDecodeState->name[j++] = pcToken[i++];
2022 }
2023 if (pcToken[i] != '"')
2024 {
2025 snprintf(pcError, MESSAGE_SIZE, "%s: Names must end with a double quote.", acRoutine);
2026 return ER;
2027 }
2028 psDecodeState->name[j++] = pcToken[i++];
2029 psDecodeState->name[j] = 0;
2030
2031 snprintf(pcOutput, DECODE_MAX_LINE, "%s", psDecodeState->name);
2032
2033 /*
2034 *********************************************************************
2035 *
2036 * Sanity check the name value.
2037 *
2038 *********************************************************************
2039 */
2040 if (psDecodeState->name[0] != '"' || psDecodeState->name[j - 1] != '"')
2041 {
2042 snprintf(pcError, MESSAGE_SIZE, "%s: Names must be enclosed in double quotes.", acRoutine);
2043 return ER;
2044 }
2045
2046 return ER_OK;
2047 }
2048
2049
2050 /*-
2051 ***********************************************************************
2052 *
2053 * DecodeProcessRDevice
2054 *
2055 ***********************************************************************
2056 */
2057 int
DecodeProcessRDevice(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2058 DecodeProcessRDevice(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2059 {
2060 const char acRoutine[] = "DecodeProcessRDevice()";
2061 char acLocalError[MESSAGE_SIZE] = "";
2062 int iError = 0;
2063 APP_UI32 ui32Value = 0;
2064
2065 if (iLength <= 0)
2066 {
2067 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->rdev, psDecodeState->prdev);
2068 pcOutput[0] = 0;
2069 return ER_OK; /* It's not an error if a value is missing. */
2070 }
2071
2072 /*-
2073 *********************************************************************
2074 *
2075 * If the decode routine returns an error, clear the previous value
2076 * and NULLify its pointer. A NULL pointer signifies that the value
2077 * is undefined (and, therefore, not to be used). If the decode
2078 * routine returns success, record the decoded value in the output
2079 * buffer, save it as the new previous value, and update its pointer
2080 * as it may have been NULLified in a previous round.
2081 *
2082 *********************************************************************
2083 */
2084 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->prdev, acLocalError);
2085 if (iError == ER)
2086 {
2087 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->rdev, psDecodeState->prdev);
2088 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2089 return iError;
2090 }
2091 else
2092 {
2093 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->rdev, psDecodeState->prdev, ui32Value);
2094 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
2095 }
2096
2097 return ER_OK;
2098 }
2099
2100
2101 /*-
2102 ***********************************************************************
2103 *
2104 * DecodeProcessSha1
2105 *
2106 ***********************************************************************
2107 */
2108 int
DecodeProcessSha1(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2109 DecodeProcessSha1(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2110 {
2111 const char acRoutine[] = "DecodeProcessSha1()";
2112 char acLocalError[MESSAGE_SIZE] = "";
2113 int iError = 0;
2114 unsigned char aucFileSha1[SHA1_HASH_SIZE] = { 0 };
2115
2116 if (iLength <= 0)
2117 {
2118 pcOutput[0] = 0;
2119 return ER_OK; /* It's not an error if a value is missing. */
2120 }
2121
2122 if (pcToken[0] == 'D' && pcToken[1] == 0)
2123 {
2124 snprintf(pcOutput, DECODE_MAX_LINE, "DIRECTORY");
2125 }
2126 else if (pcToken[0] == 'L' && pcToken[1] == 0)
2127 {
2128 snprintf(pcOutput, DECODE_MAX_LINE, "SYMLINK");
2129 }
2130 else if (pcToken[0] == 'S' && pcToken[1] == 0)
2131 {
2132 snprintf(pcOutput, DECODE_MAX_LINE, "SPECIAL");
2133 }
2134 else
2135 {
2136 iError = DecodeGetBase64Hash(pcToken, aucFileSha1, iLength, acLocalError);
2137 if (iError == ER)
2138 {
2139 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2140 return iError;
2141 }
2142 SHA1HashToHex(aucFileSha1, pcOutput);
2143 }
2144
2145 return ER_OK;
2146 }
2147
2148
2149 /*-
2150 ***********************************************************************
2151 *
2152 * DecodeProcessSha256
2153 *
2154 ***********************************************************************
2155 */
2156 int
DecodeProcessSha256(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2157 DecodeProcessSha256(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2158 {
2159 const char acRoutine[] = "DecodeProcessSha256()";
2160 char acLocalError[MESSAGE_SIZE] = "";
2161 int iError = 0;
2162 unsigned char aucFileSha256[SHA256_HASH_SIZE] = { 0 };
2163
2164 if (iLength <= 0)
2165 {
2166 pcOutput[0] = 0;
2167 return ER_OK; /* It's not an error if a value is missing. */
2168 }
2169
2170 if (pcToken[0] == 'D' && pcToken[1] == 0)
2171 {
2172 snprintf(pcOutput, DECODE_MAX_LINE, "DIRECTORY");
2173 }
2174 else if (pcToken[0] == 'L' && pcToken[1] == 0)
2175 {
2176 snprintf(pcOutput, DECODE_MAX_LINE, "SYMLINK");
2177 }
2178 else if (pcToken[0] == 'S' && pcToken[1] == 0)
2179 {
2180 snprintf(pcOutput, DECODE_MAX_LINE, "SPECIAL");
2181 }
2182 else
2183 {
2184 iError = DecodeGetBase64Hash(pcToken, aucFileSha256, iLength, acLocalError);
2185 if (iError == ER)
2186 {
2187 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2188 return iError;
2189 }
2190 SHA256HashToHex(aucFileSha256, pcOutput);
2191 }
2192
2193 return ER_OK;
2194 }
2195
2196
2197 /*-
2198 ***********************************************************************
2199 *
2200 * DecodeProcessSize
2201 *
2202 ***********************************************************************
2203 */
2204 int
DecodeProcessSize(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2205 DecodeProcessSize(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2206 {
2207 const char acRoutine[] = "DecodeProcessSize()";
2208 char acLocalError[MESSAGE_SIZE] = "";
2209 int iError = 0;
2210 APP_UI64 ui64Value = 0;
2211
2212 if (iLength <= 0)
2213 {
2214 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->size, psDecodeState->psize);
2215 pcOutput[0] = 0;
2216 return ER_OK; /* It's not an error if a value is missing. */
2217 }
2218
2219 /*-
2220 *********************************************************************
2221 *
2222 * If the decode routine returns an error, clear the previous value
2223 * and NULLify its pointer. A NULL pointer signifies that the value
2224 * is undefined (and, therefore, not to be used). If the decode
2225 * routine returns success, record the decoded value in the output
2226 * buffer, save it as the new previous value, and update its pointer
2227 * as it may have been NULLified in a previous round.
2228 *
2229 *********************************************************************
2230 */
2231 iError = Decode64BitHexToDecimal(pcToken, iLength, &ui64Value, psDecodeState->psize, acLocalError);
2232 if (iError == ER)
2233 {
2234 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->size, psDecodeState->psize);
2235 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2236 return iError;
2237 }
2238 else
2239 {
2240 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->size, psDecodeState->psize, ui64Value);
2241 #ifdef WIN32
2242 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%I64u", ui64Value);
2243 #else
2244 #ifdef USE_AP_SNPRINTF
2245 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%qu", (unsigned long long) ui64Value);
2246 #else
2247 snprintf(pcOutput, FTIMES_MAX_64BIT_SIZE, "%llu", (unsigned long long) ui64Value);
2248 #endif
2249 #endif
2250 }
2251
2252 return ER_OK;
2253 }
2254
2255
2256 /*-
2257 ***********************************************************************
2258 *
2259 * DecodeProcessUserId
2260 *
2261 ***********************************************************************
2262 */
2263 int
DecodeProcessUserId(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2264 DecodeProcessUserId(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2265 {
2266 const char acRoutine[] = "DecodeProcessUserId()";
2267 char acLocalError[MESSAGE_SIZE] = "";
2268 int iError = 0;
2269 APP_UI32 ui32Value = 0;
2270
2271 if (iLength <= 0)
2272 {
2273 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->uid, psDecodeState->puid);
2274 pcOutput[0] = 0;
2275 return ER_OK; /* It's not an error if a value is missing. */
2276 }
2277
2278 /*-
2279 *********************************************************************
2280 *
2281 * If the decode routine returns an error, clear the previous value
2282 * and NULLify its pointer. A NULL pointer signifies that the value
2283 * is undefined (and, therefore, not to be used). If the decode
2284 * routine returns success, record the decoded value in the output
2285 * buffer, save it as the new previous value, and update its pointer
2286 * as it may have been NULLified in a previous round.
2287 *
2288 *********************************************************************
2289 */
2290 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->puid, acLocalError);
2291 if (iError == ER)
2292 {
2293 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->uid, psDecodeState->puid);
2294 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2295 return iError;
2296 }
2297 else
2298 {
2299 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->uid, psDecodeState->puid, ui32Value);
2300 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
2301 }
2302
2303 return ER_OK;
2304 }
2305
2306
2307 /*-
2308 ***********************************************************************
2309 *
2310 * DecodeProcessVolume
2311 *
2312 ***********************************************************************
2313 */
2314 int
DecodeProcessVolume(DECODE_STATE * psDecodeState,char * pcToken,int iLength,char * pcOutput,char * pcError)2315 DecodeProcessVolume(DECODE_STATE *psDecodeState, char *pcToken, int iLength, char *pcOutput, char *pcError)
2316 {
2317 const char acRoutine[] = "DecodeProcessVolume()";
2318 char acLocalError[MESSAGE_SIZE] = "";
2319 int iError = 0;
2320 APP_UI32 ui32Value = 0;
2321
2322 if (iLength <= 0)
2323 {
2324 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->volume, psDecodeState->pvolume);
2325 pcOutput[0] = 0;
2326 return ER_OK; /* It's not an error if a value is missing. */
2327 }
2328
2329 /*-
2330 *********************************************************************
2331 *
2332 * If the decode routine returns an error, clear the previous value
2333 * and NULLify its pointer. A NULL pointer signifies that the value
2334 * is undefined (and, therefore, not to be used). If the decode
2335 * routine returns success, record the decoded value in the output
2336 * buffer, save it as the new previous value, and update its pointer
2337 * as it may have been NULLified in a previous round.
2338 *
2339 *********************************************************************
2340 */
2341 iError = Decode32BitHexToDecimal(pcToken, iLength, &ui32Value, psDecodeState->pvolume, acLocalError);
2342 if (iError == ER)
2343 {
2344 DECODE_UNDEFINE_PREV_NUMBER_VALUE(psDecodeState->volume, psDecodeState->pvolume);
2345 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2346 return iError;
2347 }
2348 else
2349 {
2350 DECODE_DEFINE_PREV_NUMBER_VALUE(psDecodeState->volume, psDecodeState->pvolume, ui32Value);
2351 snprintf(pcOutput, FTIMES_MAX_32BIT_SIZE, "%u", ui32Value);
2352 }
2353
2354 return ER_OK;
2355 }
2356
2357
2358 /*-
2359 ***********************************************************************
2360 *
2361 * DecodeReadLine
2362 *
2363 ***********************************************************************
2364 */
2365 char *
DecodeReadLine(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)2366 DecodeReadLine(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
2367 {
2368 const char acRoutine[] = "DecodeReadLine()";
2369 char acLocalError[MESSAGE_SIZE] = "";
2370
2371 do
2372 {
2373 /*-
2374 *******************************************************************
2375 *
2376 * Flip the current and previous records. This is how we maintain
2377 * state from line to line when decoding a compressed file. The
2378 * current line number is used to determine the new index values,
2379 * so it must not be modified anywhere else in the code.
2380 *
2381 *******************************************************************
2382 */
2383 psSnapshot->psCurrRecord = &psSnapshot->asRecords[(0 + psSnapshot->iLineNumber) % 2];
2384 psSnapshot->psPrevRecord = &psSnapshot->asRecords[(1 + psSnapshot->iLineNumber) % 2];
2385 psSnapshot->iLineNumber++;
2386
2387 /*-
2388 *******************************************************************
2389 *
2390 * Wipe the slate clean for the current (i.e., new) record.
2391 *
2392 *******************************************************************
2393 */
2394 DecodeClearRecord(psSnapshot->psCurrRecord, psSnapshot->iFieldCount);
2395
2396 /*-
2397 *******************************************************************
2398 *
2399 * Read a line, and prune any EOL characters.
2400 *
2401 *******************************************************************
2402 */
2403 /* FIXME Turn this into a loop that can read until an EOL is found.
2404 * There probably should be a maximum length, but it should not
2405 * be too low. If no EOL is found, assume that data is missing,
2406 * and generate an error.
2407 */
2408 if (fgets(psSnapshot->psCurrRecord->acLine, DECODE_MAX_LINE, psSnapshot->pFile) == NULL)
2409 {
2410 if (ferror(psSnapshot->pFile))
2411 {
2412 snprintf(pcError, MESSAGE_SIZE, "%s: fgets(): %s", acRoutine, strerror(errno));
2413 return NULL;
2414 }
2415 else
2416 {
2417 return NULL; /* Assume we've reached EOF. */
2418 }
2419 }
2420
2421 if (SupportChopEOLs(psSnapshot->psCurrRecord->acLine, feof(psSnapshot->pFile) ? 0 : 1, acLocalError) == ER)
2422 {
2423 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2424 return NULL;
2425 }
2426
2427 /*-
2428 *******************************************************************
2429 *
2430 * When compression is enabled, FTimes inserts a checkpoint record
2431 * every COMPRESS_RECOVERY_RATE records. A checkpoint records is
2432 * an uncompressed record. The following logic is used to recover
2433 * from a damaged input stream. All records between the bad record
2434 * and the checkpoint are thrown away. When a new checkpoint is
2435 * located, the decoder state values are reset (i.e., cleared).
2436 *
2437 * Note: This logic does not and should not apply to uncompressed
2438 * files -- i.e., those are decoded in pass-through mode.
2439 *
2440 * Note: Warning messages need to include the snapshot's filename
2441 * and line number because they are written directly to the error
2442 * stream.
2443 *
2444 *******************************************************************
2445 */
2446 if (psSnapshot->iCompressed && psSnapshot->iSkipToNext == TRUE)
2447 {
2448 if (strncmp(psSnapshot->psCurrRecord->acLine, DECODE_CHECKPOINT_STRING, DECODE_CHECKPOINT_LENGTH) == 0)
2449 {
2450 snprintf(pcError, MESSAGE_SIZE, "File = [%s], Line = [%d]: Checkpoint located. Restarting decoders.", psSnapshot->pcFile, psSnapshot->iLineNumber);
2451 ErrorHandler(ER_Warning, pcError, ERROR_WARNING);
2452 memset(&psSnapshot->sDecodeState, 0, sizeof(DECODE_STATE));
2453 psSnapshot->iSkipToNext = FALSE;
2454 }
2455 else
2456 {
2457 snprintf(pcError, MESSAGE_SIZE, "File = [%s], Line = [%d]: Record skipped due to previous error.", psSnapshot->pcFile, psSnapshot->iLineNumber);
2458 ErrorHandler(ER_Warning, pcError, ERROR_WARNING);
2459 psSnapshot->sDecodeStats.ulSkipped++;
2460 }
2461 }
2462
2463 } while (psSnapshot->iSkipToNext == TRUE);
2464
2465 psSnapshot->psCurrRecord->iLineLength = strlen(psSnapshot->psCurrRecord->acLine);
2466
2467 return psSnapshot->psCurrRecord->acLine;
2468 }
2469
2470
2471 /*-
2472 ***********************************************************************
2473 *
2474 * DecodeReadSnapshot
2475 *
2476 ***********************************************************************
2477 */
2478 int
DecodeReadSnapshot(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)2479 DecodeReadSnapshot(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
2480 {
2481 const char acRoutine[] = "DecodeReadSnapshot()";
2482 char acLocalError[MESSAGE_SIZE] = "";
2483 int iError = 0;
2484
2485 /*-
2486 *********************************************************************
2487 *
2488 * Read and process snapshot data. If the read returns NULL, it
2489 * could mean an error has occured or EOF was reached. If a record
2490 * fails to parse (compressed files only), set a flag so that the
2491 * next read will automatically skip all records up to the next
2492 * checkpoint.
2493 *
2494 *********************************************************************
2495 */
2496 while (DecodeReadLine(psSnapshot, acLocalError) != NULL)
2497 {
2498 psSnapshot->sDecodeStats.ulAnalyzed++;
2499 iError = DecodeParseRecord(psSnapshot, acLocalError);
2500 if (iError != ER_OK)
2501 {
2502 if (psSnapshot->iCompressed)
2503 {
2504 psSnapshot->iSkipToNext = TRUE;
2505 }
2506 psSnapshot->sDecodeStats.ulSkipped++;
2507 continue;
2508 }
2509 iError = DecodeWriteRecord(psSnapshot, acLocalError);
2510 if (iError != ER_OK)
2511 {
2512 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s], Line = [%d]: %s", acRoutine, psSnapshot->pcFile, psSnapshot->iLineNumber, acLocalError);
2513 return ER;
2514 }
2515 psSnapshot->sDecodeStats.ulDecoded++;
2516 }
2517 if (ferror(psSnapshot->pFile))
2518 {
2519 snprintf(pcError, MESSAGE_SIZE, "%s: File = [%s], Line = [%d]: %s", acRoutine, psSnapshot->pcFile, psSnapshot->iLineNumber, acLocalError);
2520 psSnapshot->sDecodeStats.ulSkipped++;
2521 return ER;
2522 }
2523
2524 return ER_OK;
2525 }
2526
2527
2528 /*-
2529 ***********************************************************************
2530 *
2531 * DecodeSetNewLine
2532 *
2533 ***********************************************************************
2534 */
2535 void
DecodeSetNewLine(char * pcNewLine)2536 DecodeSetNewLine(char *pcNewLine)
2537 {
2538 strncpy(gacNewLine, (strcmp(pcNewLine, CRLF) == 0) ? CRLF : LF, NEWLINE_LENGTH);
2539 }
2540
2541
2542 /*-
2543 ***********************************************************************
2544 *
2545 * DecodeSetOutputStream
2546 *
2547 ***********************************************************************
2548 */
2549 void
DecodeSetOutputStream(FILE * pFile)2550 DecodeSetOutputStream(FILE *pFile)
2551 {
2552 gpFile = pFile;
2553 }
2554
2555
2556 /*-
2557 ***********************************************************************
2558 *
2559 * DecodeWriteHeader
2560 *
2561 ***********************************************************************
2562 */
2563 int
DecodeWriteHeader(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)2564 DecodeWriteHeader(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
2565 {
2566 const char acRoutine[] = "DecodeWriteHeader()";
2567 char acHeader[DECODE_MAX_LINE] = { 0 };
2568 char acLocalError[MESSAGE_SIZE] = "";
2569 int i = 0;
2570 int iError = 0;
2571 int n = 0;
2572
2573 for (i = n = 0; i < psSnapshot->iFieldCount; i++)
2574 {
2575 n += sprintf(&acHeader[n], "%s%s", (i > 0) ? DECODE_SEPARATOR_S : "", psSnapshot->psDecodeMap[psSnapshot->aiIndex2Map[i]].acUName);
2576 }
2577 n += sprintf(&acHeader[n], "%s", gacNewLine);
2578
2579 iError = SupportWriteData(gpFile, acHeader, n, acLocalError);
2580 if (iError != ER_OK)
2581 {
2582 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2583 return iError;
2584 }
2585
2586 return ER_OK;
2587 }
2588
2589
2590 /*-
2591 ***********************************************************************
2592 *
2593 * DecodeWriteRecord
2594 *
2595 ***********************************************************************
2596 */
2597 int
DecodeWriteRecord(SNAPSHOT_CONTEXT * psSnapshot,char * pcError)2598 DecodeWriteRecord(SNAPSHOT_CONTEXT *psSnapshot, char *pcError)
2599 {
2600 const char acRoutine[] = "DecodeWriteRecord()";
2601 char acOutput[(DECODE_FIELD_COUNT)*(DECODE_MAX_LINE)]; /* Don't initialize this with '{ 0 }' -- it's a hugh performance hit. */
2602 char acLocalError[MESSAGE_SIZE] = "";
2603 int i = 0;
2604 int iError = 0;
2605 int n = 0;
2606
2607 for (i = n = 0; i < psSnapshot->iFieldCount; i++)
2608 {
2609 n += sprintf(&acOutput[n], "%s%s", (i > 0) ? DECODE_SEPARATOR_S : "", psSnapshot->psCurrRecord->ppcFields[psSnapshot->aiIndex2Map[i]]);
2610 }
2611 n += sprintf(&acOutput[n], "%s", gacNewLine);
2612
2613 iError = SupportWriteData(gpFile, acOutput, n, acLocalError);
2614 if (iError != ER_OK)
2615 {
2616 snprintf(pcError, MESSAGE_SIZE, "%s: %s", acRoutine, acLocalError);
2617 return iError;
2618 }
2619
2620 return ER_OK;
2621 }
2622