]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - bfd/opncls.c
Merged in some changes from Intel,
[thirdparty/binutils-gdb.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 extern void bfd_cache_init();
29 FILE *bfd_open_file();
30
31 /* fdopen is a loser -- we should use stdio exclusively. Unfortunately
32 if we do that we can't use fcntl. */
33 \f
34 /** Locking
35
36 Locking is loosely controlled by the preprocessor variable
37 BFD_LOCKS. I say loosely because Unix barely understands locking
38 -- at least in BSD it doesn't affect programs which don't
39 explicitly use it! That is to say it's practically useless, though
40 if everyone uses this library you'll be OK.
41
42 From among the many and varied lock facilities available, (none of
43 which, of course, knows about any other) we use the fcntl locks,
44 because they're Posix.
45
46 The reason that bfd_openr and bfd_fdopenr exist, yet only bfd_openw
47 exists is because of locking. When we do output, we lock the
48 filename file for output, then open a temporary file which does not
49 actually get its correct filename until closing time. This is
50 safest, but requires the asymmetry in read and write entry points.
51
52 Perhaps, since unix has so many different kinds of locking anyway,
53 we should use the emacs lock scheme?... */
54 \f
55
56 bfd *new_bfd()
57 {
58 bfd *nbfd = (bfd *)zalloc(sizeof(bfd));
59
60 nbfd->direction = no_direction;
61 nbfd->iostream = NULL;
62 nbfd->where = 0;
63 nbfd->sections = (asection *)NULL;
64 nbfd->format = bfd_unknown;
65 nbfd->my_archive = (bfd *)NULL;
66 nbfd->origin = 0;
67 nbfd->opened_once = false;
68 nbfd->output_has_begun = false;
69 nbfd->section_count = 0;
70 nbfd->usrdata = (PTR)NULL;
71 nbfd->sections = (asection *)NULL;
72 nbfd->cacheable = false;
73 nbfd->flags = NO_FLAGS;
74 return nbfd;
75 }
76 bfd *new_bfd_contained_in(obfd)
77 bfd *obfd;
78 {
79 bfd *nbfd = new_bfd();
80 nbfd->xvec = obfd->xvec;
81 nbfd->my_archive = obfd;
82 nbfd->direction = read_direction;
83 return nbfd;
84 }
85
86 /** bfd_openr, bfd_fdopenr -- open for reading.
87 Returns a pointer to a freshly-allocated bfd on success, or NULL. */
88
89 bfd *
90 DEFUN(bfd_openr, (filename, target),
91 CONST char *filename AND
92 CONST char *target)
93 {
94 bfd *nbfd;
95 bfd_target *target_vec;
96
97 target_vec = bfd_find_target (target);
98 if (target_vec == NULL) {
99 bfd_error = invalid_target;
100 return NULL;
101 }
102
103 bfd_error = system_call_error;
104 nbfd = new_bfd();
105 if (nbfd == NULL) {
106 bfd_error = no_memory;
107 return NULL;
108 }
109
110 nbfd->filename = filename;
111 nbfd->xvec = target_vec;
112 nbfd->direction = read_direction;
113
114 if (bfd_open_file (nbfd) == NULL) {
115 bfd_error = system_call_error; /* File didn't exist, or some such */
116 free (nbfd);
117 return NULL;
118 }
119 return nbfd;
120 }
121
122
123 /* Don't try to `optimize' this function:
124
125 o - We lock using stack space so that interrupting the locking
126 won't cause a storage leak.
127 o - We open the file stream last, since we don't want to have to
128 close it if anything goes wrong. Closing the stream means closing
129 the file descriptor too, even though we didn't open it.
130 */
131
132 bfd *
133 DEFUN(bfd_fdopenr,(filename, target, fd),
134 CONST char *filename AND
135 CONST char *target AND
136 int fd)
137 {
138 bfd *nbfd;
139 bfd_target *target_vec;
140 int fdflags;
141 #ifdef BFD_LOCKS
142 struct flock lock, *lockp = &lock;
143 #endif
144
145 target_vec = bfd_find_target (target);
146 if (target_vec == NULL) {
147 bfd_error = invalid_target;
148 return NULL;
149 }
150
151 bfd_error = system_call_error;
152
153 fdflags = fcntl (fd, F_GETFL);
154 if (fdflags == -1) return NULL;
155
156 #ifdef BFD_LOCKS
157 lockp->l_type = F_RDLCK;
158 if (fcntl (fd, F_SETLKW, lockp) == -1) return NULL;
159 #endif
160
161 nbfd = new_bfd();
162
163 if (nbfd == NULL) {
164 bfd_error = no_memory;
165 return NULL;
166 }
167 #ifdef BFD_LOCKS
168 nbfd->lock = (struct flock *) (nbfd + 1);
169 #endif
170 /* if the fd were open for read only, this still would not hurt: */
171 nbfd->iostream = (char *) fdopen (fd, "r+");
172 if (nbfd->iostream == NULL) {
173 free (nbfd);
174 return NULL;
175 }
176
177 /* OK, put everything where it belongs */
178
179 nbfd->filename = filename;
180 nbfd->xvec = target_vec;
181
182 /* As a special case we allow a FD open for read/write to
183 be written through, although doing so requires that we end
184 the previous clause with a preposition. */
185 switch (fdflags & O_ACCMODE) {
186 case O_RDONLY: nbfd->direction = read_direction; break;
187 case O_WRONLY: nbfd->direction = write_direction; break;
188 case O_RDWR: nbfd->direction = both_direction; break;
189 default: abort ();
190 }
191
192 #ifdef BFD_LOCKS
193 memcpy (nbfd->lock, lockp, sizeof (struct flock))
194 #endif
195
196 bfd_cache_init (nbfd);
197
198 return nbfd;
199 }
200 \f
201 /** bfd_openw -- open for writing.
202 Returns a pointer to a freshly-allocated bfd on success, or NULL.
203
204 See comment by bfd_fdopenr before you try to modify this function. */
205
206 bfd *
207 DEFUN(bfd_openw,(filename, target),
208 CONST char *filename AND
209 CONST char *target)
210 {
211 bfd *nbfd;
212 bfd_target *target_vec;
213
214 target_vec = bfd_find_target (target);
215 if (target_vec == NULL) return NULL;
216
217 bfd_error = system_call_error;
218
219 /* nbfd has to point to head of malloc'ed block so that bfd_close may
220 reclaim it correctly. */
221
222 nbfd = new_bfd();
223 if (nbfd == NULL) {
224 bfd_error = no_memory;
225 return NULL;
226 }
227
228 nbfd->filename = filename;
229 nbfd->xvec = target_vec;
230 nbfd->direction = write_direction;
231
232 if (bfd_open_file (nbfd) == NULL) {
233 bfd_error = system_call_error; /* File not writeable, etc */
234 free (nbfd);
235 return NULL;
236 }
237 return nbfd;
238 }
239
240
241 \f
242 /** Close up shop, get your deposit back. */
243 boolean
244 bfd_close (abfd)
245 bfd *abfd;
246 {
247 if (BFD_SEND (abfd, _close_and_cleanup, (abfd)) != true) return false;
248
249 bfd_cache_close(abfd);
250 /* If the file was open for writing and is now executable
251 make it so */
252 if (abfd->direction == write_direction
253 && abfd->flags & EXEC_P) {
254 struct stat buf;
255 stat(abfd->filename, &buf);
256 chmod(abfd->filename,buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH);
257 }
258 free (abfd);
259 return true;
260 }
261 /*
262 called to create a bfd with no ascociated file or target
263 */
264 bfd *
265 DEFUN(bfd_create,(filename, template),
266 CONST char *filename AND
267 CONST bfd *template)
268 {
269 bfd *nbfd = new_bfd();
270 if (nbfd == (bfd *)NULL) {
271 bfd_error = no_memory;
272 return (bfd *)NULL;
273 }
274 nbfd->filename = filename;
275 nbfd->xvec = template->xvec;
276 nbfd->direction = no_direction;
277 return nbfd;
278
279
280
281 }