*** empty log message ***
[platform/upstream/binutils.git] / bfd / opncls.c
1 /* Copyright (C) 1990, 1991 Free Software Foundation, Inc.
2
3 This file is part of BFD, the Binary File Diddler.
4
5 BFD is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 1, or (at your option)
8 any later version.
9
10 BFD is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with BFD; see the file COPYING.  If not, write to
17 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
18
19 /* $Id$ */
20
21 /*** opncls.c -- open and close a bfd. */
22
23 #include "sysdep.h"
24 #include "bfd.h"
25 #include "libbfd.h"
26
27
28
29 extern void bfd_cache_init();
30 FILE *bfd_open_file();
31
32 /* fdopen is a loser -- we should use stdio exclusively.  Unfortunately
33    if we do that we can't use fcntl.  */
34 \f
35 /** Locking 
36
37    Locking is loosely controlled by the preprocessor variable
38    BFD_LOCKS.  I say loosely because Unix barely understands locking
39    -- at least in BSD it doesn't affect programs which don't
40    explicitly use it!  That is to say it's practically useless, though
41    if everyone uses this library you'll be OK.
42
43    From among the many and varied lock facilities available, (none of
44    which, of course, knows about any other) we use the fcntl locks,
45    because they're Posix.
46
47    The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
48    exists is because of locking.  When we do output, we lock the
49    filename file for output, then open a temporary file which does not
50    actually get its correct filename until closing time.  This is
51    safest, but requires the asymmetry in read and write entry points.
52
53    Perhaps, since unix has so many different kinds of locking anyway,
54    we should use the emacs lock scheme?... */
55 \f
56
57 #define obstack_chunk_alloc malloc
58 #define obstack_chunk_free free
59
60 bfd *new_bfd()
61 {
62   struct obstack tmp;
63   bfd *nbfd;
64   obstack_init(&tmp);
65   
66   nbfd = (bfd *)obstack_alloc(&tmp,sizeof(bfd));
67   nbfd->memory = tmp;
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   return nbfd;
84 }
85 bfd *new_bfd_contained_in(obfd)
86 bfd *obfd;
87 {
88         bfd *nbfd = new_bfd();
89         nbfd->xvec = obfd->xvec;
90         nbfd->my_archive = obfd;
91         nbfd->direction = read_direction;
92         return nbfd;
93 }
94
95 /** bfd_openr, bfd_fdopenr -- open for reading.
96   Returns a pointer to a freshly-allocated bfd on success, or NULL. */
97
98 bfd *
99 DEFUN(bfd_openr, (filename, target),
100       CONST char *filename AND
101       CONST char *target)
102 {
103   bfd *nbfd;
104   bfd_target *target_vec;
105
106   target_vec = bfd_find_target (target);
107   if (target_vec == NULL) {
108     bfd_error = invalid_target;
109     return NULL;
110   }
111
112   bfd_error = system_call_error;
113   nbfd = new_bfd();
114   if (nbfd == NULL) {
115     bfd_error = no_memory;
116     return NULL;
117   }
118
119   nbfd->filename = filename;
120   nbfd->xvec = target_vec;
121   nbfd->direction = read_direction; 
122
123   if (bfd_open_file (nbfd) == NULL) {
124     bfd_error = system_call_error;      /* File didn't exist, or some such */
125     bfd_release(nbfd,0);
126     return NULL;
127   }
128   return nbfd;
129 }
130
131
132 /* Don't try to `optimize' this function:
133
134    o - We lock using stack space so that interrupting the locking
135        won't cause a storage leak.
136    o - We open the file stream last, since we don't want to have to
137        close it if anything goes wrong.  Closing the stream means closing
138        the file descriptor too, even though we didn't open it.
139  */
140
141 bfd *
142 DEFUN(bfd_fdopenr,(filename, target, fd),
143       CONST char *filename AND
144       CONST char *target AND
145       int fd)
146 {
147   bfd *nbfd;
148   bfd_target *target_vec;
149   int fdflags;
150 #ifdef BFD_LOCKS
151   struct flock lock, *lockp = &lock;
152 #endif
153
154   target_vec = bfd_find_target (target);
155   if (target_vec == NULL) {
156     bfd_error = invalid_target;
157     return NULL;
158   }
159
160   bfd_error = system_call_error;
161   
162   fdflags = fcntl (fd, F_GETFL);
163   if (fdflags == -1) return NULL;
164
165 #ifdef BFD_LOCKS
166   lockp->l_type = F_RDLCK;
167   if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
168 #endif
169
170   nbfd = new_bfd();
171
172   if (nbfd == NULL) {
173     bfd_error = no_memory;
174     return NULL;
175   }
176 #ifdef BFD_LOCKS
177   nbfd->lock = (struct flock *) (nbfd + 1);
178 #endif
179   /* if the fd were open for read only, this still would not hurt: */
180   nbfd->iostream = (char *) fdopen (fd, "r+"); 
181   if (nbfd->iostream == NULL) {
182     free (nbfd);
183     return NULL;
184   }
185   
186   /* OK, put everything where it belongs */
187
188   nbfd->filename = filename;
189   nbfd->xvec = target_vec;
190
191   /* As a special case we allow a FD open for read/write to
192      be written through, although doing so requires that we end
193      the previous clause with a preposition.  */
194   switch (fdflags & O_ACCMODE) {
195   case O_RDONLY: nbfd->direction = read_direction; break;
196   case O_WRONLY: nbfd->direction = write_direction; break;  
197   case O_RDWR: nbfd->direction = both_direction; break;
198   default: abort ();
199   }
200                                    
201 #ifdef BFD_LOCKS
202   memcpy (nbfd->lock, lockp, sizeof (struct flock))
203 #endif
204
205     bfd_cache_init (nbfd);
206
207   return nbfd;
208 }
209 \f
210 /** bfd_openw -- open for writing.
211   Returns a pointer to a freshly-allocated bfd on success, or NULL.
212
213   See comment by bfd_fdopenr before you try to modify this function. */
214
215 bfd *
216 DEFUN(bfd_openw,(filename, target),
217       CONST char *filename AND
218       CONST char *target)
219 {
220   bfd *nbfd;
221   bfd_target *target_vec;
222   
223   target_vec = bfd_find_target (target);
224   if (target_vec == NULL) return NULL;
225
226   bfd_error = system_call_error;
227
228   /* nbfd has to point to head of malloc'ed block so that bfd_close may
229      reclaim it correctly. */
230
231   nbfd = new_bfd();
232   if (nbfd == NULL) {
233     bfd_error = no_memory;
234     return NULL;
235   }
236
237   nbfd->filename = filename;
238   nbfd->xvec = target_vec;
239   nbfd->direction = write_direction;
240
241   if (bfd_open_file (nbfd) == NULL) {
242     bfd_error = system_call_error;      /* File not writeable, etc */
243     free (nbfd);
244     return NULL;
245   }
246   return nbfd;
247 }
248
249
250 \f
251 /** Close up shop, get your deposit back. */
252 boolean
253 bfd_close (abfd)
254      bfd *abfd;
255 {
256   if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
257
258   bfd_cache_close(abfd);
259 /* If the file was open for writing and is now executable
260   make it so */
261   if (abfd->direction == write_direction 
262       && abfd->flags & EXEC_P) {
263     struct stat buf;
264     stat(abfd->filename, &buf);
265     chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
266   }
267   obstack_free(&abfd->memory, (PTR)0);
268   return true;
269 }
270 /* 
271  called to create a bfd with no ascociated file or target 
272  */
273 bfd *
274 DEFUN(bfd_create,(filename, template),
275       CONST char *filename AND
276       CONST bfd *template)
277 {
278   bfd *nbfd = new_bfd();
279   if (nbfd == (bfd *)NULL) {
280     bfd_error = no_memory;
281     return (bfd *)NULL;
282   }
283   nbfd->filename = filename;
284   if(template) {
285     nbfd->xvec = template->xvec;
286   }
287   nbfd->direction = no_direction;
288   bfd_set_format(nbfd, bfd_object);
289   return nbfd;
290
291
292
293 }
294
295 DEFUN(PTR bfd_alloc, (abfd, size),
296       bfd *abfd AND
297       size_t size)
298 {
299   PTR *res = obstack_alloc(&(abfd->memory),size);
300   return res;
301 }
302
303 DEFUN(PTR bfd_zalloc,(abfd, size),
304       bfd *abfd AND
305       size_t size)
306 {
307   PTR res = bfd_alloc(abfd, size);
308   memset(res, 0, size);
309   return res;
310 }
311
312 DEFUN(PTR bfd_realloc,(abfd, old, size),
313       bfd *abfd AND
314       PTR old AND
315       size_t size)
316 {
317   PTR res = bfd_alloc(abfd, size);
318   memcpy(res, old, size);
319   return res;
320 }
321
322
323 DEFUN(size_t bfd_alloc_size,(abfd),
324       bfd *abfd)
325 {
326   struct _obstack_chunk *chunk = abfd->memory.chunk;
327   size_t size = 0;
328   while (chunk) {
329     size += chunk->limit - &(chunk->contents[0]);
330     chunk = chunk->prev;
331   }
332   return size;
333 }