void LibClose (void) /* Write remaining data, close both files and copy the temp file to the old * filename */ { /* Do we have a temporary library? */ if (NewLib) { unsigned I; unsigned char Buf [4096]; size_t Count; /* Walk through the object file list, inserting exports into the * export list checking for duplicates. Copy any data that is still * in the old library into the new one. */ for (I = 0; I < CollCount (&ObjPool); ++I) { /* Get a pointer to the object */ ObjData* O = CollAtUnchecked (&ObjPool, I); /* Check exports, make global export table */ LibCheckExports (O); /* Copy data if needed */ if ((O->Flags & OBJ_HAVEDATA) == 0) { /* Data is still in the old library */ fseek (Lib, O->Start, SEEK_SET); O->Start = ftell (NewLib); LibCopyTo (Lib, O->Size); O->Flags |= OBJ_HAVEDATA; } } /* Write the index */ WriteIndex (); /* Write the updated header */ WriteHeader (); /* Close the file */ if (Lib && fclose (Lib) != 0) { Error ("Error closing library: %s", strerror (errno)); } /* Reopen the library and truncate it */ Lib = fopen (LibName, "wb"); if (Lib == 0) { Error ("Cannot open library `%s' for writing: %s", LibName, strerror (errno)); } /* Copy the new library to the new one */ fseek (NewLib, 0, SEEK_SET); while ((Count = fread (Buf, 1, sizeof (Buf), NewLib)) != 0) { if (fwrite (Buf, 1, Count, Lib) != Count) { Error ("Cannot write to `%s': %s", LibName, strerror (errno)); } } } /* Close both files */ if (Lib && fclose (Lib) != 0) { Error ("Problem closing `%s': %s", LibName, strerror (errno)); } if (NewLib && fclose (NewLib) != 0) { Error ("Problem closing temporary library file: %s", strerror (errno)); } }
void ObjAdd (const char* Name) /* Add an object file to the library */ { struct stat StatBuf; const char* Module; ObjHeader H; ObjData* O; /* Open the object file */ FILE* Obj = fopen (Name, "rb"); if (Obj == 0) { Error ("Could not open `%s': %s", Name, strerror (errno)); } /* Get the modification time of the object file. There a race condition * here, since we cannot use fileno() (non standard identifier in standard * header file), and therefore not fstat. When using stat with the * file name, there's a risk that the file was deleted and recreated * while it was open. Since mtime and size are only used to check * if a file has changed in the debugger, we will ignore this problem * here. */ if (FileStat (Name, &StatBuf) != 0) { Error ("Cannot stat object file `%s': %s", Name, strerror (errno)); } /* Read and check the header */ ObjReadHeader (Obj, &H, Name); /* Make a module name from the file name */ Module = GetModule (Name); /* Check if we already have a module with this name */ O = FindObjData (Module); if (O == 0) { /* Not found, create a new entry */ O = NewObjData (); } else { /* Found - check the file modification times of the internal copy * and the external one. */ if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) { Warning ("Replacing module `%s' by older version in library `%s'", O->Name, LibName); } /* Free data */ ClearObjData (O); } /* Initialize the object module data structure */ O->Name = xstrdup (Module); O->Flags = OBJ_HAVEDATA; O->MTime = StatBuf.st_mtime; O->Start = 0; /* Determine the file size. Note: Race condition here */ fseek (Obj, 0, SEEK_END); O->Size = ftell (Obj); /* Read the basic data from the object file */ ObjReadData (Obj, O); /* Copy the complete object data to the library file and update the * starting offset */ fseek (Obj, 0, SEEK_SET); O->Start = LibCopyTo (Obj, O->Size); /* Done, close the file (we read it only, so no error check) */ fclose (Obj); }