1 /****************************************************************************** 2 * 3 * Module Name: asfile - Main module for the acpi source processor utility 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 AsStrlwr (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_IDENTIFIER_TABLE *MacroTable; 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 MacroTable = ConversionTable->SourceMacroTable; 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 MacroTable = ConversionTable->HeaderMacroTable; 334 StructTable = ConversionTable->HeaderStructTable; 335 SpecialMacroTable = ConversionTable->HeaderSpecialMacroTable; 336 break; 337 338 case FILE_TYPE_PATCH: 339 340 Functions = ConversionTable->PatchFunctions; 341 StringTable = ConversionTable->PatchStringTable; 342 LineTable = ConversionTable->PatchLineTable; 343 ConditionalTable = ConversionTable->PatchConditionalTable; 344 MacroTable = ConversionTable->PatchMacroTable; 345 StructTable = ConversionTable->PatchStructTable; 346 SpecialMacroTable = ConversionTable->PatchSpecialMacroTable; 347 break; 348 349 default: 350 351 printf ("Unknown file type, cannot process\n"); 352 return; 353 } 354 355 356 Gbl_StructDefs = strstr (FileBuffer, "/* acpisrc:StructDefs"); 357 Gbl_Files++; 358 VERBOSE_PRINT (("Processing %u bytes\n", 359 (unsigned int) strlen (FileBuffer))); 360 361 if (Gbl_Cleanup) 362 { 363 AsRemoveExtraLines (FileBuffer, Filename); 364 AsRemoveSpacesAfterPeriod (FileBuffer, Filename); 365 } 366 367 if (ConversionTable->LowerCaseTable) 368 { 369 for (i = 0; ConversionTable->LowerCaseTable[i].Identifier; i++) 370 { 371 AsLowerCaseString (ConversionTable->LowerCaseTable[i].Identifier, 372 FileBuffer); 373 } 374 } 375 376 /* Process all the string replacements */ 377 378 if (StringTable) 379 { 380 for (i = 0; StringTable[i].Target; i++) 381 { 382 AsReplaceString (StringTable[i].Target, StringTable[i].Replacement, 383 StringTable[i].Type, FileBuffer); 384 } 385 } 386 387 if (LineTable) 388 { 389 for (i = 0; LineTable[i].Identifier; i++) 390 { 391 AsRemoveLine (FileBuffer, LineTable[i].Identifier); 392 } 393 } 394 395 if (ConditionalTable) 396 { 397 for (i = 0; ConditionalTable[i].Identifier; i++) 398 { 399 AsRemoveConditionalCompile (FileBuffer, ConditionalTable[i].Identifier); 400 } 401 } 402 403 if (MacroTable) 404 { 405 for (i = 0; MacroTable[i].Identifier; i++) 406 { 407 AsRemoveMacro (FileBuffer, MacroTable[i].Identifier); 408 } 409 } 410 411 if (StructTable) 412 { 413 for (i = 0; StructTable[i].Identifier; i++) 414 { 415 AsInsertPrefix (FileBuffer, StructTable[i].Identifier, 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 = NULL; 552 553 554 /* Allocate a file pathname buffer for both source and target */ 555 556 Pathname = calloc (MaxPathLength + strlen (Filename) + 2, 1); 557 if (!Pathname) 558 { 559 printf ("Could not allocate buffer for file pathnames\n"); 560 return (-1); 561 } 562 563 Gbl_FileType = FileType; 564 565 /* Generate the source pathname and read the file */ 566 567 if (SourcePath) 568 { 569 strcpy (Pathname, SourcePath); 570 strcat (Pathname, "/"); 571 } 572 573 strcat (Pathname, Filename); 574 575 if (AsGetFile (Pathname, &Gbl_FileBuffer, &Gbl_FileSize)) 576 { 577 return (-1); 578 } 579 580 Gbl_HeaderSize = 0; 581 if (strstr (Filename, ".asl")) 582 { 583 Gbl_HeaderSize = LINES_IN_ASL_HEADER; /* Lines in default ASL header */ 584 } 585 else if (strstr (Gbl_FileBuffer, LEGAL_HEADER_SIGNATURE)) 586 { 587 Gbl_HeaderSize = LINES_IN_LEGAL_HEADER; /* Normal C file and H header */ 588 } 589 else if (strstr (Gbl_FileBuffer, LINUX_HEADER_SIGNATURE)) 590 { 591 Gbl_HeaderSize = LINES_IN_LINUX_HEADER; /* Linuxized C file and H header */ 592 } 593 594 /* Process the file in the buffer */ 595 596 Gbl_MadeChanges = FALSE; 597 if (!Gbl_IgnoreLoneLineFeeds && Gbl_HasLoneLineFeeds) 598 { 599 /* 600 * All lone LFs will be converted to CR/LF 601 * (when file is written, Windows version only) 602 */ 603 printf ("Converting lone linefeeds\n"); 604 Gbl_MadeChanges = TRUE; 605 } 606 607 AsConvertFile (ConversionTable, Gbl_FileBuffer, Pathname, FileType); 608 609 if (!(ConversionTable->Flags & FLG_NO_FILE_OUTPUT)) 610 { 611 if (!(Gbl_Overwrite && !Gbl_MadeChanges)) 612 { 613 /* Generate the target pathname and write the file */ 614 615 OutPathname = calloc (MaxPathLength + strlen (Filename) + 2 + strlen (TargetPath), 1); 616 if (!OutPathname) 617 { 618 printf ("Could not allocate buffer for file pathnames\n"); 619 return (-1); 620 } 621 622 strcpy (OutPathname, TargetPath); 623 if (SourcePath) 624 { 625 strcat (OutPathname, "/"); 626 strcat (OutPathname, Filename); 627 } 628 629 AsPutFile (OutPathname, Gbl_FileBuffer, ConversionTable->Flags); 630 } 631 } 632 633 free (Gbl_FileBuffer); 634 free (Pathname); 635 if (OutPathname) 636 { 637 free (OutPathname); 638 } 639 640 return (0); 641 } 642 643 644 /****************************************************************************** 645 * 646 * FUNCTION: AsCheckForDirectory 647 * 648 * DESCRIPTION: Check if the current file is a valid directory. If not, 649 * construct the full pathname for the source and target paths. 650 * Checks for the dot and dot-dot files (they are ignored) 651 * 652 ******************************************************************************/ 653 654 ACPI_NATIVE_INT 655 AsCheckForDirectory ( 656 char *SourceDirPath, 657 char *TargetDirPath, 658 char *Filename, 659 char **SourcePath, 660 char **TargetPath) 661 { 662 char *SrcPath; 663 char *TgtPath; 664 665 666 if (!(strcmp (Filename, ".")) || 667 !(strcmp (Filename, ".."))) 668 { 669 return (-1); 670 } 671 672 SrcPath = calloc (strlen (SourceDirPath) + strlen (Filename) + 2, 1); 673 if (!SrcPath) 674 { 675 printf ("Could not allocate buffer for directory source pathname\n"); 676 return (-1); 677 } 678 679 TgtPath = calloc (strlen (TargetDirPath) + strlen (Filename) + 2, 1); 680 if (!TgtPath) 681 { 682 printf ("Could not allocate buffer for directory target pathname\n"); 683 free (SrcPath); 684 return (-1); 685 } 686 687 strcpy (SrcPath, SourceDirPath); 688 strcat (SrcPath, "/"); 689 strcat (SrcPath, Filename); 690 691 strcpy (TgtPath, TargetDirPath); 692 strcat (TgtPath, "/"); 693 strcat (TgtPath, Filename); 694 695 *SourcePath = SrcPath; 696 *TargetPath = TgtPath; 697 return (0); 698 } 699 700 701 /****************************************************************************** 702 * 703 * FUNCTION: AsGetFile 704 * 705 * DESCRIPTION: Open a file and read it entirely into a an allocated buffer 706 * 707 ******************************************************************************/ 708 709 int 710 AsGetFile ( 711 char *Filename, 712 char **FileBuffer, 713 UINT32 *FileSize) 714 { 715 FILE *File; 716 UINT32 Size; 717 char *Buffer; 718 size_t Actual; 719 720 721 /* Binary mode leaves CR/LF pairs */ 722 723 File = fopen (Filename, "rb"); 724 if (!File) 725 { 726 printf ("Could not open file %s\n", Filename); 727 return (-1); 728 } 729 730 /* Need file size to allocate a buffer */ 731 732 Size = CmGetFileSize (File); 733 if (Size == ACPI_UINT32_MAX) 734 { 735 printf ("Could not get file size for %s\n", Filename); 736 goto ErrorExit; 737 } 738 739 /* 740 * Create a buffer for the entire file 741 * Add plenty extra buffer to accommodate string replacements 742 */ 743 Gbl_TotalSize += Size; 744 745 Buffer = calloc (Size * 2, 1); 746 if (!Buffer) 747 { 748 printf ("Could not allocate buffer of size %u\n", Size * 2); 749 goto ErrorExit; 750 } 751 752 /* Read the entire file */ 753 754 Actual = fread (Buffer, 1, Size, File); 755 if (Actual != Size) 756 { 757 printf ("Could not read the input file %s (%u bytes)\n", 758 Filename, Size); 759 goto ErrorExit; 760 } 761 762 Buffer [Size] = 0; /* Null terminate the buffer */ 763 fclose (File); 764 765 /* Check for unix contamination */ 766 767 Gbl_HasLoneLineFeeds = AsDetectLoneLineFeeds (Filename, Buffer); 768 769 /* 770 * Convert all CR/LF pairs to LF only. We do this locally so that 771 * this code is portable across operating systems. 772 */ 773 AsConvertToLineFeeds (Buffer); 774 775 *FileBuffer = Buffer; 776 *FileSize = Size; 777 return (0); 778 779 780 ErrorExit: 781 782 fclose (File); 783 return (-1); 784 } 785 786 787 /****************************************************************************** 788 * 789 * FUNCTION: AsPutFile 790 * 791 * DESCRIPTION: Create a new output file and write the entire contents of the 792 * buffer to the new file. Buffer must be a zero terminated string 793 * 794 ******************************************************************************/ 795 796 int 797 AsPutFile ( 798 char *Pathname, 799 char *FileBuffer, 800 UINT32 SystemFlags) 801 { 802 FILE *File; 803 UINT32 FileSize; 804 size_t Actual; 805 int Status = 0; 806 807 808 /* Create the target file */ 809 810 if (!(SystemFlags & FLG_NO_CARRIAGE_RETURNS)) 811 { 812 /* Put back the CR before each LF */ 813 814 AsInsertCarriageReturns (FileBuffer); 815 } 816 817 File = fopen (Pathname, "w+b"); 818 if (!File) 819 { 820 perror ("Could not create destination file"); 821 printf ("Could not create destination file \"%s\"\n", Pathname); 822 return (-1); 823 } 824 825 /* Write the buffer to the file */ 826 827 FileSize = strlen (FileBuffer); 828 Actual = fwrite (FileBuffer, 1, FileSize, File); 829 if (Actual != FileSize) 830 { 831 printf ("Error writing output file \"%s\"\n", Pathname); 832 Status = -1; 833 } 834 835 fclose (File); 836 return (Status); 837 } 838