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 #include "acapps.h"
46 
47 /* Local prototypes */
48 
49 void
50 AsDoWildcard (
51     ACPI_CONVERSION_TABLE   *ConversionTable,
52     char                    *SourcePath,
53     char                    *TargetPath,
54     int                     MaxPathLength,
55     int                     FileType,
56     char                    *WildcardSpec);
57 
58 BOOLEAN
59 AsDetectLoneLineFeeds (
60     char                    *Filename,
61     char                    *Buffer);
62 
63 static ACPI_INLINE int
64 AsMaxInt (int a, int b)
65 {
66     return (a > b ? a : b);
67 }
68 
69 
70 /******************************************************************************
71  *
72  * FUNCTION:    AsDoWildcard
73  *
74  * DESCRIPTION: Process files via wildcards
75  *
76  ******************************************************************************/
77 
78 void
79 AsDoWildcard (
80     ACPI_CONVERSION_TABLE   *ConversionTable,
81     char                    *SourcePath,
82     char                    *TargetPath,
83     int                     MaxPathLength,
84     int                     FileType,
85     char                    *WildcardSpec)
86 {
87     void                    *DirInfo;
88     char                    *Filename;
89     char                    *SourceDirPath;
90     char                    *TargetDirPath;
91     char                    RequestedFileType;
92 
93 
94     if (FileType == FILE_TYPE_DIRECTORY)
95     {
96         RequestedFileType = REQUEST_DIR_ONLY;
97     }
98     else
99     {
100         RequestedFileType = REQUEST_FILE_ONLY;
101     }
102 
103     VERBOSE_PRINT (("Checking for %s source files in directory \"%s\"\n",
104             WildcardSpec, SourcePath));
105 
106     /* Open the directory for wildcard search */
107 
108     DirInfo = AcpiOsOpenDirectory (SourcePath, WildcardSpec, RequestedFileType);
109     if (DirInfo)
110     {
111         /*
112          * Get all of the files that match both the
113          * wildcard and the requested file type
114          */
115         while ((Filename = AcpiOsGetNextFilename (DirInfo)))
116         {
117             /* Looking for directory files, must check file type */
118 
119             switch (RequestedFileType)
120             {
121             case REQUEST_DIR_ONLY:
122 
123                 /* If we actually have a dir, process the subtree */
124 
125                 if (!AsCheckForDirectory (SourcePath, TargetPath, Filename,
126                     &SourceDirPath, &TargetDirPath))
127                 {
128                     VERBOSE_PRINT (("Subdirectory: %s\n", Filename));
129 
130                     AsProcessTree (ConversionTable, SourceDirPath, TargetDirPath);
131                     free (SourceDirPath);
132                     free (TargetDirPath);
133                 }
134                 break;
135 
136             case REQUEST_FILE_ONLY:
137 
138                 /* Otherwise, this is a file, not a directory */
139 
140                 VERBOSE_PRINT (("File: %s\n", Filename));
141 
142                 AsProcessOneFile (ConversionTable, SourcePath, TargetPath,
143                     MaxPathLength, Filename, FileType);
144                 break;
145 
146             default:
147 
148                 break;
149             }
150         }
151 
152         /* Cleanup */
153 
154         AcpiOsCloseDirectory (DirInfo);
155     }
156 }
157 
158 
159 /******************************************************************************
160  *
161  * FUNCTION:    AsProcessTree
162  *
163  * DESCRIPTION: Process the directory tree. Files with the extension ".C" and
164  *              ".H" are processed as the tree is traversed.
165  *
166  ******************************************************************************/
167 
168 ACPI_NATIVE_INT
169 AsProcessTree (
170     ACPI_CONVERSION_TABLE   *ConversionTable,
171     char                    *SourcePath,
172     char                    *TargetPath)
173 {
174     int                     MaxPathLength;
175 
176 
177     MaxPathLength = AsMaxInt (strlen (SourcePath), strlen (TargetPath));
178 
179     if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT))
180     {
181         if (ConversionTable->Flags & FLG_LOWERCASE_DIRNAMES)
182         {
183             AcpiUtStrlwr (TargetPath);
184         }
185 
186         VERBOSE_PRINT (("Creating Directory \"%s\"\n", TargetPath));
187         if (mkdir (TargetPath))
188         {
189             if (errno != EEXIST)
190             {
191                 printf ("Could not create target directory\n");
192                 return (-1);
193             }
194         }
195     }
196 
197     /* Do the C source files */
198 
199     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
200         FILE_TYPE_SOURCE, "*.c");
201 
202     /* Do the C header files */
203 
204     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
205         FILE_TYPE_HEADER, "*.h");
206 
207     /* Do the Lex file(s) */
208 
209     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
210         FILE_TYPE_SOURCE, "*.l");
211 
212     /* Do the yacc file(s) */
213 
214     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
215         FILE_TYPE_SOURCE, "*.y");
216 
217     /* Do any ASL files */
218 
219     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
220         FILE_TYPE_HEADER, "*.asl");
221 
222     /* Do any subdirectories */
223 
224     AsDoWildcard (ConversionTable, SourcePath, TargetPath, MaxPathLength,
225         FILE_TYPE_DIRECTORY, "*");
226 
227     return (0);
228 }
229 
230 
231 /******************************************************************************
232  *
233  * FUNCTION:    AsDetectLoneLineFeeds
234  *
235  * DESCRIPTION: Find LF without CR.
236  *
237  ******************************************************************************/
238 
239 BOOLEAN
240 AsDetectLoneLineFeeds (
241     char                    *Filename,
242     char                    *Buffer)
243 {
244     UINT32                  i = 1;
245     UINT32                  LfCount = 0;
246     UINT32                  LineCount = 0;
247 
248 
249     if (!Buffer[0])
250     {
251         return (FALSE);
252     }
253 
254     while (Buffer[i])
255     {
256         if (Buffer[i] == 0x0A)
257         {
258             if (Buffer[i-1] != 0x0D)
259             {
260                 LfCount++;
261             }
262 
263             LineCount++;
264         }
265         i++;
266     }
267 
268     if (LfCount)
269     {
270         if (LineCount == LfCount)
271         {
272             if (!Gbl_IgnoreLoneLineFeeds)
273             {
274                 printf ("%s: ****File has UNIX format**** (LF only, not CR/LF) %u lines\n",
275                     Filename, LfCount);
276             }
277         }
278         else
279         {
280             printf ("%s: %u lone linefeeds in file\n", Filename, LfCount);
281         }
282 
283         return (TRUE);
284     }
285 
286     return (FALSE);
287 }
288 
289 
290 /******************************************************************************
291  *
292  * FUNCTION:    AsConvertFile
293  *
294  * DESCRIPTION: Perform the requested transforms on the file buffer (as
295  *              determined by the ConversionTable and the FileType).
296  *
297  ******************************************************************************/
298 
299 void
300 AsConvertFile (
301     ACPI_CONVERSION_TABLE   *ConversionTable,
302     char                    *FileBuffer,
303     char                    *Filename,
304     ACPI_NATIVE_INT         FileType)
305 {
306     UINT32                  i;
307     UINT32                  Functions;
308     ACPI_STRING_TABLE       *StringTable;
309     ACPI_IDENTIFIER_TABLE   *ConditionalTable;
310     ACPI_IDENTIFIER_TABLE   *LineTable;
311     ACPI_TYPED_IDENTIFIER_TABLE *StructTable;
312     ACPI_IDENTIFIER_TABLE   *SpecialMacroTable;
313 
314 
315     switch (FileType)
316     {
317     case FILE_TYPE_SOURCE:
318 
319         Functions           = ConversionTable->SourceFunctions;
320         StringTable         = ConversionTable->SourceStringTable;
321         LineTable           = ConversionTable->SourceLineTable;
322         ConditionalTable    = ConversionTable->SourceConditionalTable;
323         StructTable         = ConversionTable->SourceStructTable;
324         SpecialMacroTable   = ConversionTable->SourceSpecialMacroTable;
325        break;
326 
327     case FILE_TYPE_HEADER:
328 
329         Functions           = ConversionTable->HeaderFunctions;
330         StringTable         = ConversionTable->HeaderStringTable;
331         LineTable           = ConversionTable->HeaderLineTable;
332         ConditionalTable    = ConversionTable->HeaderConditionalTable;
333         StructTable         = ConversionTable->HeaderStructTable;
334         SpecialMacroTable   = ConversionTable->HeaderSpecialMacroTable;
335         break;
336 
337     case FILE_TYPE_PATCH:
338 
339         Functions           = ConversionTable->PatchFunctions;
340         StringTable         = ConversionTable->PatchStringTable;
341         LineTable           = ConversionTable->PatchLineTable;
342         ConditionalTable    = ConversionTable->PatchConditionalTable;
343         StructTable         = ConversionTable->PatchStructTable;
344         SpecialMacroTable   = ConversionTable->PatchSpecialMacroTable;
345         break;
346 
347     default:
348 
349         printf ("Unknown file type, cannot process\n");
350         return;
351     }
352 
353 
354     Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs");
355     Gbl_Files++;
356     VERBOSE_PRINT (("Processing %u bytes\n",
357         (unsigned int) strlen (FileBuffer)));
358 
359     if (Gbl_Cleanup)
360     {
361         AsRemoveExtraLines (FileBuffer, Filename);
362         AsRemoveSpacesAfterPeriod (FileBuffer, Filename);
363     }
364 
365     if (ConversionTable->LowerCaseTable)
366     {
367         for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++)
368         {
369             AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier,
370                 FileBuffer);
371         }
372     }
373 
374     /* Process all the string replacements */
375 
376     if (StringTable)
377     {
378         for (i = 0; StringTable[i].Target; i++)
379         {
380             AsReplaceString (StringTable[i].Target, StringTable[i].Replacement,
381                 StringTable[i].Type, FileBuffer);
382         }
383     }
384 
385     if (LineTable)
386     {
387         for (i = 0; LineTable[i].Identifier; i++)
388         {
389             AsRemoveLine (FileBuffer, LineTable[i].Identifier);
390         }
391     }
392 
393     if (ConditionalTable)
394     {
395         for (i = 0; ConditionalTable[i].Identifier; i++)
396         {
397             AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier);
398         }
399     }
400 
401 #ifdef _OBSOLETE_FUNCTIONS
402     if (MacroTable)
403     {
404         for (i = 0; MacroTable[i].Identifier; i++)
405         {
406             AsRemoveMacro (FileBuffer, MacroTable[i].Identifier);
407         }
408     }
409 #endif
410 
411     if (StructTable)
412     {
413         for (i = 0; StructTable[i].Identifier; i++)
414         {
415             AsInsertPrefix (FileBuffer, StructTable[i].Identifier,
416                 StructTable[i].Type);
417         }
418     }
419 
420     if (SpecialMacroTable)
421     {
422         for (i = 0; SpecialMacroTable[i].Identifier; i++)
423         {
424             AsCleanupSpecialMacro (FileBuffer, SpecialMacroTable[i].Identifier);
425         }
426     }
427 
428     /* Process the function table */
429 
430     for (i = 0; i < 32; i++)
431     {
432         /* Decode the function bitmap */
433 
434         switch ((1 << i) & Functions)
435         {
436         case 0:
437 
438             /* This function not configured */
439             break;
440 
441         case CVT_COUNT_TABS:
442 
443             AsCountTabs (FileBuffer, Filename);
444             break;
445 
446         case CVT_COUNT_NON_ANSI_COMMENTS:
447 
448             AsCountNonAnsiComments (FileBuffer, Filename);
449             break;
450 
451         case CVT_CHECK_BRACES:
452 
453             AsCheckForBraces (FileBuffer, Filename);
454             break;
455 
456         case CVT_TRIM_LINES:
457 
458             AsTrimLines (FileBuffer, Filename);
459             break;
460 
461         case CVT_COUNT_LINES:
462 
463             AsCountSourceLines (FileBuffer, Filename);
464             break;
465 
466         case CVT_BRACES_ON_SAME_LINE:
467 
468             AsBracesOnSameLine (FileBuffer);
469             break;
470 
471         case CVT_MIXED_CASE_TO_UNDERSCORES:
472 
473             AsMixedCaseToUnderscores (FileBuffer, Filename);
474             break;
475 
476         case CVT_LOWER_CASE_IDENTIFIERS:
477 
478             AsLowerCaseIdentifiers (FileBuffer);
479             break;
480 
481         case CVT_REMOVE_DEBUG_MACROS:
482 
483             AsRemoveDebugMacros (FileBuffer);
484             break;
485 
486         case CVT_TRIM_WHITESPACE:
487 
488             AsTrimWhitespace (FileBuffer);
489             break;
490 
491         case CVT_REMOVE_EMPTY_BLOCKS:
492 
493             AsRemoveEmptyBlocks (FileBuffer, Filename);
494             break;
495 
496         case CVT_REDUCE_TYPEDEFS:
497 
498             AsReduceTypedefs (FileBuffer, "typedef union");
499             AsReduceTypedefs (FileBuffer, "typedef struct");
500             break;
501 
502         case CVT_SPACES_TO_TABS4:
503 
504             AsTabify4 (FileBuffer);
505             break;
506 
507         case CVT_SPACES_TO_TABS8:
508 
509             AsTabify8 (FileBuffer);
510             break;
511 
512         case CVT_COUNT_SHORTMULTILINE_COMMENTS:
513 
514 #ifdef ACPI_FUTURE_IMPLEMENTATION
515             AsTrimComments (FileBuffer, Filename);
516 #endif
517             break;
518 
519         default:
520 
521             printf ("Unknown conversion subfunction opcode\n");
522             break;
523         }
524     }
525 
526     if (ConversionTable->NewHeader)
527     {
528         AsReplaceHeader (FileBuffer, ConversionTable->NewHeader);
529     }
530 }
531 
532 
533 /******************************************************************************
534  *
535  * FUNCTION:    AsProcessOneFile
536  *
537  * DESCRIPTION: Process one source file. The file is opened, read entirely
538  *              into a buffer, converted, then written to a new file.
539  *
540  ******************************************************************************/
541 
542 ACPI_NATIVE_INT
543 AsProcessOneFile (
544     ACPI_CONVERSION_TABLE   *ConversionTable,
545     char                    *SourcePath,
546     char                    *TargetPath,
547     int                     MaxPathLength,
548     char                    *Filename,
549     ACPI_NATIVE_INT         FileType)
550 {
551     char                    *Pathname;
552     char                    *OutPathname = NULL;
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         free (Pathname);
579         return (-1);
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                 return (-1);
623             }
624 
625             strcpy (OutPathname, TargetPath);
626             if (SourcePath)
627             {
628                 strcat (OutPathname, "/");
629                 strcat (OutPathname, Filename);
630             }
631 
632             AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags);
633         }
634     }
635 
636     free (Gbl_FileBuffer);
637     free (Pathname);
638     if (OutPathname)
639     {
640         free (OutPathname);
641     }
642 
643     return (0);
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