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