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