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