libctf: actually close bfds we have opened
[deliverable/binutils-gdb.git] / libctf / ctf-archive.c
CommitLineData
9402cc59
NA
1/* CTF archive files.
2 Copyright (C) 2019 Free Software Foundation, Inc.
3
4 This file is part of libctf.
5
6 libctf is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 See the GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING. If not see
18 <http://www.gnu.org/licenses/>. */
19
20#include <ctf-impl.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <elf.h>
a0486bac 24#include "ctf-endian.h"
9402cc59
NA
25#include <errno.h>
26#include <fcntl.h>
27#include <stdio.h>
28#include <string.h>
29#include <unistd.h>
30
31#ifdef HAVE_MMAP
32#include <sys/mman.h>
33#endif
34
35static off_t arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold);
36static ctf_file_t *ctf_arc_open_by_offset (const struct ctf_archive *arc,
37 const ctf_sect_t *symsect,
38 const ctf_sect_t *strsect,
39 size_t offset, int *errp);
40static int sort_modent_by_name (const void *one, const void *two, void *n);
41static void *arc_mmap_header (int fd, size_t headersz);
42static void *arc_mmap_file (int fd, size_t size);
43static int arc_mmap_writeout (int fd, void *header, size_t headersz,
44 const char **errmsg);
45static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
46
47/* bsearch() internal state. */
48static __thread char *search_nametbl;
49
5537f9b9
NA
50/* Write out a CTF archive to the start of the file referenced by the passed-in
51 fd. The entries in CTF_FILES are referenced by name: the names are passed in
52 the names array, which must have CTF_FILES entries.
9402cc59
NA
53
54 Returns 0 on success, or an errno, or an ECTF_* value. */
55int
5537f9b9
NA
56ctf_arc_write_fd (int fd, ctf_file_t **ctf_files, size_t ctf_file_cnt,
57 const char **names, size_t threshold)
9402cc59
NA
58{
59 const char *errmsg;
60 struct ctf_archive *archdr;
9402cc59
NA
61 size_t i;
62 char dummy = 0;
63 size_t headersz;
64 ssize_t namesz;
65 size_t ctf_startoffs; /* Start of the section we are working over. */
66 char *nametbl = NULL; /* The name table. */
67 char *np;
68 off_t nameoffs;
69 struct ctf_archive_modent *modent;
70
5537f9b9 71 ctf_dprintf ("Writing CTF archive with %lu files\n",
62d8e3b7 72 (unsigned long) ctf_file_cnt);
9402cc59 73
9402cc59
NA
74 /* Figure out the size of the mmap()ed header, including the
75 ctf_archive_modent array. We assume that all of this needs no
76 padding: a likely assumption, given that it's all made up of
77 uint64_t's. */
78 headersz = sizeof (struct ctf_archive)
79 + (ctf_file_cnt * sizeof (uint64_t) * 2);
62d8e3b7 80 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
9402cc59
NA
81
82 /* From now on we work in two pieces: an mmap()ed region from zero up to the
83 headersz, and a region updated via write() starting after that, containing
84 all the tables. Platforms that do not support mmap() just use write(). */
85 ctf_startoffs = headersz;
86 if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
87 {
5537f9b9
NA
88 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
89 goto err;
9402cc59
NA
90 }
91
92 if (write (fd, &dummy, 1) < 0)
93 {
5537f9b9
NA
94 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
95 goto err;
9402cc59
NA
96 }
97
98 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
99 {
5537f9b9
NA
100 errmsg = "ctf_arc_write(): Cannot mmap(): %s\n";
101 goto err;
9402cc59
NA
102 }
103
104 /* Fill in everything we can, which is everything other than the name
105 table offset. */
106 archdr->ctfa_magic = htole64 (CTFA_MAGIC);
107 archdr->ctfa_nfiles = htole64 (ctf_file_cnt);
108 archdr->ctfa_ctfs = htole64 (ctf_startoffs);
109
110 /* We could validate that all CTF files have the same data model, but
111 since any reasonable construction process will be building things of
112 only one bitness anyway, this is pretty pointless, so just use the
113 model of the first CTF file for all of them. (It *is* valid to
114 create an empty archive: the value of ctfa_model is irrelevant in
115 this case, but we must be sure not to dereference uninitialized
116 memory.) */
117
118 if (ctf_file_cnt > 0)
119 archdr->ctfa_model = htole64 (ctf_getmodel (ctf_files[0]));
120
121 /* Now write out the CTFs: ctf_archive_modent array via the mapping,
122 ctfs via write(). The names themselves have not been written yet: we
123 track them in a local strtab until the time is right, and sort the
124 modents array after construction.
125
126 The name table is not sorted. */
127
128 for (i = 0, namesz = 0; i < le64toh (archdr->ctfa_nfiles); i++)
129 namesz += strlen (names[i]) + 1;
130
131 nametbl = malloc (namesz);
132 if (nametbl == NULL)
133 {
5537f9b9 134 errmsg = "Error writing named CTF to archive: %s\n";
9402cc59
NA
135 goto err_unmap;
136 }
137
138 for (i = 0, namesz = 0,
139 modent = (ctf_archive_modent_t *) ((char *) archdr
140 + sizeof (struct ctf_archive));
141 i < le64toh (archdr->ctfa_nfiles); i++)
142 {
143 off_t off;
144
145 strcpy (&nametbl[namesz], names[i]);
146
147 off = arc_write_one_ctf (ctf_files[i], fd, threshold);
9402cc59
NA
148 if ((off < 0) && (off > -ECTF_BASE))
149 {
150 errmsg = "ctf_arc_write(): Cannot determine file "
5537f9b9 151 "position while writing to archive: %s";
9402cc59
NA
152 goto err_free;
153 }
154 if (off < 0)
155 {
5537f9b9 156 errmsg = "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
9402cc59
NA
157 errno = off * -1;
158 goto err_free;
159 }
160
161 modent->name_offset = htole64 (namesz);
162 modent->ctf_offset = htole64 (off - ctf_startoffs);
163 namesz += strlen (names[i]) + 1;
164 modent++;
165 }
166
6b22174f
NA
167 ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
168 + sizeof (struct ctf_archive)),
169 le64toh (archdr->ctfa_nfiles),
170 sizeof (struct ctf_archive_modent), sort_modent_by_name,
171 nametbl);
9402cc59
NA
172
173 /* Now the name table. */
174
175 if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
176 {
177 errmsg = "ctf_arc_write(): Cannot get current file position "
5537f9b9 178 "in archive: %s\n";
9402cc59
NA
179 goto err_free;
180 }
181 archdr->ctfa_names = htole64 (nameoffs);
182 np = nametbl;
183 while (namesz > 0)
184 {
185 ssize_t len;
186 if ((len = write (fd, np, namesz)) < 0)
187 {
5537f9b9 188 errmsg = "ctf_arc_write(): Cannot write name table to archive: %s\n";
9402cc59
NA
189 goto err_free;
190 }
191 namesz -= len;
192 np += len;
193 }
194 free (nametbl);
195
196 if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
197 goto err_unmap;
198 if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
5537f9b9 199 goto err;
9402cc59
NA
200 return 0;
201
202err_free:
203 free (nametbl);
204err_unmap:
205 arc_mmap_unmap (archdr, headersz, NULL);
9402cc59 206err:
5537f9b9 207 ctf_dprintf (errmsg, errno < ECTF_BASE ? strerror (errno) :
9402cc59
NA
208 ctf_errmsg (errno));
209 return errno;
210}
211
5537f9b9
NA
212/* Write out a CTF archive. The entries in CTF_FILES are referenced by name:
213 the names are passed in the names array, which must have CTF_FILES entries.
214
215 If the filename is NULL, create a temporary file and return a pointer to it.
216
217 Returns 0 on success, or an errno, or an ECTF_* value. */
218int
219ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
220 const char **names, size_t threshold)
221{
222 int err;
223 int fd;
224
225 if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
226 {
227 ctf_dprintf ("ctf_arc_write(): cannot create %s: %s\n", file,
228 strerror (errno));
229 return errno;
230 }
231
232 err = ctf_arc_write_fd (fd, ctf_files, ctf_file_cnt, names, threshold);
233 if (err)
234 goto err;
235
236 if ((err = close (fd)) < 0)
237 {
238 ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
239 "%s\n", strerror (errno));
240 goto err_close;
241 }
242
243 err:
244 close (fd);
245 if (err < 0)
246 unlink (file);
247
248 return err;
249
250 err_close:
251 if (err < 0)
252 unlink (file);
253
254 return err;
255}
256
9402cc59
NA
257/* Write one CTF file out. Return the file position of the written file (or
258 rather, of the file-size uint64_t that precedes it): negative return is a
259 negative errno or ctf_errno value. On error, the file position may no longer
260 be at the end of the file. */
261static off_t
262arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold)
263{
264 off_t off, end_off;
265 uint64_t ctfsz = 0;
266 char *ctfszp;
267 size_t ctfsz_len;
268 int (*writefn) (ctf_file_t * fp, int fd);
269
270 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
271 return errno * -1;
272
273 if (f->ctf_size > threshold)
274 writefn = ctf_compress_write;
275 else
276 writefn = ctf_write;
277
278 /* This zero-write turns into the size in a moment. */
279 ctfsz_len = sizeof (ctfsz);
280 ctfszp = (char *) &ctfsz;
281 while (ctfsz_len > 0)
282 {
283 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
284 if (writelen < 0)
285 return errno * -1;
286 ctfsz_len -= writelen;
287 ctfszp += writelen;
288 }
289
290 if (writefn (f, fd) != 0)
291 return f->ctf_errno * -1;
292
293 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
294 return errno * -1;
295 ctfsz = htole64 (end_off - off);
296
297 if ((lseek (fd, off, SEEK_SET)) < 0)
298 return errno * -1;
299
300 /* ... here. */
301 ctfsz_len = sizeof (ctfsz);
302 ctfszp = (char *) &ctfsz;
303 while (ctfsz_len > 0)
304 {
305 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
306 if (writelen < 0)
307 return errno * -1;
308 ctfsz_len -= writelen;
309 ctfszp += writelen;
310 }
311
312 end_off = LCTF_ALIGN_OFFS (end_off, 8);
313 if ((lseek (fd, end_off, SEEK_SET)) < 0)
314 return errno * -1;
315
316 return off;
317}
318
319/* qsort() function to sort the array of struct ctf_archive_modents into
320 ascending name order. */
321static int
322sort_modent_by_name (const void *one, const void *two, void *n)
323{
324 const struct ctf_archive_modent *a = one;
325 const struct ctf_archive_modent *b = two;
326 char *nametbl = n;
327
328 return strcmp (&nametbl[le64toh (a->name_offset)],
329 &nametbl[le64toh (b->name_offset)]);
330}
331
332/* bsearch() function to search for a given name in the sorted array of struct
333 ctf_archive_modents. */
334static int
335search_modent_by_name (const void *key, const void *ent)
336{
337 const char *k = key;
338 const struct ctf_archive_modent *v = ent;
339
340 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
341}
342
343/* A trivial wrapper: open a CTF archive, from data in a buffer (which the
344 caller must preserve until ctf_arc_close() time). Returns the archive, or
345 NULL and an error in *err (if not NULL). */
346struct ctf_archive *
347ctf_arc_bufopen (const void *buf, size_t size _libctf_unused_, int *errp)
348{
349 struct ctf_archive *arc = (struct ctf_archive *) buf;
350
351 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
352 {
353 if (errp)
354 *errp = ECTF_FMT;
355 return NULL;
356 }
357 return arc;
358}
359
360/* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
361 not NULL). */
362struct ctf_archive *
363ctf_arc_open_internal (const char *filename, int *errp)
364{
365 const char *errmsg;
366 int fd;
367 struct stat s;
368 struct ctf_archive *arc; /* (Actually the whole file.) */
369
370 libctf_init_debug();
371 if ((fd = open (filename, O_RDONLY)) < 0)
372 {
373 errmsg = "ctf_arc_open(): cannot open %s: %s\n";
374 goto err;
375 }
376 if (fstat (fd, &s) < 0)
377 {
378 errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
379 goto err_close;
380 }
381
382 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
383 {
384 errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
385 goto err_close;
386 }
387
388 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
389 {
390 errmsg = "ctf_arc_open(): Invalid magic number";
391 errno = ECTF_FMT;
392 goto err_unmap;
393 }
394
395 /* This horrible hack lets us know how much to unmap when the file is
396 closed. (We no longer need the magic number, and the mapping
397 is private.) */
398 arc->ctfa_magic = s.st_size;
399 close (fd);
400 return arc;
401
402err_unmap:
403 arc_mmap_unmap (arc, s.st_size, NULL);
404err_close:
405 close (fd);
406err:
407 if (errp)
408 *errp = errno;
409 ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
410 ctf_errmsg (errno));
411 return NULL;
412}
413
414/* Close an archive. */
415void
416ctf_arc_close_internal (struct ctf_archive *arc)
417{
418 if (arc == NULL)
419 return;
420
421 /* See the comment in ctf_arc_open(). */
422 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
423}
424
425/* Public entry point: close an archive, or CTF file. */
426void
427ctf_arc_close (ctf_archive_t *arc)
428{
429 if (arc == NULL)
430 return;
431
432 if (arc->ctfi_is_archive)
433 ctf_arc_close_internal (arc->ctfi_archive);
434 else
435 ctf_file_close (arc->ctfi_file);
436 free ((void *) arc->ctfi_symsect.cts_data);
6d5944fc 437 /* Do not free the ctfi_strsect: it is bound to the bfd. */
9402cc59 438 free (arc->ctfi_data);
f046147d
NA
439 if (arc->ctfi_bfd_close)
440 arc->ctfi_bfd_close (arc);
9402cc59
NA
441 free (arc);
442}
443
444/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
445 non-NULL. A name of NULL means to open the default file. */
446static ctf_file_t *
447ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
448 const ctf_sect_t *symsect,
449 const ctf_sect_t *strsect,
450 const char *name, int *errp)
451{
452 struct ctf_archive_modent *modent;
453
454 if (name == NULL)
455 name = _CTF_SECTION; /* The default name. */
456
457 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
458
459 modent = (ctf_archive_modent_t *) ((char *) arc
460 + sizeof (struct ctf_archive));
461
462 search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
463 modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
464 sizeof (struct ctf_archive_modent),
465 search_modent_by_name);
466
467 /* This is actually a common case and normal operation: no error
468 debug output. */
469 if (modent == NULL)
470 {
471 if (errp)
472 *errp = ECTF_ARNNAME;
473 return NULL;
474 }
475
476 return ctf_arc_open_by_offset (arc, symsect, strsect,
477 le64toh (modent->ctf_offset), errp);
478}
479
480/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
481 non-NULL. A name of NULL means to open the default file.
482
483 Use the specified string and symbol table sections.
484
485 Public entry point. */
486ctf_file_t *
487ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
488 const ctf_sect_t *symsect,
489 const ctf_sect_t *strsect,
490 const char *name,
491 int *errp)
492{
493 if (arc->ctfi_is_archive)
494 {
495 ctf_file_t *ret;
496 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
497 name, errp);
498 if (ret)
499 ret->ctf_archive = (ctf_archive_t *) arc;
500 return ret;
501 }
502
503 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
504 {
505 if (errp)
506 *errp = ECTF_ARNNAME;
507 return NULL;
508 }
509 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
510
511 /* Bump the refcount so that the user can ctf_file_close() it. */
512 arc->ctfi_file->ctf_refcnt++;
513 return arc->ctfi_file;
514}
515
516/* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
517 non-NULL. A name of NULL means to open the default file.
518
519 Public entry point. */
520ctf_file_t *
521ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
522{
523 const ctf_sect_t *symsect = &arc->ctfi_symsect;
524 const ctf_sect_t *strsect = &arc->ctfi_strsect;
525
526 if (symsect->cts_name == NULL)
527 symsect = NULL;
528 if (strsect->cts_name == NULL)
529 strsect = NULL;
530
531 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
532}
533
534/* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
535 none, setting 'err' if non-NULL. */
536static ctf_file_t *
537ctf_arc_open_by_offset (const struct ctf_archive *arc,
538 const ctf_sect_t *symsect,
539 const ctf_sect_t *strsect, size_t offset,
540 int *errp)
541{
542 ctf_sect_t ctfsect;
543 ctf_file_t *fp;
544
62d8e3b7 545 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
9402cc59 546
a0486bac 547 memset (&ctfsect, 0, sizeof (ctf_sect_t));
9402cc59
NA
548
549 offset += le64toh (arc->ctfa_ctfs);
550
551 ctfsect.cts_name = _CTF_SECTION;
9402cc59
NA
552 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
553 ctfsect.cts_entsize = 1;
9402cc59
NA
554 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
555 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
556 if (fp)
557 ctf_setmodel (fp, le64toh (arc->ctfa_model));
558 return fp;
559}
560
561/* Raw iteration over all CTF files in an archive. We pass the raw data for all
562 CTF files in turn to the specified callback function. */
563static int
564ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
565 ctf_archive_raw_member_f *func, void *data)
566{
567 int rc;
568 size_t i;
569 struct ctf_archive_modent *modent;
570 const char *nametbl;
571
572 modent = (ctf_archive_modent_t *) ((char *) arc
573 + sizeof (struct ctf_archive));
574 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
575
576 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
577 {
578 const char *name;
579 char *fp;
580
581 name = &nametbl[le64toh (modent[i].name_offset)];
582 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
583 + le64toh (modent[i].ctf_offset));
584
585 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
586 le64toh (*((uint64_t *) fp)), data)) != 0)
587 return rc;
588 }
589 return 0;
590}
591
592/* Raw iteration over all CTF files in an archive: public entry point.
593
594 Returns -EINVAL if not supported for this sort of archive. */
595int
596ctf_archive_raw_iter (const ctf_archive_t *arc,
597 ctf_archive_raw_member_f * func, void *data)
598{
599 if (arc->ctfi_is_archive)
600 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
601
602 return -EINVAL; /* Not supported. */
603}
604
605/* Iterate over all CTF files in an archive. We pass all CTF files in turn to
606 the specified callback function. */
607static int
608ctf_archive_iter_internal (const ctf_archive_t *wrapper,
609 const struct ctf_archive *arc,
610 const ctf_sect_t *symsect,
611 const ctf_sect_t *strsect,
612 ctf_archive_member_f *func, void *data)
613{
614 int rc;
615 size_t i;
616 ctf_file_t *f;
617 struct ctf_archive_modent *modent;
618 const char *nametbl;
619
620 modent = (ctf_archive_modent_t *) ((char *) arc
621 + sizeof (struct ctf_archive));
622 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
623
624 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
625 {
626 const char *name;
627
628 name = &nametbl[le64toh (modent[i].name_offset)];
629 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
630 name, &rc)) == NULL)
631 return rc;
632
633 f->ctf_archive = (ctf_archive_t *) wrapper;
634 if ((rc = func (f, name, data)) != 0)
635 {
636 ctf_file_close (f);
637 return rc;
638 }
639
640 ctf_file_close (f);
641 }
642 return 0;
643}
644
645/* Iterate over all CTF files in an archive: public entry point. We pass all
646 CTF files in turn to the specified callback function. */
647int
648ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
649 void *data)
650{
651 const ctf_sect_t *symsect = &arc->ctfi_symsect;
652 const ctf_sect_t *strsect = &arc->ctfi_strsect;
653
654 if (symsect->cts_name == NULL)
655 symsect = NULL;
656 if (strsect->cts_name == NULL)
657 strsect = NULL;
658
659 if (arc->ctfi_is_archive)
660 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
661 func, data);
662
663 return func (arc->ctfi_file, _CTF_SECTION, data);
664}
665
666#ifdef HAVE_MMAP
667/* Map the header in. Only used on new, empty files. */
668static void *arc_mmap_header (int fd, size_t headersz)
669{
670 void *hdr;
671 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
672 0)) == MAP_FAILED)
673 return NULL;
674 return hdr;
675}
676
677/* mmap() the whole file, for reading only. (Map it writably, but privately: we
678 need to modify the region, but don't need anyone else to see the
679 modifications.) */
680static void *arc_mmap_file (int fd, size_t size)
681{
682 void *arc;
683 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
684 fd, 0)) == MAP_FAILED)
685 return NULL;
686 return arc;
687}
688
689/* Persist the header to disk. */
690static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
691 size_t headersz, const char **errmsg)
692{
693 if (msync (header, headersz, MS_ASYNC) < 0)
694 {
695 if (errmsg)
696 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
697 return -1;
698 }
699 return 0;
700}
701
702/* Unmap the region. */
703static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
704{
705 if (munmap (header, headersz) < 0)
706 {
707 if (errmsg)
708 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
709 return -1;
710 }
711 return 0;
712}
713#else
714/* Map the header in. Only used on new, empty files. */
f5e73be1 715static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
9402cc59
NA
716{
717 void *hdr;
718 if ((hdr = malloc (headersz)) == NULL)
719 return NULL;
720 return hdr;
721}
722
723/* Pull in the whole file, for reading only. We assume the current file
724 position is at the start of the file. */
725static void *arc_mmap_file (int fd, size_t size)
726{
727 char *data;
728
729 if ((data = malloc (size)) == NULL)
730 return NULL;
731
732 if (ctf_pread (fd, data, size, 0) < 0)
733 {
734 free (data);
735 return NULL;
736 }
737 return data;
738}
739
740/* Persist the header to disk. */
741static int arc_mmap_writeout (int fd, void *header, size_t headersz,
742 const char **errmsg)
743{
744 ssize_t len;
745 size_t acc = 0;
746 char *data = (char *) header;
747 ssize_t count = headersz;
748
749 if ((lseek (fd, 0, SEEK_SET)) < 0)
750 {
751 if (errmsg)
752 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
753 "%s: %s\n";
754 return -1;
755 }
756
757 while (headersz > 0)
758 {
759 if ((len = write (fd, data, count)) < 0)
760 {
761 if (errmsg)
762 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
763 return len;
764 }
765 if (len == EINTR)
766 continue;
767
768 acc += len;
769 if (len == 0) /* EOF. */
770 break;
771
772 count -= len;
773 data += len;
774 }
775 return 0;
776}
777
778/* Unmap the region. */
779static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
780 const char **errmsg _libctf_unused_)
781{
782 free (header);
783 return 0;
784}
785#endif
This page took 0.0758 seconds and 4 git commands to generate.