Now full of documentation. Yum Yum.
[platform/upstream/binutils.git] / bfd / opncls.c
1 /* opncls.c -- open and close a bfd. */
2
3 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Diddler.
6
7 BFD is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 1, or (at your option)
10 any later version.
11
12 BFD is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with BFD; see the file COPYING.  If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 /* $Id$ */
22
23 #include <sysdep.h>
24 #include "bfd.h"
25 #include "libbfd.h"
26
27 extern void bfd_cache_init();
28 FILE *bfd_open_file();
29
30 /* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
31    if we do that we can't use fcntl.  */
32 \f
33 /** Locking 
34
35    Locking is loosely controlled by the preprocessor variable
36    BFD_LOCKS.  I say loosely because Unix barely understands locking
37    -- at least in BSD it doesn't affect programs which don't
38    explicitly use it!  That is to say it's practically useless, though
39    if everyone uses this library you'll be OK.
40
41    From among the many and varied lock facilities available, (none of
42    which, of course, knows about any other) we use the fcntl locks,
43    because they're Posix.
44
45    The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
46    exists is because of locking.  When we do output, we lock the
47    filename file for output, then open a temporary file which does not
48    actually get its correct filename until closing time.  This is
49    safest, but requires the asymmetry in read and write entry points.
50
51    Perhaps, since unix has so many different kinds of locking anyway,
52    we should use the emacs lock scheme?... */
53
54 #define obstack_chunk_alloc malloc
55 #define obstack_chunk_free free
56
57 /* Return a new BFD.  All BFD's are allocated through this routine.  */
58
59 bfd *new_bfd()
60 {
61   bfd *nbfd;
62
63   nbfd = (bfd *)zalloc (sizeof (bfd));
64   if (!nbfd)
65     return 0;
66
67   obstack_begin((PTR)&nbfd->memory, 128);
68   
69   nbfd->direction = no_direction;
70   nbfd->iostream = NULL;
71   nbfd->where = 0;
72   nbfd->sections = (asection *)NULL;
73   nbfd->format = bfd_unknown;
74   nbfd->my_archive = (bfd *)NULL;
75   nbfd->origin = 0;                                
76   nbfd->opened_once = false;
77   nbfd->output_has_begun = false;
78   nbfd->section_count = 0;
79   nbfd->usrdata = (PTR)NULL;
80   nbfd->sections = (asection *)NULL;
81   nbfd->cacheable = false;
82   nbfd->flags = NO_FLAGS;
83   nbfd->mtime_set = 0;
84   return nbfd;
85 }
86
87 /* Allocate a new BFD as a member of archive OBFD.  */
88
89 bfd *new_bfd_contained_in(obfd)
90 bfd *obfd;
91 {
92         bfd *nbfd = new_bfd();
93         nbfd->xvec = obfd->xvec;
94         nbfd->my_archive = obfd;
95         nbfd->direction = read_direction;
96         return nbfd;
97 }
98
99 /*doc*
100 @section Opening and Closing BFDs
101
102 */
103 /*proto*
104 *i bfd_openr
105 Opens the file supplied (using fopen) with the target supplied, it
106 returns a pointer to the created bfd.
107
108 If NULL is returned then an error has occured.
109 Possible errors are no_memory, invalid_target or system_call error.
110 *; PROTO(bfd*, bfd_openr, (CONST char *filename,CONST char*target));
111 *-*/
112
113 bfd *
114 DEFUN(bfd_openr, (filename, target),
115       CONST char *filename AND
116       CONST char *target)
117 {
118   bfd *nbfd;
119   bfd_target *target_vec;
120
121   nbfd = new_bfd();
122   if (nbfd == NULL) {
123     bfd_error = no_memory;
124     return NULL;
125   }
126
127   target_vec = bfd_find_target (target, nbfd);
128   if (target_vec == NULL) {
129     bfd_error = invalid_target;
130     return NULL;
131   }
132
133   nbfd->filename = filename;
134   nbfd->direction = read_direction; 
135
136   if (bfd_open_file (nbfd) == NULL) {
137     bfd_error = system_call_error;      /* File didn't exist, or some such */
138     bfd_release(nbfd,0);
139     return NULL;
140   }
141   return nbfd;
142 }
143
144
145 /* Don't try to `optimize' this function:
146
147    o - We lock using stack space so that interrupting the locking
148        won't cause a storage leak.
149    o - We open the file stream last, since we don't want to have to
150        close it if anything goes wrong.  Closing the stream means closing
151        the file descriptor too, even though we didn't open it.
152  */
153 /*proto*
154 *i bfd_fdopenr
155 bfd_fdopenr is to bfd_fopenr much like  fdopen is to fopen. It opens a bfd on
156 a file already described by the @var{fd} supplied. 
157
158 Possible errors are no_memory, invalid_target and system_call error.
159 *;  PROTO(bfd *, bfd_fdopenr,
160     (CONST char *filename, CONST char *target, int fd));
161 *-*/
162
163 bfd *
164 DEFUN(bfd_fdopenr,(filename, target, fd),
165       CONST char *filename AND
166       CONST char *target AND
167       int fd)
168 {
169   bfd *nbfd;
170   bfd_target *target_vec;
171   int fdflags;
172 #ifdef BFD_LOCKS
173   struct flock lock, *lockp = &lock;
174 #endif
175
176   bfd_error = system_call_error;
177   
178   fdflags = fcntl (fd, F_GETFL, NULL);
179   if (fdflags == -1) return NULL;
180
181 #ifdef BFD_LOCKS
182   lockp->l_type = F_RDLCK;
183   if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
184 #endif
185
186   nbfd = new_bfd();
187
188   if (nbfd == NULL) {
189     bfd_error = no_memory;
190     return NULL;
191   }
192
193   target_vec = bfd_find_target (target, nbfd);
194   if (target_vec == NULL) {
195     bfd_error = invalid_target;
196     return NULL;
197   }
198
199 #ifdef BFD_LOCKS
200   nbfd->lock = (struct flock *) (nbfd + 1);
201 #endif
202   /* if the fd were open for read only, this still would not hurt: */
203   nbfd->iostream = (char *) fdopen (fd, "r+"); 
204   if (nbfd->iostream == NULL) {
205     (void) obstack_free (&nbfd->memory, (PTR)0);
206     return NULL;
207   }
208   
209   /* OK, put everything where it belongs */
210
211   nbfd->filename = filename;
212
213   /* As a special case we allow a FD open for read/write to
214      be written through, although doing so requires that we end
215      the previous clause with a preposition.  */
216   switch (fdflags & O_ACCMODE) {
217   case O_RDONLY: nbfd->direction = read_direction; break;
218   case O_WRONLY: nbfd->direction = write_direction; break;  
219   case O_RDWR: nbfd->direction = both_direction; break;
220   default: abort ();
221   }
222                                    
223 #ifdef BFD_LOCKS
224   memcpy (nbfd->lock, lockp, sizeof (struct flock))
225 #endif
226
227   bfd_cache_init (nbfd);
228
229   return nbfd;
230 }
231 \f
232 /** bfd_openw -- open for writing.
233   Returns a pointer to a freshly-allocated bfd on success, or NULL.
234
235   See comment by bfd_fdopenr before you try to modify this function. */
236
237 /*proto* bfd_openw
238 Creates a bfd, associated with file @var{filename}, using the file
239 format @var{target}, and returns a pointer to it.
240
241 Possible errors are system_call_error, no_memory, invalid_target.
242 *; PROTO(bfd *, bfd_openw, (CONST char *filename, CONST char *target));
243 */
244
245 bfd *
246 DEFUN(bfd_openw,(filename, target),
247       CONST char *filename AND
248       CONST char *target)
249 {
250   bfd *nbfd;
251   bfd_target *target_vec;
252   
253   bfd_error = system_call_error;
254
255   /* nbfd has to point to head of malloc'ed block so that bfd_close may
256      reclaim it correctly. */
257
258   nbfd = new_bfd();
259   if (nbfd == NULL) {
260     bfd_error = no_memory;
261     return NULL;
262   }
263
264   target_vec = bfd_find_target (target, nbfd);
265   if (target_vec == NULL) return NULL;
266
267   nbfd->filename = filename;
268   nbfd->direction = write_direction;
269
270   if (bfd_open_file (nbfd) == NULL) {
271     bfd_error = system_call_error;      /* File not writeable, etc */
272     (void) obstack_free (&nbfd->memory, (PTR)0);
273     return NULL;
274   }
275   return nbfd;
276 }
277
278 /*proto* bfd_close
279 This function closes a bfd. If the bfd was open for writing, then
280 pending operations are completed and the file written out and closed.
281 If the created file is executable, then @code{chmod} is called to mark
282 it as such.
283
284 All memory attatched to the bfd's obstacks is released. 
285
286 @code{true} is returned if all is ok, otherwise @code{false}.
287 *; PROTO(boolean, bfd_close,(bfd *));
288 */
289
290 boolean
291 DEFUN(bfd_close,(abfd),
292       bfd *abfd)
293 {
294   if (!bfd_read_p(abfd))
295     if (BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)) != true)
296       return false;
297
298   if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
299
300   bfd_cache_close(abfd);
301
302   /* If the file was open for writing and is now executable,
303      make it so */
304   if (abfd->direction == write_direction 
305       && abfd->flags & EXEC_P) {
306     struct stat buf;
307     stat(abfd->filename, &buf);
308 #ifndef S_IXUSR
309 #define S_IXUSR 0100    /* Execute by owner.  */
310 #endif
311 #ifndef S_IXGRP
312 #define S_IXGRP 0010    /* Execute by group.  */
313 #endif
314 #ifndef S_IXOTH
315 #define S_IXOTH 0001    /* Execute by others.  */
316 #endif
317
318     chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
319   }
320   (void) obstack_free (&abfd->memory, (PTR)0);
321   /* FIXME, shouldn't we de-allocate the bfd as well? */
322   return true;
323 }
324
325 /*proto* bfd_create
326 This routine creates a new bfd in the manner of bfd_openw, but without
327 opening a file. The new bfd takes the target from the target used by
328 @var{template}. The format is always set to @code{bfd_object}.
329
330 *; PROTO(bfd *, bfd_create, (CONST char *filename, bfd *template));
331 */
332
333 bfd *
334 DEFUN(bfd_create,(filename, template),
335       CONST char *filename AND
336       bfd *template)
337 {
338   bfd *nbfd = new_bfd();
339   if (nbfd == (bfd *)NULL) {
340     bfd_error = no_memory;
341     return (bfd *)NULL;
342   }
343   nbfd->filename = filename;
344   if(template) {
345     nbfd->xvec = template->xvec;
346   }
347   nbfd->direction = no_direction;
348   bfd_set_format(nbfd, bfd_object);
349   return nbfd;
350 }
351
352 /* Memory allocation */
353
354 DEFUN(PTR bfd_alloc_by_size_t,(abfd, size),
355       bfd *abfd AND
356       size_t size)
357 {
358   PTR res = obstack_alloc(&(abfd->memory), size);
359   return res;
360 }
361
362 DEFUN(void bfd_alloc_grow,(abfd, ptr, size),
363       bfd *abfd AND
364       PTR ptr AND
365       bfd_size_type size)
366 {
367    obstack_grow(&(abfd->memory), ptr, size);
368 }
369 DEFUN(PTR bfd_alloc_finish,(abfd),
370       bfd *abfd)
371 {
372   return obstack_finish(&(abfd->memory));
373 }
374
375 DEFUN(PTR bfd_alloc, (abfd, size),
376       bfd *abfd AND
377       bfd_size_type size)
378 {
379   return bfd_alloc_by_size_t(abfd, (size_t)size);
380 }
381
382 DEFUN(PTR bfd_zalloc,(abfd, size),
383       bfd *abfd AND
384       bfd_size_type size)
385 {
386   PTR res = bfd_alloc(abfd, size);
387   memset(res, 0, (size_t)size);
388   return res;
389 }
390
391 DEFUN(PTR bfd_realloc,(abfd, old, size),
392       bfd *abfd AND
393       PTR old AND
394       bfd_size_type size)
395 {
396   PTR res = bfd_alloc(abfd, size);
397   memcpy(res, old, (size_t)size);
398   return res;
399 }
400
401 /*proto* bfd_alloc_size
402 Return the number of bytes in the obstacks connected to the supplied
403 bfd.
404 *; PROTO(bfd_size_type,bfd_alloc_size,(bfd *abfd));
405 */
406
407 bfd_size_type
408 DEFUN( bfd_alloc_size,(abfd),
409       bfd *abfd)
410 {
411   struct _obstack_chunk *chunk = abfd->memory.chunk;
412   size_t size = 0;
413   while (chunk) {
414     size += chunk->limit - &(chunk->contents[0]);
415     chunk = chunk->prev;
416   }
417   return size;
418 }