1 /****************************************************************************** 2 * 3 * Module Name: asfile - Main module for the acpi source processor utility 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 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 return (TRUE); 282 } 283 284 return (FALSE); 285 } 286 287 288 /****************************************************************************** 289 * 290 * FUNCTION: AsConvertFile 291 * 292 * DESCRIPTION: Perform the requested transforms on the file buffer (as 293 * determined by the ConversionTable and the FileType). 294 * 295 ******************************************************************************/ 296 297 void 298 AsConvertFile ( 299 ACPI_CONVERSION_TABLE *ConversionTable, 300 char *FileBuffer, 301 char *Filename, 302 ACPI_NATIVE_INT FileType) 303 { 304 UINT32 i; 305 UINT32 Functions; 306 ACPI_STRING_TABLE *StringTable; 307 ACPI_IDENTIFIER_TABLE *ConditionalTable; 308 ACPI_IDENTIFIER_TABLE *LineTable; 309 ACPI_TYPED_IDENTIFIER_TABLE *StructTable; 310 ACPI_IDENTIFIER_TABLE *SpecialMacroTable; 311 312 313 switch (FileType) 314 { 315 case FILE_TYPE_SOURCE: 316 317 Functions = ConversionTable->SourceFunctions; 318 StringTable = ConversionTable->SourceStringTable; 319 LineTable = ConversionTable->SourceLineTable; 320 ConditionalTable = ConversionTable->SourceConditionalTable; 321 StructTable = ConversionTable->SourceStructTable; 322 SpecialMacroTable = ConversionTable->SourceSpecialMacroTable; 323 break; 324 325 case FILE_TYPE_HEADER: 326 327 Functions = ConversionTable->HeaderFunctions; 328 StringTable = ConversionTable->HeaderStringTable; 329 LineTable = ConversionTable->HeaderLineTable; 330 ConditionalTable = ConversionTable->HeaderConditionalTable; 331 StructTable = ConversionTable->HeaderStructTable; 332 SpecialMacroTable = ConversionTable->HeaderSpecialMacroTable; 333 break; 334 335 case FILE_TYPE_PATCH: 336 337 Functions = ConversionTable->PatchFunctions; 338 StringTable = ConversionTable->PatchStringTable; 339 LineTable = ConversionTable->PatchLineTable; 340 ConditionalTable = ConversionTable->PatchConditionalTable; 341 StructTable = ConversionTable->PatchStructTable; 342 SpecialMacroTable = ConversionTable->PatchSpecialMacroTable; 343 break; 344 345 default: 346 347 printf ("Unknown file type, cannot process\n"); 348 return; 349 } 350 351 352 Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs"); 353 Gbl_Files++; 354 VERBOSE_PRINT (("Processing %u bytes\n", 355 (unsigned int) strlen (FileBuffer))); 356 357 if (Gbl_Cleanup) 358 { 359 AsRemoveExtraLines (FileBuffer, Filename); 360 AsRemoveSpacesAfterPeriod (FileBuffer, Filename); 361 } 362 363 if (ConversionTable->LowerCaseTable) 364 { 365 for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++) 366 { 367 AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier, 368 FileBuffer); 369 } 370 } 371 372 /* Process all the string replacements */ 373 374 if (StringTable) 375 { 376 for (i = 0; StringTable[i].Target; i++) 377 { 378 AsReplaceString (StringTable[i].Target, StringTable[i].Replacement, 379 StringTable[i].Type, FileBuffer); 380 } 381 } 382 383 if (LineTable) 384 { 385 for (i = 0; LineTable[i].Identifier; i++) 386 { 387 AsRemoveLine (FileBuffer, LineTable[i].Identifier); 388 } 389 } 390 391 if (ConditionalTable) 392 { 393 for (i = 0; ConditionalTable[i].Identifier; i++) 394 { 395 AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier); 396 } 397 } 398 399 #ifdef _OBSOLETE_FUNCTIONS 400 if (MacroTable) 401 { 402 for (i = 0; MacroTable[i].Identifier; i++) 403 { 404 AsRemoveMacro (FileBuffer, MacroTable[i].Identifier); 405 } 406 } 407 #endif 408 409 if (StructTable) 410 { 411 for (i = 0; StructTable[i].Identifier; i++) 412 { 413 AsInsertPrefix (FileBuffer, StructTable[i].Identifier, StructTable[i].Type); 414 } 415 } 416 417 if (SpecialMacroTable) 418 { 419 for (i = 0; SpecialMacroTable[i].Identifier; i++) 420 { 421 AsCleanupSpecialMacro (FileBuffer, SpecialMacroTable[i].Identifier); 422 } 423 } 424 425 /* Process the function table */ 426 427 for (i = 0; i < 32; i++) 428 { 429 /* Decode the function bitmap */ 430 431 switch ((1 << i) & Functions) 432 { 433 case 0: 434 435 /* This function not configured */ 436 break; 437 438 case CVT_COUNT_TABS: 439 440 AsCountTabs (FileBuffer, Filename); 441 break; 442 443 case CVT_COUNT_NON_ANSI_COMMENTS: 444 445 AsCountNonAnsiComments (FileBuffer, Filename); 446 break; 447 448 case CVT_CHECK_BRACES: 449 450 AsCheckForBraces (FileBuffer, Filename); 451 break; 452 453 case CVT_TRIM_LINES: 454 455 AsTrimLines (FileBuffer, Filename); 456 break; 457 458 case CVT_COUNT_LINES: 459 460 AsCountSourceLines (FileBuffer, Filename); 461 break; 462 463 case CVT_BRACES_ON_SAME_LINE: 464 465 AsBracesOnSameLine (FileBuffer); 466 break; 467 468 case CVT_MIXED_CASE_TO_UNDERSCORES: 469 470 AsMixedCaseToUnderscores (FileBuffer, Filename); 471 break; 472 473 case CVT_LOWER_CASE_IDENTIFIERS: 474 475 AsLowerCaseIdentifiers (FileBuffer); 476 break; 477 478 case CVT_REMOVE_DEBUG_MACROS: 479 480 AsRemoveDebugMacros (FileBuffer); 481 break; 482 483 case CVT_TRIM_WHITESPACE: 484 485 AsTrimWhitespace (FileBuffer); 486 break; 487 488 case CVT_REMOVE_EMPTY_BLOCKS: 489 490 AsRemoveEmptyBlocks (FileBuffer, Filename); 491 break; 492 493 case CVT_REDUCE_TYPEDEFS: 494 495 AsReduceTypedefs (FileBuffer, "typedef union"); 496 AsReduceTypedefs (FileBuffer, "typedef struct"); 497 break; 498 499 case CVT_SPACES_TO_TABS4: 500 501 AsTabify4 (FileBuffer); 502 break; 503 504 case CVT_SPACES_TO_TABS8: 505 506 AsTabify8 (FileBuffer); 507 break; 508 509 case CVT_COUNT_SHORTMULTILINE_COMMENTS: 510 511 #ifdef ACPI_FUTURE_IMPLEMENTATION 512 AsTrimComments (FileBuffer, Filename); 513 #endif 514 break; 515 516 default: 517 518 printf ("Unknown conversion subfunction opcode\n"); 519 break; 520 } 521 } 522 523 if (ConversionTable->NewHeader) 524 { 525 AsReplaceHeader (FileBuffer, ConversionTable->NewHeader); 526 } 527 } 528 529 530 /****************************************************************************** 531 * 532 * FUNCTION: AsProcessOneFile 533 * 534 * DESCRIPTION: Process one source file. The file is opened, read entirely 535 * into a buffer, converted, then written to a new file. 536 * 537 ******************************************************************************/ 538 539 ACPI_NATIVE_INT 540 AsProcessOneFile ( 541 ACPI_CONVERSION_TABLE *ConversionTable, 542 char *SourcePath, 543 char *TargetPath, 544 int MaxPathLength, 545 char *Filename, 546 ACPI_NATIVE_INT FileType) 547 { 548 char *Pathname; 549 char *OutPathname = NULL; 550 551 552 /* Allocate a file pathname buffer for both source and target */ 553 554 Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1); 555 if (!Pathname) 556 { 557 printf ("Could not allocate buffer for file pathnames\n"); 558 return (-1); 559 } 560 561 Gbl_FileType = FileType; 562 563 /* Generate the source pathname and read the file */ 564 565 if (SourcePath) 566 { 567 strcpy (Pathname, SourcePath); 568 strcat (Pathname, "/"); 569 } 570 571 strcat (Pathname, Filename); 572 573 if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize)) 574 { 575 return (-1); 576 } 577 578 Gbl_HeaderSize = 0; 579 if (strstr (Filename, ".asl")) 580 { 581 Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */ 582 } 583 else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE)) 584 { 585 Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */ 586 } 587 else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE)) 588 { 589 Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */ 590 } 591 592 /* Process the file in the buffer */ 593 594 Gbl_MadeChanges = FALSE; 595 if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds) 596 { 597 /* 598 * All lone LFs will be converted to CR/LF 599 * (when file is written, Windows version only) 600 */ 601 printf ("Converting lone linefeeds\n"); 602 Gbl_MadeChanges = TRUE; 603 } 604 605 AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType); 606 607 if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT)) 608 { 609 if (!(Gbl_Overwrite && !Gbl_MadeChanges)) 610 { 611 /* Generate the target pathname and write the file */ 612 613 OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1); 614 if (!OutPathname) 615 { 616 printf ("Could not allocate buffer for file pathnames\n"); 617 return (-1); 618 } 619 620 strcpy (OutPathname, TargetPath); 621 if (SourcePath) 622 { 623 strcat (OutPathname, "/"); 624 strcat (OutPathname, Filename); 625 } 626 627 AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags); 628 } 629 } 630 631 free (Gbl_FileBuffer); 632 free (Pathname); 633 if (OutPathname) 634 { 635 free (OutPathname); 636 } 637 638 return (0); 639 } 640 641 642 /****************************************************************************** 643 * 644 * FUNCTION: AsCheckForDirectory 645 * 646 * DESCRIPTION: Check if the current file is a valid directory. If not, 647 * construct the full pathname for the source and target paths. 648 * Checks for the dot and dot-dot files (they are ignored) 649 * 650 ******************************************************************************/ 651 652 ACPI_NATIVE_INT 653 AsCheckForDirectory ( 654 char *SourceDirPath, 655 char *TargetDirPath, 656 char *Filename, 657 char **SourcePath, 658 char **TargetPath) 659 { 660 char *SrcPath; 661 char *TgtPath; 662 663 664 if (!(strcmp (Filename, ".")) || 665 !(strcmp (Filename, ".."))) 666 { 667 return (-1); 668 } 669 670 SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1); 671 if (!SrcPath) 672 { 673 printf ("Could not allocate buffer for directory source pathname\n"); 674 return (-1); 675 } 676 677 TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1); 678 if (!TgtPath) 679 { 680 printf ("Could not allocate buffer for directory target pathname\n"); 681 free (SrcPath); 682 return (-1); 683 } 684 685 strcpy (SrcPath, SourceDirPath); 686 strcat (SrcPath, "/"); 687 strcat (SrcPath, Filename); 688 689 strcpy (TgtPath, TargetDirPath); 690 strcat (TgtPath, "/"); 691 strcat (TgtPath, Filename); 692 693 *SourcePath = SrcPath; 694 *TargetPath = TgtPath; 695 return (0); 696 } 697 698 699 /****************************************************************************** 700 * 701 * FUNCTION: AsGetFile 702 * 703 * DESCRIPTION: Open a file and read it entirely into a an allocated buffer 704 * 705 ******************************************************************************/ 706 707 int 708 AsGetFile ( 709 char *Filename, 710 char **FileBuffer, 711 UINT32 *FileSize) 712 { 713 FILE *File; 714 UINT32 Size; 715 char *Buffer; 716 size_t Actual; 717 718 719 /* Binary mode leaves CR/LF pairs */ 720 721 File = fopen (Filename, "rb"); 722 if (!File) 723 { 724 printf ("Could not open file %s\n", Filename); 725 return (-1); 726 } 727 728 /* Need file size to allocate a buffer */ 729 730 Size = CmGetFileSize (File); 731 if (Size == ACPI_UINT32_MAX) 732 { 733 printf ("Could not get file size for %s\n", Filename); 734 goto ErrorExit; 735 } 736 737 /* 738 * Create a buffer for the entire file 739 * Add plenty extra buffer to accommodate string replacements 740 */ 741 Gbl_TotalSize += Size; 742 743 Buffer = calloc (Size * 2, 1); 744 if (!Buffer) 745 { 746 printf ("Could not allocate buffer of size %u\n", Size * 2); 747 goto ErrorExit; 748 } 749 750 /* Read the entire file */ 751 752 Actual = fread (Buffer, 1, Size, File); 753 if (Actual != Size) 754 { 755 printf ("Could not read the input file %s (%u bytes)\n", 756 Filename, Size); 757 goto ErrorExit; 758 } 759 760 Buffer [Size] = 0; /* Null terminate the buffer */ 761 fclose (File); 762 763 /* Check for unix contamination */ 764 765 Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer); 766 767 /* 768 * Convert all CR/LF pairs to LF only. We do this locally so that 769 * this code is portable across operating systems. 770 */ 771 AsConvertToLineFeeds (Buffer); 772 773 *FileBuffer = Buffer; 774 *FileSize = Size; 775 return (0); 776 777 778 ErrorExit: 779 780 fclose (File); 781 return (-1); 782 } 783 784 785 /****************************************************************************** 786 * 787 * FUNCTION: AsPutFile 788 * 789 * DESCRIPTION: Create a new output file and write the entire contents of the 790 * buffer to the new file. Buffer must be a zero terminated string 791 * 792 ******************************************************************************/ 793 794 int 795 AsPutFile ( 796 char *Pathname, 797 char *FileBuffer, 798 UINT32 SystemFlags) 799 { 800 FILE *File; 801 UINT32 FileSize; 802 size_t Actual; 803 int Status = 0; 804 805 806 /* Create the target file */ 807 808 if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS)) 809 { 810 /* Put back the CR before each LF */ 811 812 AsInsertCarriageReturns (FileBuffer); 813 } 814 815 File = fopen (Pathname, "w+b"); 816 if (!File) 817 { 818 perror ("Could not create destination file"); 819 printf ("Could not create destination file \"%s\"\n", Pathname); 820 return (-1); 821 } 822 823 /* Write the buffer to the file */ 824 825 FileSize = strlen (FileBuffer); 826 Actual = fwrite (FileBuffer, 1, FileSize, File); 827 if (Actual != FileSize) 828 { 829 printf ("Error writing output file \"%s\"\n", Pathname); 830 Status = -1; 831 } 832 833 fclose (File); 834 return (Status); 835 } 836