1 /******************************************************************************
2  *
3  * Module Name: asfile - Main module for the acpi source processor utility
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpisrc.h"
45 
46 /* Local prototypes */
47 
48 void
49 AsDoWildcard (
50     ACPI_CONVERSION_TABLE   *ConversionTable,
51     char                    *SourcePath,
52     char                    *TargetPath,
53     int                     MaxPathLength,
54     int                     FileType,
55     char                    *WildcardSpec);
56 
57 BOOLEAN
58 AsDetectLoneLineFeeds (
59     char                    *Filename,
60     char                    *Buffer);
61 
62 static ACPI_INLINE int
63 AsMaxInt (int a, int b)
64 {
65     return (a > b ? a : b);
66 }
67 
68 
69 /******************************************************************************
70  *
71  * FUNCTION:    AsDoWildcard
72  *
73  * DESCRIPTION: Process files via wildcards
74  *
75  ******************************************************************************/
76 
77 void
78 AsDoWildcard (
79     ACPI_CONVERSION_TABLE   *ConversionTable,
80     char                    *SourcePath,
81     char                    *TargetPath,
82     int                     MaxPathLength,
83     int                     FileType,
84     char                    *WildcardSpec)
85 {
86     void                    *DirInfo;
87     char                    *Filename;
88     char                    *SourceDirPath;
89     char                    *TargetDirPath;
90     char                    RequestedFileType;
91 
92 
93     if (FileType == FILE_TYPE_DIRECTORY)
94     {
95         RequestedFileType = REQUEST_DIR_ONLY;
96     }
97     else
98     {
99         RequestedFileType = REQUEST_FILE_ONLY;
100     }
101 
102     VERBOSE_PRINT (("Checking for %s source files in directory \"%s\"\n",
103             WildcardSpec, SourcePath));
104 
105     /* Open the directory for wildcard search */
106 
107     DirInfo = AcpiOsOpenDirectory (SourcePath, WildcardSpec, RequestedFileType);
108     if (DirInfo)
109     {
110         /*
111          * Get all of the files that match both the
112          * wildcard and the requested file type
113          */
114         while ((Filename = AcpiOsGetNextFilename (DirInfo)))
115         {
116             /* Looking for directory files, must check file type */
117 
118             switch (RequestedFileType)
119             {
120             case REQUEST_DIR_ONLY:
121 
122                 /* If we actually have a dir, process the subtree */
123 
124                 if (!AsCheckForDirectory (SourcePath, TargetPath, Filename,
125                     &SourceDirPath, &TargetDirPath))
126                 {
127                     VERBOSE_PRINT (("Subdirectory: %s\n", Filename));
128 
129                     AsProcessTree (ConversionTable, SourceDirPath, TargetDirPath);
130                     free (SourceDirPath);
131                     free (TargetDirPath);
132                 }
133                 break;
134 
135             case REQUEST_FILE_ONLY:
136 
137                 /* Otherwise, this is a file, not a directory */
138 
139                 VERBOSE_PRINT (("File: %s\n", Filename));
140 
141                 AsProcessOneFile (ConversionTable, SourcePath, TargetPath,
142                     MaxPathLength, Filename, FileType);
143                 break;
144 
145             default:
146 
147                 break;
148             }
149         }
150 
151         /* Cleanup */
152 
153         AcpiOsCloseDirectory (DirInfo);
154     }
155 }
156 
157 
158 /******************************************************************************
159  *
160  * FUNCTION:    AsProcessTree
161  *
162  * DESCRIPTION: Process the directory tree. Files with the extension ".C" and
163  *              ".H" are processed as the tree is traversed.
164  *
165  ******************************************************************************/
166 
167 ACPI_NATIVE_INT
168 AsProcessTree (
169     ACPI_CONVERSION_TABLE   *ConversionTable,
170     char                    *SourcePath,
171     char                    *TargetPath)
172 {
173     int                     MaxPathLength;
174 
175 
176     MaxPathLength = AsMaxInt (strlen (SourcePath), strlen (TargetPath));
177 
178     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
179     {
180         if (ConversionTable->Flags & FLG_LOWERCASE_DIRNAMES)
181         {
182             AcpiUtStrlwr (TargetPath);
183         }
184 
185         VERBOSE_PRINT (("Creating Directory \"%s\"\n", TargetPath));
186         if (mkdir (TargetPath))
187         {
188             if (errno != EEXIST)
189             {
190                 printf ("Could not create target directory\n");
191                 return (-1);
192             }
193         }
194     }
195 
196     /* Do the C source files */
197 
198     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
199         FILE_TYPE_SOURCE, "*.c");
200 
201     /* Do the C header files */
202 
203     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
204         FILE_TYPE_HEADER, "*.h");
205 
206     /* Do the Lex file(s) */
207 
208     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
209         FILE_TYPE_SOURCE, "*.l");
210 
211     /* Do the yacc file(s) */
212 
213     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
214         FILE_TYPE_SOURCE, "*.y");
215 
216     /* Do any ASL files */
217 
218     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
219         FILE_TYPE_HEADER, "*.asl");
220 
221     /* Do any subdirectories */
222 
223     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
224         FILE_TYPE_DIRECTORY, "*");
225 
226     return (0);
227 }
228 
229 
230 /******************************************************************************
231  *
232  * FUNCTION:    AsDetectLoneLineFeeds
233  *
234  * DESCRIPTION: Find LF without CR.
235  *
236  ******************************************************************************/
237 
238 BOOLEAN
239 AsDetectLoneLineFeeds (
240     char                    *Filename,
241     char                    *Buffer)
242 {
243     UINT32                  i = 1;
244     UINT32                  LfCount = 0;
245     UINT32                  LineCount = 0;
246 
247 
248     if (!Buffer[0])
249     {
250         return (FALSE);
251     }
252 
253     while (Buffer[i])
254     {
255         if (Buffer[i] == 0x0A)
256         {
257             if (Buffer[i-1] != 0x0D)
258             {
259                 LfCount++;
260             }
261 
262             LineCount++;
263         }
264         i++;
265     }
266 
267     if (LfCount)
268     {
269         if (LineCount == LfCount)
270         {
271             if (!Gbl_IgnoreLoneLineFeeds)
272             {
273                 printf ("%s: ****File has UNIX format**** (LF only, not CR/LF) %u lines\n",
274                     Filename, LfCount);
275             }
276         }
277         else
278         {
279             printf ("%s: %u lone linefeeds in file\n", Filename, LfCount);
280         }
281 
282         return (TRUE);
283     }
284 
285     return (FALSE);
286 }
287 
288 
289 /******************************************************************************
290  *
291  * FUNCTION:    AsConvertFile
292  *
293  * DESCRIPTION: Perform the requested transforms on the file buffer (as
294  *              determined by the ConversionTable and the FileType).
295  *
296  ******************************************************************************/
297 
298 void
299 AsConvertFile (
300     ACPI_CONVERSION_TABLE   *ConversionTable,
301     char                    *FileBuffer,
302     char                    *Filename,
303     ACPI_NATIVE_INT         FileType)
304 {
305     UINT32                  i;
306     UINT32                  Functions;
307     ACPI_STRING_TABLE       *StringTable;
308     ACPI_IDENTIFIER_TABLE   *ConditionalTable;
309     ACPI_IDENTIFIER_TABLE   *LineTable;
310     ACPI_TYPED_IDENTIFIER_TABLE *StructTable;
311     ACPI_IDENTIFIER_TABLE   *SpecialMacroTable;
312 
313 
314     switch (FileType)
315     {
316     case FILE_TYPE_SOURCE:
317 
318         Functions           = ConversionTable->SourceFunctions;
319         StringTable         = ConversionTable->SourceStringTable;
320         LineTable           = ConversionTable->SourceLineTable;
321         ConditionalTable    = ConversionTable->SourceConditionalTable;
322         StructTable         = ConversionTable->SourceStructTable;
323         SpecialMacroTable   = ConversionTable->SourceSpecialMacroTable;
324        break;
325 
326     case FILE_TYPE_HEADER:
327 
328         Functions           = ConversionTable->HeaderFunctions;
329         StringTable         = ConversionTable->HeaderStringTable;
330         LineTable           = ConversionTable->HeaderLineTable;
331         ConditionalTable    = ConversionTable->HeaderConditionalTable;
332         StructTable         = ConversionTable->HeaderStructTable;
333         SpecialMacroTable   = ConversionTable->HeaderSpecialMacroTable;
334         break;
335 
336     case FILE_TYPE_PATCH:
337 
338         Functions           = ConversionTable->PatchFunctions;
339         StringTable         = ConversionTable->PatchStringTable;
340         LineTable           = ConversionTable->PatchLineTable;
341         ConditionalTable    = ConversionTable->PatchConditionalTable;
342         StructTable         = ConversionTable->PatchStructTable;
343         SpecialMacroTable   = ConversionTable->PatchSpecialMacroTable;
344         break;
345 
346     default:
347 
348         printf ("Unknown file type, cannot process\n");
349         return;
350     }
351 
352 
353     Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs");
354     Gbl_Files++;
355     VERBOSE_PRINT (("Processing %u bytes\n",
356         (unsigned int) strlen (FileBuffer)));
357 
358     if (Gbl_Cleanup)
359     {
360         AsRemoveExtraLines (FileBuffer, Filename);
361         AsRemoveSpacesAfterPeriod (FileBuffer, Filename);
362     }
363 
364     if (ConversionTable->LowerCaseTable)
365     {
366         for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++)
367         {
368             AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier,
369                 FileBuffer);
370         }
371     }
372 
373     /* Process all the string replacements */
374 
375     if (StringTable)
376     {
377         for (i = 0; StringTable[i].Target; i++)
378         {
379             AsReplaceString (StringTable[i].Target, StringTable[i].Replacement,
380                 StringTable[i].Type, FileBuffer);
381         }
382     }
383 
384     if (LineTable)
385     {
386         for (i = 0; LineTable[i].Identifier; i++)
387         {
388             AsRemoveLine (FileBuffer, LineTable[i].Identifier);
389         }
390     }
391 
392     if (ConditionalTable)
393     {
394         for (i = 0; ConditionalTable[i].Identifier; i++)
395         {
396             AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier);
397         }
398     }
399 
400 #ifdef _OBSOLETE_FUNCTIONS
401     if (MacroTable)
402     {
403         for (i = 0; MacroTable[i].Identifier; i++)
404         {
405             AsRemoveMacro (FileBuffer, MacroTable[i].Identifier);
406         }
407     }
408 #endif
409 
410     if (StructTable)
411     {
412         for (i = 0; StructTable[i].Identifier; i++)
413         {
414             AsInsertPrefix (FileBuffer, StructTable[i].Identifier,
415                 StructTable[i].Type);
416         }
417     }
418 
419     if (SpecialMacroTable)
420     {
421         for (i = 0; SpecialMacroTable[i].Identifier; i++)
422         {
423             AsCleanupSpecialMacro (FileBuffer, SpecialMacroTable[i].Identifier);
424         }
425     }
426 
427     /* Process the function table */
428 
429     for (i = 0; i < 32; i++)
430     {
431         /* Decode the function bitmap */
432 
433         switch ((1 << i) & Functions)
434         {
435         case 0:
436 
437             /* This function not configured */
438             break;
439 
440         case CVT_COUNT_TABS:
441 
442             AsCountTabs (FileBuffer, Filename);
443             break;
444 
445         case CVT_COUNT_NON_ANSI_COMMENTS:
446 
447             AsCountNonAnsiComments (FileBuffer, Filename);
448             break;
449 
450         case CVT_CHECK_BRACES:
451 
452             AsCheckForBraces (FileBuffer, Filename);
453             break;
454 
455         case CVT_TRIM_LINES:
456 
457             AsTrimLines (FileBuffer, Filename);
458             break;
459 
460         case CVT_COUNT_LINES:
461 
462             AsCountSourceLines (FileBuffer, Filename);
463             break;
464 
465         case CVT_BRACES_ON_SAME_LINE:
466 
467             AsBracesOnSameLine (FileBuffer);
468             break;
469 
470         case CVT_MIXED_CASE_TO_UNDERSCORES:
471 
472             AsMixedCaseToUnderscores (FileBuffer, Filename);
473             break;
474 
475         case CVT_LOWER_CASE_IDENTIFIERS:
476 
477             AsLowerCaseIdentifiers (FileBuffer);
478             break;
479 
480         case CVT_REMOVE_DEBUG_MACROS:
481 
482             AsRemoveDebugMacros (FileBuffer);
483             break;
484 
485         case CVT_TRIM_WHITESPACE:
486 
487             AsTrimWhitespace (FileBuffer);
488             break;
489 
490         case CVT_REMOVE_EMPTY_BLOCKS:
491 
492             AsRemoveEmptyBlocks (FileBuffer, Filename);
493             break;
494 
495         case CVT_REDUCE_TYPEDEFS:
496 
497             AsReduceTypedefs (FileBuffer, "typedef union");
498             AsReduceTypedefs (FileBuffer, "typedef struct");
499             break;
500 
501         case CVT_SPACES_TO_TABS4:
502 
503             AsTabify4 (FileBuffer);
504             break;
505 
506         case CVT_SPACES_TO_TABS8:
507 
508             AsTabify8 (FileBuffer);
509             break;
510 
511         case CVT_COUNT_SHORTMULTILINE_COMMENTS:
512 
513 #ifdef ACPI_FUTURE_IMPLEMENTATION
514             AsTrimComments (FileBuffer, Filename);
515 #endif
516             break;
517 
518         default:
519 
520             printf ("Unknown conversion subfunction opcode\n");
521             break;
522         }
523     }
524 
525     if (ConversionTable->NewHeader)
526     {
527         AsReplaceHeader (FileBuffer, ConversionTable->NewHeader);
528     }
529 }
530 
531 
532 /******************************************************************************
533  *
534  * FUNCTION:    AsProcessOneFile
535  *
536  * DESCRIPTION: Process one source file. The file is opened, read entirely
537  *              into a buffer, converted, then written to a new file.
538  *
539  ******************************************************************************/
540 
541 ACPI_NATIVE_INT
542 AsProcessOneFile (
543     ACPI_CONVERSION_TABLE   *ConversionTable,
544     char                    *SourcePath,
545     char                    *TargetPath,
546     int                     MaxPathLength,
547     char                    *Filename,
548     ACPI_NATIVE_INT         FileType)
549 {
550     char                    *Pathname;
551     char                    *OutPathname;
552     int                     Status = 0;
553 
554 
555     /* Allocate a file pathname buffer for both source and target */
556 
557     Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1);
558     if (!Pathname)
559     {
560         printf ("Could not allocate buffer for file pathnames\n");
561         return (-1);
562     }
563 
564     Gbl_FileType = FileType;
565 
566     /* Generate the source pathname and read the file */
567 
568     if (SourcePath)
569     {
570         strcpy (Pathname, SourcePath);
571         strcat (Pathname, "/");
572     }
573 
574     strcat (Pathname, Filename);
575 
576     if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize))
577     {
578         Status = -1;
579         goto Exit1;
580     }
581 
582     Gbl_HeaderSize = 0;
583     if (strstr (Filename, ".asl"))
584     {
585         Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */
586     }
587     else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE))
588     {
589         Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */
590     }
591     else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE))
592     {
593         Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */
594     }
595 
596     /* Process the file in the buffer */
597 
598     Gbl_MadeChanges = FALSE;
599     if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds)
600     {
601         /*
602          * All lone LFs will be converted to CR/LF
603          * (when file is written, Windows version only)
604          */
605         printf ("Converting lone linefeeds\n");
606         Gbl_MadeChanges = TRUE;
607     }
608 
609     AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType);
610 
611     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
612     {
613         if (!(Gbl_Overwrite && !Gbl_MadeChanges))
614         {
615             /* Generate the target pathname and write the file */
616 
617             OutPathname = calloc (MaxPathLength +
618                 strlen (Filename) + 2 + strlen (TargetPath), 1);
619             if (!OutPathname)
620             {
621                 printf ("Could not allocate buffer for file pathnames\n");
622                 Status = -1;
623                 goto Exit2;
624             }
625 
626             strcpy (OutPathname, TargetPath);
627             if (SourcePath)
628             {
629                 strcat (OutPathname, "/");
630                 strcat (OutPathname, Filename);
631             }
632 
633             AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags);
634             free (OutPathname);
635         }
636     }
637 
638 Exit2:
639     free (Gbl_FileBuffer);
640 
641 Exit1:
642     free (Pathname);
643     return (Status);
644 }
645 
646 
647 /******************************************************************************
648  *
649  * FUNCTION:    AsCheckForDirectory
650  *
651  * DESCRIPTION: Check if the current file is a valid directory. If not,
652  *              construct the full pathname for the source and target paths.
653  *              Checks for the dot and dot-dot files (they are ignored)
654  *
655  ******************************************************************************/
656 
657 ACPI_NATIVE_INT
658 AsCheckForDirectory (
659     char                    *SourceDirPath,
660     char                    *TargetDirPath,
661     char                    *Filename,
662     char                    **SourcePath,
663     char                    **TargetPath)
664 {
665     char                    *SrcPath;
666     char                    *TgtPath;
667 
668 
669     if (!(strcmp (Filename, ".")) ||
670         !(strcmp (Filename, "..")))
671     {
672         return (-1);
673     }
674 
675     SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1);
676     if (!SrcPath)
677     {
678         printf ("Could not allocate buffer for directory source pathname\n");
679         return (-1);
680     }
681 
682     TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1);
683     if (!TgtPath)
684     {
685         printf ("Could not allocate buffer for directory target pathname\n");
686         free (SrcPath);
687         return (-1);
688     }
689 
690     strcpy (SrcPath, SourceDirPath);
691     strcat (SrcPath, "/");
692     strcat (SrcPath, Filename);
693 
694     strcpy (TgtPath, TargetDirPath);
695     strcat (TgtPath, "/");
696     strcat (TgtPath, Filename);
697 
698     *SourcePath = SrcPath;
699     *TargetPath = TgtPath;
700     return (0);
701 }
702 
703 
704 /******************************************************************************
705  *
706  * FUNCTION:    AsGetFile
707  *
708  * DESCRIPTION: Open a file and read it entirely into a an allocated buffer
709  *
710  ******************************************************************************/
711 
712 int
713 AsGetFile (
714     char                    *Filename,
715     char                    **FileBuffer,
716     UINT32                  *FileSize)
717 {
718     FILE                    *File;
719     UINT32                  Size;
720     char                    *Buffer;
721     size_t                  Actual;
722 
723 
724     /* Binary mode leaves CR/LF pairs */
725 
726     File = fopen (Filename, "rb");
727     if (!File)
728     {
729         printf ("Could not open file %s\n", Filename);
730         return (-1);
731     }
732 
733     /* Need file size to allocate a buffer */
734 
735     Size = CmGetFileSize (File);
736     if (Size == ACPI_UINT32_MAX)
737     {
738         printf ("Could not get file size for %s\n", Filename);
739         goto ErrorExit;
740     }
741 
742     /*
743      * Create a buffer for the entire file
744      * Add plenty extra buffer to accommodate string replacements
745      */
746     Gbl_TotalSize += Size;
747 
748     Buffer = calloc (Size * 2, 1);
749     if (!Buffer)
750     {
751         printf ("Could not allocate buffer of size %u\n", Size * 2);
752         goto ErrorExit;
753     }
754 
755     /* Read the entire file */
756 
757     Actual = fread (Buffer, 1, Size, File);
758     if (Actual != Size)
759     {
760         printf ("Could not read the input file %s (%u bytes)\n",
761             Filename, Size);
762         goto ErrorFree;
763     }
764 
765     Buffer [Size] = 0;         /* Null terminate the buffer */
766     fclose (File);
767 
768     /* Check for unix contamination */
769 
770     Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer);
771 
772     /*
773      * Convert all CR/LF pairs to LF only. We do this locally so that
774      * this code is portable across operating systems.
775      */
776     AsConvertToLineFeeds (Buffer);
777 
778     *FileBuffer = Buffer;
779     *FileSize = Size;
780     return (0);
781 
782 ErrorFree:
783     free (Buffer);
784 
785 ErrorExit:
786 
787     fclose (File);
788     return (-1);
789 }
790 
791 
792 /******************************************************************************
793  *
794  * FUNCTION:    AsPutFile
795  *
796  * DESCRIPTION: Create a new output file and write the entire contents of the
797  *              buffer to the new file. Buffer must be a zero terminated string
798  *
799  ******************************************************************************/
800 
801 int
802 AsPutFile (
803     char                    *Pathname,
804     char                    *FileBuffer,
805     UINT32                  SystemFlags)
806 {
807     FILE                    *File;
808     UINT32                  FileSize;
809     size_t                  Actual;
810     int                     Status = 0;
811 
812 
813     /* Create the target file */
814 
815     if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS))
816     {
817         /* Put back the CR before each LF */
818 
819         AsInsertCarriageReturns (FileBuffer);
820     }
821 
822     File = fopen (Pathname, "w+b");
823     if (!File)
824     {
825         perror ("Could not create destination file");
826         printf ("Could not create destination file \"%s\"\n", Pathname);
827         return (-1);
828     }
829 
830     /* Write the buffer to the file */
831 
832     FileSize = strlen (FileBuffer);
833     Actual = fwrite (FileBuffer, 1, FileSize, File);
834     if (Actual != FileSize)
835     {
836         printf ("Error writing output file \"%s\"\n", Pathname);
837         Status = -1;
838     }
839 
840     fclose (File);
841     return (Status);
842 }
843