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 /*****************************************************************************/
39 /* Watcom has the file in the wrong directory */
40 # include <sys/utime.h>
42 # include <sys/types.h> /* FreeBSD needs this */
57 /*****************************************************************************/
59 /*****************************************************************************/
63 static const char* GetModule (const char* Name)
64 /* Get a module name from the file name */
66 /* Make a module name from the file name */
67 const char* Module = Name + strlen (Name);
68 while (Module > Name) {
70 if (*Module == '/' || *Module == '\\') {
76 Error ("Cannot make module name from `%s'", Name);
83 void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
84 /* Read the header of the object file checking the signature */
86 H->Magic = Read32 (Obj);
87 if (H->Magic != OBJ_MAGIC) {
88 Error ("`%s' is not an object file", Name);
90 H->Version = Read16 (Obj);
91 if (H->Version != OBJ_VERSION) {
92 Error ("Object file `%s' has wrong version", Name);
94 H->Flags = Read16 (Obj);
95 H->OptionOffs = Read32 (Obj);
96 H->OptionSize = Read32 (Obj);
97 H->FileOffs = Read32 (Obj);
98 H->FileSize = Read32 (Obj);
99 H->SegOffs = Read32 (Obj);
100 H->SegSize = Read32 (Obj);
101 H->ImportOffs = Read32 (Obj);
102 H->ImportSize = Read32 (Obj);
103 H->ExportOffs = Read32 (Obj);
104 H->ExportSize = Read32 (Obj);
105 H->DbgSymOffs = Read32 (Obj);
106 H->DbgSymSize = Read32 (Obj);
111 void ObjWriteHeader (FILE* Obj, ObjHeader* H)
112 /* Write the header of the object file */
114 Write32 (Obj, H->Magic);
115 Write16 (Obj, H->Version);
116 Write16 (Obj, H->Flags);
117 Write32 (Obj, H->OptionOffs);
118 Write32 (Obj, H->OptionSize);
119 Write32 (Obj, H->FileOffs);
120 Write32 (Obj, H->FileSize);
121 Write32 (Obj, H->SegOffs);
122 Write32 (Obj, H->SegSize);
123 Write32 (Obj, H->ImportOffs);
124 Write32 (Obj, H->ImportSize);
125 Write32 (Obj, H->ExportOffs);
126 Write32 (Obj, H->ExportSize);
127 Write32 (Obj, H->DbgSymOffs);
128 Write32 (Obj, H->DbgSymSize);
133 void ObjAdd (const char* Name)
134 /* Add an object file to the library */
141 /* Open the object file */
142 FILE* Obj = fopen (Name, "rb");
144 Error ("Could not open `%s': %s", Name, strerror (errno));
147 /* Get the modification time of the object file */
148 if (fstat (fileno (Obj), &StatBuf) != 0) {
149 Error ("Cannot stat object file `%s': %s", Name, strerror (errno));
152 /* Read and check the header */
153 ObjReadHeader (Obj, &H, Name);
155 /* Make a module name from the file name */
156 Module = GetModule (Name);
158 /* Check if we already have a module with this name */
159 O = FindObjData (Module);
161 /* Not found, create a new entry */
164 /* Found - check the file modification times of the internal copy
165 * and the external one.
167 if (difftime ((time_t)O->MTime, StatBuf.st_mtime) > 0.0) {
168 Warning ("Replacing module `%s' by older version", O->Name);
172 /* Initialize the object module data structure */
173 O->Name = StrDup (Module);
174 O->Flags = OBJ_HAVEDATA;
175 O->MTime = StatBuf.st_mtime;
176 O->ImportSize = H.ImportSize;
177 O->Imports = Xmalloc (O->ImportSize);
178 O->ExportSize = H.ExportSize;
179 O->Exports = Xmalloc (O->ExportSize);
181 /* Read imports and exports */
182 fseek (Obj, H.ImportOffs, SEEK_SET);
183 ReadData (Obj, O->Imports, O->ImportSize);
184 fseek (Obj, H.ExportOffs, SEEK_SET);
185 ReadData (Obj, O->Exports, O->ExportSize);
187 /* Skip the object file header */
188 O->Start = ftell (NewLib);
189 fseek (NewLib, OBJ_HDR_SIZE, SEEK_CUR);
191 /* Copy the remaining sections */
192 fseek (Obj, H.DbgSymOffs, SEEK_SET);
193 H.DbgSymOffs = LibCopyTo (Obj, H.DbgSymSize) - O->Start;
194 fseek (Obj, H.OptionOffs, SEEK_SET);
195 H.OptionOffs = LibCopyTo (Obj, H.OptionSize) - O->Start;
196 fseek (Obj, H.SegOffs, SEEK_SET);
197 H.SegOffs = LibCopyTo (Obj, H.SegSize) - O->Start;
198 fseek (Obj, H.FileOffs, SEEK_SET);
199 H.FileOffs = LibCopyTo (Obj, H.FileSize) - O->Start;
201 /* Calculate the amount of data written */
202 O->Size = ftell (NewLib) - O->Start;
204 /* Clear the remaining header fields */
205 H.ImportOffs = H.ImportSize = 0;
206 H.ExportOffs = H.ExportSize = 0;
208 /* Seek back and write the updated header */
209 fseek (NewLib, O->Start, SEEK_SET);
210 ObjWriteHeader (NewLib, &H);
212 /* Now seek again to end of file */
213 fseek (NewLib, 0, SEEK_END);
215 /* Done, close the file (we read it only, so no error check) */
221 void ObjExtract (const char* Name)
222 /* Extract a module from the library */
224 unsigned long ImportStart;
225 unsigned long ExportStart;
231 /* Make a module name from the file name */
232 const char* Module = GetModule (Name);
234 /* Try to find the module in the library */
235 ObjData* O = FindObjData (Module);
237 /* Bail out if the module does not exist */
239 Error ("Module `%s' not found in library", Module);
242 /* Open the output file */
243 Obj = fopen (Name, "w+b");
245 Error ("Cannot open target file `%s': %s", Name, strerror (errno));
248 /* Copy the first four segments including the header to the new file */
249 LibCopyFrom (O->Start, O->Size, Obj);
251 /* Write imports and exports */
252 ImportStart = ftell (Obj);
253 WriteData (Obj, O->Imports, O->ImportSize);
254 ExportStart = ftell (Obj);
255 WriteData (Obj, O->Exports, O->ExportSize);
257 /* Seek back and read the header */
258 fseek (Obj, 0, SEEK_SET);
259 ObjReadHeader (Obj, &H, Name);
261 /* Update the header fields */
262 H.ImportOffs = ImportStart;
263 H.ImportSize = O->ImportSize;
264 H.ExportOffs = ExportStart;
265 H.ExportSize = O->ExportSize;
267 /* Write the changed header */
268 fseek (Obj, 0, SEEK_SET);
269 ObjWriteHeader (Obj, &H);
272 if (fclose (Obj) != 0) {
273 Error ("Problem closing object file `%s': %s", Name, strerror (errno));
276 /* Set access and modification time */
278 U.modtime = O->MTime;
279 if (utime (Name, &U) != 0) {
280 Error ("Cannot set mod time on `%s': %s", Name, strerror (errno));