Tue Jun 18 14:42:58 1996 Klaus Kaempf <kkaempf@progis.de>
[deliverable/binutils-gdb.git] / bfd / opncls.c
1 /* opncls.c -- open and close a BFD.
2 Copyright (C) 1990 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
3 Written by Cygnus Support.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program 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 2 of the License, or
10 (at your option) any later version.
11
12 This program 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 this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "obstack.h"
25
26 #ifndef S_IXUSR
27 #define S_IXUSR 0100 /* Execute by owner. */
28 #endif
29 #ifndef S_IXGRP
30 #define S_IXGRP 0010 /* Execute by group. */
31 #endif
32 #ifndef S_IXOTH
33 #define S_IXOTH 0001 /* Execute by others. */
34 #endif
35
36 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately
37 if we do that we can't use fcntl. */
38
39
40 #define obstack_chunk_alloc malloc
41 #define obstack_chunk_free free
42
43 #ifndef HAVE_GETPAGESIZE
44 #define getpagesize() 2048
45 #endif
46
47 long _bfd_chunksize = -1;
48
49 /* Return a new BFD. All BFD's are allocated through this routine. */
50
51 bfd *
52 _bfd_new_bfd ()
53 {
54 bfd *nbfd;
55
56 nbfd = (bfd *)bfd_zmalloc (sizeof (bfd));
57 if (!nbfd)
58 return 0;
59
60 if (_bfd_chunksize <= 0)
61 {
62 _bfd_chunksize = getpagesize ();
63 if (_bfd_chunksize <= 0)
64 _bfd_chunksize = 2048;
65 /* Leave some slush space, since many malloc implementations
66 prepend a header, and may wind up wasting another page
67 because of it. */
68 _bfd_chunksize -= 32;
69 }
70
71 if (!obstack_begin(&nbfd->memory, _bfd_chunksize))
72 {
73 bfd_set_error (bfd_error_no_memory);
74 return 0;
75 }
76
77 nbfd->arch_info = &bfd_default_arch_struct;
78
79 nbfd->direction = no_direction;
80 nbfd->iostream = NULL;
81 nbfd->where = 0;
82 nbfd->sections = (asection *)NULL;
83 nbfd->format = bfd_unknown;
84 nbfd->my_archive = (bfd *)NULL;
85 nbfd->origin = 0;
86 nbfd->opened_once = false;
87 nbfd->output_has_begun = false;
88 nbfd->section_count = 0;
89 nbfd->usrdata = (PTR)NULL;
90 nbfd->cacheable = false;
91 nbfd->flags = NO_FLAGS;
92 nbfd->mtime_set = false;
93
94 return nbfd;
95 }
96
97 /* Allocate a new BFD as a member of archive OBFD. */
98
99 bfd *
100 _bfd_new_bfd_contained_in (obfd)
101 bfd *obfd;
102 {
103 bfd *nbfd;
104
105 nbfd = _bfd_new_bfd();
106 nbfd->xvec = obfd->xvec;
107 nbfd->my_archive = obfd;
108 nbfd->direction = read_direction;
109 nbfd->target_defaulted = obfd->target_defaulted;
110 return nbfd;
111 }
112
113 /*
114 SECTION
115 Opening and closing BFDs
116
117 */
118
119 /*
120 FUNCTION
121 bfd_openr
122
123 SYNOPSIS
124 bfd *bfd_openr(CONST char *filename, CONST char *target);
125
126 DESCRIPTION
127 Open the file @var{filename} (using <<fopen>>) with the target
128 @var{target}. Return a pointer to the created BFD.
129
130 Calls <<bfd_find_target>>, so @var{target} is interpreted as by
131 that function.
132
133 If <<NULL>> is returned then an error has occured. Possible errors
134 are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> or <<system_call>> error.
135 */
136
137 bfd *
138 bfd_openr (filename, target)
139 CONST char *filename;
140 CONST char *target;
141 {
142 bfd *nbfd;
143 const bfd_target *target_vec;
144
145 nbfd = _bfd_new_bfd();
146 if (nbfd == NULL)
147 return NULL;
148
149 target_vec = bfd_find_target (target, nbfd);
150 if (target_vec == NULL) {
151 bfd_set_error (bfd_error_invalid_target);
152 return NULL;
153 }
154
155 nbfd->filename = filename;
156 nbfd->direction = read_direction;
157
158 if (bfd_open_file (nbfd) == NULL) {
159 bfd_set_error (bfd_error_system_call); /* File didn't exist, or some such */
160 bfd_release(nbfd,0);
161 return NULL;
162 }
163 return nbfd;
164 }
165
166
167 /* Don't try to `optimize' this function:
168
169 o - We lock using stack space so that interrupting the locking
170 won't cause a storage leak.
171 o - We open the file stream last, since we don't want to have to
172 close it if anything goes wrong. Closing the stream means closing
173 the file descriptor too, even though we didn't open it.
174 */
175 /*
176 FUNCTION
177 bfd_fdopenr
178
179 SYNOPSIS
180 bfd *bfd_fdopenr(CONST char *filename, CONST char *target, int fd);
181
182 DESCRIPTION
183 <<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to <<fopen>>.
184 It opens a BFD on a file already described by the @var{fd}
185 supplied.
186
187 When the file is later <<bfd_close>>d, the file descriptor will be closed.
188
189 If the caller desires that this file descriptor be cached by BFD
190 (opened as needed, closed as needed to free descriptors for
191 other opens), with the supplied @var{fd} used as an initial
192 file descriptor (but subject to closure at any time), call
193 bfd_set_cacheable(bfd, 1) on the returned BFD. The default is to
194 assume no cacheing; the file descriptor will remain open until
195 <<bfd_close>>, and will not be affected by BFD operations on other
196 files.
197
198 Possible errors are <<bfd_error_no_memory>>, <<bfd_error_invalid_target>> and <<bfd_error_system_call>>.
199 */
200
201 bfd *
202 bfd_fdopenr (filename, target, fd)
203 CONST char *filename;
204 CONST char *target;
205 int fd;
206 {
207 bfd *nbfd;
208 const bfd_target *target_vec;
209 int fdflags;
210
211 bfd_set_error (bfd_error_system_call);
212 #if ! defined(HAVE_FCNTL) || ! defined(F_GETFL)
213 fdflags = O_RDWR; /* Assume full access */
214 #else
215 fdflags = fcntl (fd, F_GETFL, NULL);
216 #endif
217 if (fdflags == -1) return NULL;
218
219 nbfd = _bfd_new_bfd();
220
221 if (nbfd == NULL)
222 return NULL;
223
224 target_vec = bfd_find_target (target, nbfd);
225 if (target_vec == NULL) {
226 bfd_set_error (bfd_error_invalid_target);
227 return NULL;
228 }
229 #if defined(VMS) || defined(__GO32__) || defined (WINGDB)
230 nbfd->iostream = (PTR)fopen(filename, FOPEN_RB);
231 #else
232 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
233 switch (fdflags & (O_ACCMODE)) {
234 case O_RDONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RB); break;
235 case O_WRONLY: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
236 case O_RDWR: nbfd->iostream = (PTR) fdopen (fd, FOPEN_RUB); break;
237 default: abort ();
238 }
239 #endif
240 if (nbfd->iostream == NULL) {
241 (void) obstack_free (&nbfd->memory, (PTR)0);
242 return NULL;
243 }
244
245 /* OK, put everything where it belongs */
246
247 nbfd->filename = filename;
248
249 /* As a special case we allow a FD open for read/write to
250 be written through, although doing so requires that we end
251 the previous clause with a preposition. */
252 /* (O_ACCMODE) parens are to avoid Ultrix header file bug */
253 switch (fdflags & (O_ACCMODE)) {
254 case O_RDONLY: nbfd->direction = read_direction; break;
255 case O_WRONLY: nbfd->direction = write_direction; break;
256 case O_RDWR: nbfd->direction = both_direction; break;
257 default: abort ();
258 }
259
260 if (! bfd_cache_init (nbfd))
261 return NULL;
262
263 return nbfd;
264 }
265
266 /*
267 FUNCTION
268 bfd_openstreamr
269
270 SYNOPSIS
271 bfd *bfd_openstreamr();
272
273 DESCRIPTION
274
275 Open a BFD for read access on an existing stdio stream. When
276 the BFD is passed to <<bfd_close>>, the stream will be closed.
277 */
278
279 bfd *
280 bfd_openstreamr (filename, target, stream)
281 const char *filename;
282 const char *target;
283 FILE *stream;
284 {
285 bfd *nbfd;
286 const bfd_target *target_vec;
287
288 nbfd = _bfd_new_bfd ();
289 if (nbfd == NULL)
290 return NULL;
291
292 target_vec = bfd_find_target (target, nbfd);
293 if (target_vec == NULL)
294 {
295 bfd_set_error (bfd_error_invalid_target);
296 return NULL;
297 }
298
299 nbfd->iostream = (PTR) stream;
300 nbfd->filename = filename;
301 nbfd->direction = read_direction;
302
303 if (! bfd_cache_init (nbfd))
304 return NULL;
305
306 return nbfd;
307 }
308 \f
309 /** bfd_openw -- open for writing.
310 Returns a pointer to a freshly-allocated BFD on success, or NULL.
311
312 See comment by bfd_fdopenr before you try to modify this function. */
313
314 /*
315 FUNCTION
316 bfd_openw
317
318 SYNOPSIS
319 bfd *bfd_openw(CONST char *filename, CONST char *target);
320
321 DESCRIPTION
322 Create a BFD, associated with file @var{filename}, using the
323 file format @var{target}, and return a pointer to it.
324
325 Possible errors are <<bfd_error_system_call>>, <<bfd_error_no_memory>>,
326 <<bfd_error_invalid_target>>.
327 */
328
329 bfd *
330 bfd_openw (filename, target)
331 CONST char *filename;
332 CONST char *target;
333 {
334 bfd *nbfd;
335 const bfd_target *target_vec;
336
337 bfd_set_error (bfd_error_system_call);
338
339 /* nbfd has to point to head of malloc'ed block so that bfd_close may
340 reclaim it correctly. */
341
342 nbfd = _bfd_new_bfd();
343 if (nbfd == NULL)
344 return NULL;
345
346 target_vec = bfd_find_target (target, nbfd);
347 if (target_vec == NULL) return NULL;
348
349 nbfd->filename = filename;
350 nbfd->direction = write_direction;
351
352 if (bfd_open_file (nbfd) == NULL) {
353 bfd_set_error (bfd_error_system_call); /* File not writeable, etc */
354 (void) obstack_free (&nbfd->memory, (PTR)0);
355 return NULL;
356 }
357 return nbfd;
358 }
359
360 /*
361
362 FUNCTION
363 bfd_close
364
365 SYNOPSIS
366 boolean bfd_close(bfd *abfd);
367
368 DESCRIPTION
369
370 Close a BFD. If the BFD was open for writing,
371 then pending operations are completed and the file written out
372 and closed. If the created file is executable, then
373 <<chmod>> is called to mark it as such.
374
375 All memory attached to the BFD's obstacks is released.
376
377 The file descriptor associated with the BFD is closed (even
378 if it was passed in to BFD by <<bfd_fdopenr>>).
379
380 RETURNS
381 <<true>> is returned if all is ok, otherwise <<false>>.
382 */
383
384
385 boolean
386 bfd_close (abfd)
387 bfd *abfd;
388 {
389 boolean ret;
390
391 if (!bfd_read_p (abfd))
392 {
393 if (! BFD_SEND_FMT (abfd, _bfd_write_contents, (abfd)))
394 return false;
395 }
396
397 if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
398 return false;
399
400 ret = bfd_cache_close (abfd);
401
402 /* If the file was open for writing and is now executable,
403 make it so */
404 if (ret
405 && abfd->direction == write_direction
406 && abfd->flags & EXEC_P)
407 {
408 struct stat buf;
409
410 if (stat (abfd->filename, &buf) == 0)
411 {
412 int mask = umask (0);
413 umask (mask);
414 chmod (abfd->filename,
415 (0777
416 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
417 }
418 }
419
420 (void) obstack_free (&abfd->memory, (PTR)0);
421 (void) free (abfd);
422
423 return ret;
424 }
425
426 /*
427 FUNCTION
428 bfd_close_all_done
429
430 SYNOPSIS
431 boolean bfd_close_all_done(bfd *);
432
433 DESCRIPTION
434 Close a BFD. Differs from <<bfd_close>>
435 since it does not complete any pending operations. This
436 routine would be used if the application had just used BFD for
437 swapping and didn't want to use any of the writing code.
438
439 If the created file is executable, then <<chmod>> is called
440 to mark it as such.
441
442 All memory attached to the BFD's obstacks is released.
443
444 RETURNS
445 <<true>> is returned if all is ok, otherwise <<false>>.
446
447 */
448
449 boolean
450 bfd_close_all_done (abfd)
451 bfd *abfd;
452 {
453 boolean ret;
454
455 ret = bfd_cache_close (abfd);
456
457 /* If the file was open for writing and is now executable,
458 make it so */
459 if (ret
460 && abfd->direction == write_direction
461 && abfd->flags & EXEC_P)
462 {
463 struct stat buf;
464
465 if (stat (abfd->filename, &buf) == 0)
466 {
467 int mask = umask (0);
468 umask (mask);
469 chmod (abfd->filename,
470 (0x777
471 & (buf.st_mode | ((S_IXUSR | S_IXGRP | S_IXOTH) &~ mask))));
472 }
473 }
474 (void) obstack_free (&abfd->memory, (PTR)0);
475 (void) free(abfd);
476 return ret;
477 }
478
479
480 /*
481 FUNCTION
482 bfd_alloc_size
483
484 SYNOPSIS
485 bfd_size_type bfd_alloc_size(bfd *abfd);
486
487 DESCRIPTION
488 Return the number of bytes in the obstacks connected to @var{abfd}.
489
490 */
491
492 bfd_size_type
493 bfd_alloc_size (abfd)
494 bfd *abfd;
495 {
496 struct _obstack_chunk *chunk = abfd->memory.chunk;
497 size_t size = 0;
498 while (chunk) {
499 size += chunk->limit - &(chunk->contents[0]);
500 chunk = chunk->prev;
501 }
502 return size;
503 }
504
505
506
507 /*
508 FUNCTION
509 bfd_create
510
511 SYNOPSIS
512 bfd *bfd_create(CONST char *filename, bfd *templ);
513
514 DESCRIPTION
515 Create a new BFD in the manner of
516 <<bfd_openw>>, but without opening a file. The new BFD
517 takes the target from the target used by @var{template}. The
518 format is always set to <<bfd_object>>.
519
520 */
521
522 bfd *
523 bfd_create (filename, templ)
524 CONST char *filename;
525 bfd *templ;
526 {
527 bfd *nbfd = _bfd_new_bfd();
528 if (nbfd == (bfd *)NULL)
529 return (bfd *)NULL;
530 nbfd->filename = filename;
531 if(templ) {
532 nbfd->xvec = templ->xvec;
533 }
534 nbfd->direction = no_direction;
535 bfd_set_format(nbfd, bfd_object);
536 return nbfd;
537 }
538
539 /*
540 INTERNAL_FUNCTION
541 bfd_alloc_by_size_t
542
543 SYNOPSIS
544 PTR bfd_alloc_by_size_t(bfd *abfd, size_t wanted);
545
546 DESCRIPTION
547 Allocate a block of @var{wanted} bytes of memory in the obstack
548 attatched to <<abfd>> and return a pointer to it.
549 */
550
551
552 PTR
553 bfd_alloc_by_size_t (abfd, size)
554 bfd *abfd;
555 size_t size;
556 {
557 PTR ret;
558
559 ret = obstack_alloc (&(abfd->memory), size);
560 if (ret == NULL)
561 bfd_set_error (bfd_error_no_memory);
562 return ret;
563 }
564
565 void
566 bfd_alloc_grow (abfd, ptr, size)
567 bfd *abfd;
568 PTR ptr;
569 size_t size;
570 {
571 (void) obstack_grow(&(abfd->memory), ptr, size);
572 }
573
574 PTR
575 bfd_alloc_finish (abfd)
576 bfd *abfd;
577 {
578 PTR ret;
579
580 ret = obstack_finish (&(abfd->memory));
581 if (ret == NULL)
582 bfd_set_error (bfd_error_no_memory);
583 return ret;
584 }
585
586 PTR
587 bfd_alloc (abfd, size)
588 bfd *abfd;
589 size_t size;
590 {
591 return bfd_alloc_by_size_t(abfd, (size_t)size);
592 }
593
594 PTR
595 bfd_zalloc (abfd, size)
596 bfd *abfd;
597 size_t size;
598 {
599 PTR res;
600 res = bfd_alloc(abfd, size);
601 if (res)
602 memset(res, 0, (size_t)size);
603 return res;
604 }
This page took 0.047302 seconds and 4 git commands to generate.