1 /*****************************************************************************/
5 /* Object file handling for the ar65 archiver */
9 /* (C) 1998 Ullrich von Bassewitz */
11 /* D-70597 Stuttgart */
12 /* EMail: uz@musoftware.de */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
38 #if defined(__WATCOMC__) || defined(_MSC_VER)
39 /* The Windows compilers have the file in the wrong directory */
40 # include <sys/utime.h>
42 # include <sys/types.h> /* FreeBSD needs this */
48 #include "../common/xmalloc.h"
58 /*****************************************************************************/
60 /*****************************************************************************/
64 static const char* GetModule (const char* Name)
65 /* Get a module name from the file name */
67 /* Make a module name from the file name */
68 const char* Module = Name + strlen (Name);
69 while (Module > Name) {
71 if (*Module == '/' || *Module == '\\') {
77 Error ("Cannot make module name from `%s'", Name);
84 void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
85 /* Read the header of the object file checking the signature */
87 H->Magic = Read32 (Obj);
88 if (H->Magic != OBJ_MAGIC) {
89 Error ("`%s' is not an object file", Name);
91 H->Version = Read16 (Obj);
92 if (H->Version != OBJ_VERSION) {
93 Error ("Object file `%s' has wrong version", Name);
95 H->Flags = Read16 (Obj);
96 H->OptionOffs = Read32 (Obj);
97 H->OptionSize = Read32 (Obj);
98 H->FileOffs = Read32 (Obj);
99 H->FileSize = Read32 (Obj);
100 H->SegOffs = Read32 (Obj);
101 H->SegSize = Read32 (Obj);
102 H->ImportOffs = Read32 (Obj);
103 H->ImportSize = Read32 (Obj);
104 H->ExportOffs = Read32 (Obj);
105 H->ExportSize = Read32 (Obj);
106 H->DbgSymOffs = Read32 (Obj);
107 H->DbgSymSize = Read32 (Obj);
112 void ObjWriteHeader (FILE* Obj, ObjHeader* H)
113 /* Write the header of the object file */
115 Write32 (Obj, H->Magic);
116 Write16 (Obj, H->Version);
117 Write16 (Obj, H->Flags);
118 Write32 (Obj, H->OptionOffs);
119 Write32 (Obj, H->OptionSize);
120 Write32 (Obj, H->FileOffs);
121 Write32 (Obj, H->FileSize);
122 Write32 (Obj, H->SegOffs);
123 Write32 (Obj, H->SegSize);
124 Write32 (Obj, H->ImportOffs);
125 Write32 (Obj, H->ImportSize);
126 Write32 (Obj, H->ExportOffs);
127 Write32 (Obj, H->ExportSize);
128 Write32 (Obj, H->DbgSymOffs);
129 Write32 (Obj, H->DbgSymSize);
134 void ObjAdd (const char* Name)
135 /* Add an object file to the library */
142 /* Open the object file */
143 FILE* Obj = fopen (Name, "rb");
145 Error ("Could not open `%s': %s", Name, strerror (errno));
148 /* Get the modification time of the object file */
149 if (fstat (fileno (Obj), &StatBuf) != 0) {
150 Error ("Cannot stat object file `%s': %s", Name, strerror (errno));
153 /* Read and check the header */
154 ObjReadHeader (Obj, &H, Name);
156 /* Make a module name from the file name */
157 Module = GetModule (Name);
159 /* Check if we already have a module with this name */
160 O = FindObjData (Module);
162 /* Not found, create a new entry */
165 /* Found - check the file modification times of the internal copy
166 * and the external one.
168 if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
169 Warning ("Replacing module `%s' by older version", O->Name);
173 /* Initialize the object module data structure */
174 O->Name = xstrdup (Module);
175 O->Flags = OBJ_HAVEDATA;
176 O->MTime = StatBuf.st_mtime;
177 O->ImportSize = H.ImportSize;
178 O->Imports = xmalloc (O->ImportSize);
179 O->ExportSize = H.ExportSize;
180 O->Exports = xmalloc (O->ExportSize);
182 /* Read imports and exports */
183 fseek (Obj, H.ImportOffs, SEEK_SET);
184 ReadData (Obj, O->Imports, O->ImportSize);
185 fseek (Obj, H.ExportOffs, SEEK_SET);
186 ReadData (Obj, O->Exports, O->ExportSize);
188 /* Skip the object file header */
189 O->Start = ftell (NewLib);
190 fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
192 /* Copy the remaining sections */
193 fseek (Obj, H.DbgSymOffs, SEEK_SET);
194 H.DbgSymOffs = LibCopyTo (Obj, H.DbgSymSize) - O->Start;
195 fseek (Obj, H.OptionOffs, SEEK_SET);
196 H.OptionOffs = LibCopyTo (Obj, H.OptionSize) - O->Start;
197 fseek (Obj, H.SegOffs, SEEK_SET);
198 H.SegOffs = LibCopyTo (Obj, H.SegSize) - O->Start;
199 fseek (Obj, H.FileOffs, SEEK_SET);
200 H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
202 /* Calculate the amount of data written */
203 O->Size = ftell (NewLib) - O->Start;
205 /* Clear the remaining header fields */
206 H.ImportOffs = H.ImportSize = 0;
207 H.ExportOffs = H.ExportSize = 0;
209 /* Seek back and write the updated header */
210 fseek (NewLib, O->Start, SEEK_SET);
211 ObjWriteHeader (NewLib, &H);
213 /* Now seek again to end of file */
214 fseek (NewLib, 0, SEEK_END);
216 /* Done, close the file (we read it only, so no error check) */
222 void ObjExtract (const char* Name)
223 /* Extract a module from the library */
225 unsigned long ImportStart;
226 unsigned long ExportStart;
232 /* Make a module name from the file name */
233 const char* Module = GetModule (Name);
235 /* Try to find the module in the library */
236 ObjData* O = FindObjData (Module);
238 /* Bail out if the module does not exist */
240 Error ("Module `%s' not found in library", Module);
243 /* Open the output file */
244 Obj = fopen (Name, "w+b");
246 Error ("Cannot open target file `%s': %s", Name, strerror (errno));
249 /* Copy the first four segments including the header to the new file */
250 LibCopyFrom (O->Start, O->Size, Obj);
252 /* Write imports and exports */
253 ImportStart = ftell (Obj);
254 WriteData (Obj, O->Imports, O->ImportSize);
255 ExportStart = ftell (Obj);
256 WriteData (Obj, O->Exports, O->ExportSize);
258 /* Seek back and read the header */
259 fseek (Obj, 0, SEEK_SET);
260 ObjReadHeader (Obj, &H, Name);
262 /* Update the header fields */
263 H.ImportOffs = ImportStart;
264 H.ImportSize = O->ImportSize;
265 H.ExportOffs = ExportStart;
266 H.ExportSize = O->ExportSize;
268 /* Write the changed header */
269 fseek (Obj, 0, SEEK_SET);
270 ObjWriteHeader (Obj, &H);
273 if (fclose (Obj) != 0) {
274 Error ("Problem closing object file `%s': %s", Name, strerror (errno));
277 /* Set access and modification time */
279 U.modtime = O->MTime;
280 if (utime (Name, &U) != 0) {
281 Error ("Cannot set mod time on `%s': %s", Name, strerror (errno));