libctf: map from old to corresponding newly-added types in ctf_add_type
[deliverable/binutils-gdb.git] / libctf / ctf-archive.c
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>
24 #include "ctf-endian.h"
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
35 static off_t arc_write_one_ctf (ctf_file_t * f, int fd, size_t threshold);
36 static 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);
40 static int sort_modent_by_name (const void *one, const void *two, void *n);
41 static void *arc_mmap_header (int fd, size_t headersz);
42 static void *arc_mmap_file (int fd, size_t size);
43 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
44 const char **errmsg);
45 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg);
46
47 /* bsearch() internal state. */
48 static __thread char *search_nametbl;
49
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.
53
54 Returns 0 on success, or an errno, or an ECTF_* value. */
55 int
56 ctf_arc_write_fd (int fd, ctf_file_t **ctf_files, size_t ctf_file_cnt,
57 const char **names, size_t threshold)
58 {
59 const char *errmsg;
60 struct ctf_archive *archdr;
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
71 ctf_dprintf ("Writing CTF archive with %lu files\n",
72 (unsigned long) ctf_file_cnt);
73
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);
80 ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
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 {
88 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
89 goto err;
90 }
91
92 if (write (fd, &dummy, 1) < 0)
93 {
94 errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
95 goto err;
96 }
97
98 if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
99 {
100 errmsg = "ctf_arc_write(): Cannot mmap(): %s\n";
101 goto err;
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 {
134 errmsg = "Error writing named CTF to archive: %s\n";
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);
148 if ((off < 0) && (off > -ECTF_BASE))
149 {
150 errmsg = "ctf_arc_write(): Cannot determine file "
151 "position while writing to archive: %s";
152 goto err_free;
153 }
154 if (off < 0)
155 {
156 errmsg = "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
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
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);
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 "
178 "in archive: %s\n";
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 {
188 errmsg = "ctf_arc_write(): Cannot write name table to archive: %s\n";
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)
199 goto err;
200 return 0;
201
202 err_free:
203 free (nametbl);
204 err_unmap:
205 arc_mmap_unmap (archdr, headersz, NULL);
206 err:
207 ctf_dprintf (errmsg, errno < ECTF_BASE ? strerror (errno) :
208 ctf_errmsg (errno));
209 return errno;
210 }
211
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. */
218 int
219 ctf_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
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. */
261 static off_t
262 arc_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. */
321 static int
322 sort_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. */
334 static int
335 search_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). */
346 struct ctf_archive *
347 ctf_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). */
362 struct ctf_archive *
363 ctf_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
402 err_unmap:
403 arc_mmap_unmap (arc, s.st_size, NULL);
404 err_close:
405 close (fd);
406 err:
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. */
415 void
416 ctf_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. */
426 void
427 ctf_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);
437 /* Do not free the ctfi_strsect: it is bound to the bfd. */
438 free (arc->ctfi_data);
439 free (arc);
440 }
441
442 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
443 non-NULL. A name of NULL means to open the default file. */
444 static ctf_file_t *
445 ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
446 const ctf_sect_t *symsect,
447 const ctf_sect_t *strsect,
448 const char *name, int *errp)
449 {
450 struct ctf_archive_modent *modent;
451
452 if (name == NULL)
453 name = _CTF_SECTION; /* The default name. */
454
455 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
456
457 modent = (ctf_archive_modent_t *) ((char *) arc
458 + sizeof (struct ctf_archive));
459
460 search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
461 modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
462 sizeof (struct ctf_archive_modent),
463 search_modent_by_name);
464
465 /* This is actually a common case and normal operation: no error
466 debug output. */
467 if (modent == NULL)
468 {
469 if (errp)
470 *errp = ECTF_ARNNAME;
471 return NULL;
472 }
473
474 return ctf_arc_open_by_offset (arc, symsect, strsect,
475 le64toh (modent->ctf_offset), errp);
476 }
477
478 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
479 non-NULL. A name of NULL means to open the default file.
480
481 Use the specified string and symbol table sections.
482
483 Public entry point. */
484 ctf_file_t *
485 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
486 const ctf_sect_t *symsect,
487 const ctf_sect_t *strsect,
488 const char *name,
489 int *errp)
490 {
491 if (arc->ctfi_is_archive)
492 {
493 ctf_file_t *ret;
494 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
495 name, errp);
496 if (ret)
497 ret->ctf_archive = (ctf_archive_t *) arc;
498 return ret;
499 }
500
501 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
502 {
503 if (errp)
504 *errp = ECTF_ARNNAME;
505 return NULL;
506 }
507 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
508
509 /* Bump the refcount so that the user can ctf_file_close() it. */
510 arc->ctfi_file->ctf_refcnt++;
511 return arc->ctfi_file;
512 }
513
514 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
515 non-NULL. A name of NULL means to open the default file.
516
517 Public entry point. */
518 ctf_file_t *
519 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
520 {
521 const ctf_sect_t *symsect = &arc->ctfi_symsect;
522 const ctf_sect_t *strsect = &arc->ctfi_strsect;
523
524 if (symsect->cts_name == NULL)
525 symsect = NULL;
526 if (strsect->cts_name == NULL)
527 strsect = NULL;
528
529 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
530 }
531
532 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
533 none, setting 'err' if non-NULL. */
534 static ctf_file_t *
535 ctf_arc_open_by_offset (const struct ctf_archive *arc,
536 const ctf_sect_t *symsect,
537 const ctf_sect_t *strsect, size_t offset,
538 int *errp)
539 {
540 ctf_sect_t ctfsect;
541 ctf_file_t *fp;
542
543 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
544
545 memset (&ctfsect, 0, sizeof (ctf_sect_t));
546
547 offset += le64toh (arc->ctfa_ctfs);
548
549 ctfsect.cts_name = _CTF_SECTION;
550 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
551 ctfsect.cts_entsize = 1;
552 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
553 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
554 if (fp)
555 ctf_setmodel (fp, le64toh (arc->ctfa_model));
556 return fp;
557 }
558
559 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
560 CTF files in turn to the specified callback function. */
561 static int
562 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
563 ctf_archive_raw_member_f *func, void *data)
564 {
565 int rc;
566 size_t i;
567 struct ctf_archive_modent *modent;
568 const char *nametbl;
569
570 modent = (ctf_archive_modent_t *) ((char *) arc
571 + sizeof (struct ctf_archive));
572 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
573
574 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
575 {
576 const char *name;
577 char *fp;
578
579 name = &nametbl[le64toh (modent[i].name_offset)];
580 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
581 + le64toh (modent[i].ctf_offset));
582
583 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
584 le64toh (*((uint64_t *) fp)), data)) != 0)
585 return rc;
586 }
587 return 0;
588 }
589
590 /* Raw iteration over all CTF files in an archive: public entry point.
591
592 Returns -EINVAL if not supported for this sort of archive. */
593 int
594 ctf_archive_raw_iter (const ctf_archive_t *arc,
595 ctf_archive_raw_member_f * func, void *data)
596 {
597 if (arc->ctfi_is_archive)
598 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
599
600 return -EINVAL; /* Not supported. */
601 }
602
603 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
604 the specified callback function. */
605 static int
606 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
607 const struct ctf_archive *arc,
608 const ctf_sect_t *symsect,
609 const ctf_sect_t *strsect,
610 ctf_archive_member_f *func, void *data)
611 {
612 int rc;
613 size_t i;
614 ctf_file_t *f;
615 struct ctf_archive_modent *modent;
616 const char *nametbl;
617
618 modent = (ctf_archive_modent_t *) ((char *) arc
619 + sizeof (struct ctf_archive));
620 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
621
622 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
623 {
624 const char *name;
625
626 name = &nametbl[le64toh (modent[i].name_offset)];
627 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
628 name, &rc)) == NULL)
629 return rc;
630
631 f->ctf_archive = (ctf_archive_t *) wrapper;
632 if ((rc = func (f, name, data)) != 0)
633 {
634 ctf_file_close (f);
635 return rc;
636 }
637
638 ctf_file_close (f);
639 }
640 return 0;
641 }
642
643 /* Iterate over all CTF files in an archive: public entry point. We pass all
644 CTF files in turn to the specified callback function. */
645 int
646 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
647 void *data)
648 {
649 const ctf_sect_t *symsect = &arc->ctfi_symsect;
650 const ctf_sect_t *strsect = &arc->ctfi_strsect;
651
652 if (symsect->cts_name == NULL)
653 symsect = NULL;
654 if (strsect->cts_name == NULL)
655 strsect = NULL;
656
657 if (arc->ctfi_is_archive)
658 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
659 func, data);
660
661 return func (arc->ctfi_file, _CTF_SECTION, data);
662 }
663
664 #ifdef HAVE_MMAP
665 /* Map the header in. Only used on new, empty files. */
666 static void *arc_mmap_header (int fd, size_t headersz)
667 {
668 void *hdr;
669 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
670 0)) == MAP_FAILED)
671 return NULL;
672 return hdr;
673 }
674
675 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
676 need to modify the region, but don't need anyone else to see the
677 modifications.) */
678 static void *arc_mmap_file (int fd, size_t size)
679 {
680 void *arc;
681 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
682 fd, 0)) == MAP_FAILED)
683 return NULL;
684 return arc;
685 }
686
687 /* Persist the header to disk. */
688 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
689 size_t headersz, const char **errmsg)
690 {
691 if (msync (header, headersz, MS_ASYNC) < 0)
692 {
693 if (errmsg)
694 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
695 return -1;
696 }
697 return 0;
698 }
699
700 /* Unmap the region. */
701 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
702 {
703 if (munmap (header, headersz) < 0)
704 {
705 if (errmsg)
706 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
707 return -1;
708 }
709 return 0;
710 }
711 #else
712 /* Map the header in. Only used on new, empty files. */
713 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
714 {
715 void *hdr;
716 if ((hdr = malloc (headersz)) == NULL)
717 return NULL;
718 return hdr;
719 }
720
721 /* Pull in the whole file, for reading only. We assume the current file
722 position is at the start of the file. */
723 static void *arc_mmap_file (int fd, size_t size)
724 {
725 char *data;
726
727 if ((data = malloc (size)) == NULL)
728 return NULL;
729
730 if (ctf_pread (fd, data, size, 0) < 0)
731 {
732 free (data);
733 return NULL;
734 }
735 return data;
736 }
737
738 /* Persist the header to disk. */
739 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
740 const char **errmsg)
741 {
742 ssize_t len;
743 size_t acc = 0;
744 char *data = (char *) header;
745 ssize_t count = headersz;
746
747 if ((lseek (fd, 0, SEEK_SET)) < 0)
748 {
749 if (errmsg)
750 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
751 "%s: %s\n";
752 return -1;
753 }
754
755 while (headersz > 0)
756 {
757 if ((len = write (fd, data, count)) < 0)
758 {
759 if (errmsg)
760 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
761 return len;
762 }
763 if (len == EINTR)
764 continue;
765
766 acc += len;
767 if (len == 0) /* EOF. */
768 break;
769
770 count -= len;
771 data += len;
772 }
773 return 0;
774 }
775
776 /* Unmap the region. */
777 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
778 const char **errmsg _libctf_unused_)
779 {
780 free (header);
781 return 0;
782 }
783 #endif
This page took 0.057698 seconds and 4 git commands to generate.