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 ErrorExit; 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 783 ErrorExit: 784 785 fclose (File); 786 return (-1); 787 } 788 789 790 /****************************************************************************** 791 * 792 * FUNCTION: AsPutFile 793 * 794 * DESCRIPTION: Create a new output file and write the entire contents of the 795 * buffer to the new file. Buffer must be a zero terminated string 796 * 797 ******************************************************************************/ 798 799 int 800 AsPutFile ( 801 char *Pathname, 802 char *FileBuffer, 803 UINT32 SystemFlags) 804 { 805 FILE *File; 806 UINT32 FileSize; 807 size_t Actual; 808 int Status = 0; 809 810 811 /* Create the target file */ 812 813 if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS)) 814 { 815 /* Put back the CR before each LF */ 816 817 AsInsertCarriageReturns (FileBuffer); 818 } 819 820 File = fopen (Pathname, "w+b"); 821 if (!File) 822 { 823 perror ("Could not create destination file"); 824 printf ("Could not create destination file \"%s\"\n", Pathname); 825 return (-1); 826 } 827 828 /* Write the buffer to the file */ 829 830 FileSize = strlen (FileBuffer); 831 Actual = fwrite (FileBuffer, 1, FileSize, File); 832 if (Actual != FileSize) 833 { 834 printf ("Error writing output file \"%s\"\n", Pathname); 835 Status = -1; 836 } 837 838 fclose (File); 839 return (Status); 840 } 841