gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / libctf / ctf-archive.c
1 /* CTF archive files.
2 Copyright (C) 2019-2020 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 (ctf_serialize (f) < 0)
271 return f->ctf_errno * -1;
272
273 if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
274 return errno * -1;
275
276 if (f->ctf_size > threshold)
277 writefn = ctf_compress_write;
278 else
279 writefn = ctf_write;
280
281 /* This zero-write turns into the size in a moment. */
282 ctfsz_len = sizeof (ctfsz);
283 ctfszp = (char *) &ctfsz;
284 while (ctfsz_len > 0)
285 {
286 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
287 if (writelen < 0)
288 return errno * -1;
289 ctfsz_len -= writelen;
290 ctfszp += writelen;
291 }
292
293 if (writefn (f, fd) != 0)
294 return f->ctf_errno * -1;
295
296 if ((end_off = lseek (fd, 0, SEEK_CUR)) < 0)
297 return errno * -1;
298 ctfsz = htole64 (end_off - off);
299
300 if ((lseek (fd, off, SEEK_SET)) < 0)
301 return errno * -1;
302
303 /* ... here. */
304 ctfsz_len = sizeof (ctfsz);
305 ctfszp = (char *) &ctfsz;
306 while (ctfsz_len > 0)
307 {
308 ssize_t writelen = write (fd, ctfszp, ctfsz_len);
309 if (writelen < 0)
310 return errno * -1;
311 ctfsz_len -= writelen;
312 ctfszp += writelen;
313 }
314
315 end_off = LCTF_ALIGN_OFFS (end_off, 8);
316 if ((lseek (fd, end_off, SEEK_SET)) < 0)
317 return errno * -1;
318
319 return off;
320 }
321
322 /* qsort() function to sort the array of struct ctf_archive_modents into
323 ascending name order. */
324 static int
325 sort_modent_by_name (const void *one, const void *two, void *n)
326 {
327 const struct ctf_archive_modent *a = one;
328 const struct ctf_archive_modent *b = two;
329 char *nametbl = n;
330
331 return strcmp (&nametbl[le64toh (a->name_offset)],
332 &nametbl[le64toh (b->name_offset)]);
333 }
334
335 /* bsearch() function to search for a given name in the sorted array of struct
336 ctf_archive_modents. */
337 static int
338 search_modent_by_name (const void *key, const void *ent)
339 {
340 const char *k = key;
341 const struct ctf_archive_modent *v = ent;
342
343 return strcmp (k, &search_nametbl[le64toh (v->name_offset)]);
344 }
345
346 /* A trivial wrapper: open a CTF archive, from data in a buffer (which the
347 caller must preserve until ctf_arc_close() time). Returns the archive, or
348 NULL and an error in *err (if not NULL). */
349 struct ctf_archive *
350 ctf_arc_bufopen (const void *buf, size_t size _libctf_unused_, int *errp)
351 {
352 struct ctf_archive *arc = (struct ctf_archive *) buf;
353
354 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
355 {
356 if (errp)
357 *errp = ECTF_FMT;
358 return NULL;
359 }
360 return arc;
361 }
362
363 /* Open a CTF archive. Returns the archive, or NULL and an error in *err (if
364 not NULL). */
365 struct ctf_archive *
366 ctf_arc_open_internal (const char *filename, int *errp)
367 {
368 const char *errmsg;
369 int fd;
370 struct stat s;
371 struct ctf_archive *arc; /* (Actually the whole file.) */
372
373 libctf_init_debug();
374 if ((fd = open (filename, O_RDONLY)) < 0)
375 {
376 errmsg = "ctf_arc_open(): cannot open %s: %s\n";
377 goto err;
378 }
379 if (fstat (fd, &s) < 0)
380 {
381 errmsg = "ctf_arc_open(): cannot stat %s: %s\n";
382 goto err_close;
383 }
384
385 if ((arc = arc_mmap_file (fd, s.st_size)) == NULL)
386 {
387 errmsg = "ctf_arc_open(): Cannot read in %s: %s\n";
388 goto err_close;
389 }
390
391 if (le64toh (arc->ctfa_magic) != CTFA_MAGIC)
392 {
393 errmsg = "ctf_arc_open(): Invalid magic number";
394 errno = ECTF_FMT;
395 goto err_unmap;
396 }
397
398 /* This horrible hack lets us know how much to unmap when the file is
399 closed. (We no longer need the magic number, and the mapping
400 is private.) */
401 arc->ctfa_magic = s.st_size;
402 close (fd);
403 return arc;
404
405 err_unmap:
406 arc_mmap_unmap (arc, s.st_size, NULL);
407 err_close:
408 close (fd);
409 err:
410 if (errp)
411 *errp = errno;
412 ctf_dprintf (errmsg, filename, errno < ECTF_BASE ? strerror (errno) :
413 ctf_errmsg (errno));
414 return NULL;
415 }
416
417 /* Close an archive. */
418 void
419 ctf_arc_close_internal (struct ctf_archive *arc)
420 {
421 if (arc == NULL)
422 return;
423
424 /* See the comment in ctf_arc_open(). */
425 arc_mmap_unmap (arc, arc->ctfa_magic, NULL);
426 }
427
428 /* Public entry point: close an archive, or CTF file. */
429 void
430 ctf_arc_close (ctf_archive_t *arc)
431 {
432 if (arc == NULL)
433 return;
434
435 if (arc->ctfi_is_archive)
436 ctf_arc_close_internal (arc->ctfi_archive);
437 else
438 ctf_file_close (arc->ctfi_file);
439 free ((void *) arc->ctfi_symsect.cts_data);
440 /* Do not free the ctfi_strsect: it is bound to the bfd. */
441 free (arc->ctfi_data);
442 if (arc->ctfi_bfd_close)
443 arc->ctfi_bfd_close (arc);
444 free (arc);
445 }
446
447 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
448 non-NULL. A name of NULL means to open the default file. */
449 static ctf_file_t *
450 ctf_arc_open_by_name_internal (const struct ctf_archive *arc,
451 const ctf_sect_t *symsect,
452 const ctf_sect_t *strsect,
453 const char *name, int *errp)
454 {
455 struct ctf_archive_modent *modent;
456
457 if (name == NULL)
458 name = _CTF_SECTION; /* The default name. */
459
460 ctf_dprintf ("ctf_arc_open_by_name(%s): opening\n", name);
461
462 modent = (ctf_archive_modent_t *) ((char *) arc
463 + sizeof (struct ctf_archive));
464
465 search_nametbl = (char *) arc + le64toh (arc->ctfa_names);
466 modent = bsearch (name, modent, le64toh (arc->ctfa_nfiles),
467 sizeof (struct ctf_archive_modent),
468 search_modent_by_name);
469
470 /* This is actually a common case and normal operation: no error
471 debug output. */
472 if (modent == NULL)
473 {
474 if (errp)
475 *errp = ECTF_ARNNAME;
476 return NULL;
477 }
478
479 return ctf_arc_open_by_offset (arc, symsect, strsect,
480 le64toh (modent->ctf_offset), errp);
481 }
482
483 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
484 non-NULL. A name of NULL means to open the default file.
485
486 Use the specified string and symbol table sections.
487
488 Public entry point. */
489 ctf_file_t *
490 ctf_arc_open_by_name_sections (const ctf_archive_t *arc,
491 const ctf_sect_t *symsect,
492 const ctf_sect_t *strsect,
493 const char *name,
494 int *errp)
495 {
496 if (arc->ctfi_is_archive)
497 {
498 ctf_file_t *ret;
499 ret = ctf_arc_open_by_name_internal (arc->ctfi_archive, symsect, strsect,
500 name, errp);
501 if (ret)
502 ret->ctf_archive = (ctf_archive_t *) arc;
503 return ret;
504 }
505
506 if ((name != NULL) && (strcmp (name, _CTF_SECTION) != 0))
507 {
508 if (errp)
509 *errp = ECTF_ARNNAME;
510 return NULL;
511 }
512 arc->ctfi_file->ctf_archive = (ctf_archive_t *) arc;
513
514 /* Bump the refcount so that the user can ctf_file_close() it. */
515 arc->ctfi_file->ctf_refcnt++;
516 return arc->ctfi_file;
517 }
518
519 /* Return the ctf_file_t with the given name, or NULL if none, setting 'err' if
520 non-NULL. A name of NULL means to open the default file.
521
522 Public entry point. */
523 ctf_file_t *
524 ctf_arc_open_by_name (const ctf_archive_t *arc, const char *name, int *errp)
525 {
526 const ctf_sect_t *symsect = &arc->ctfi_symsect;
527 const ctf_sect_t *strsect = &arc->ctfi_strsect;
528
529 if (symsect->cts_name == NULL)
530 symsect = NULL;
531 if (strsect->cts_name == NULL)
532 strsect = NULL;
533
534 return ctf_arc_open_by_name_sections (arc, symsect, strsect, name, errp);
535 }
536
537 /* Return the ctf_file_t at the given ctfa_ctfs-relative offset, or NULL if
538 none, setting 'err' if non-NULL. */
539 static ctf_file_t *
540 ctf_arc_open_by_offset (const struct ctf_archive *arc,
541 const ctf_sect_t *symsect,
542 const ctf_sect_t *strsect, size_t offset,
543 int *errp)
544 {
545 ctf_sect_t ctfsect;
546 ctf_file_t *fp;
547
548 ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
549
550 memset (&ctfsect, 0, sizeof (ctf_sect_t));
551
552 offset += le64toh (arc->ctfa_ctfs);
553
554 ctfsect.cts_name = _CTF_SECTION;
555 ctfsect.cts_size = le64toh (*((uint64_t *) ((char *) arc + offset)));
556 ctfsect.cts_entsize = 1;
557 ctfsect.cts_data = (void *) ((char *) arc + offset + sizeof (uint64_t));
558 fp = ctf_bufopen (&ctfsect, symsect, strsect, errp);
559 if (fp)
560 ctf_setmodel (fp, le64toh (arc->ctfa_model));
561 return fp;
562 }
563
564 /* Raw iteration over all CTF files in an archive. We pass the raw data for all
565 CTF files in turn to the specified callback function. */
566 static int
567 ctf_archive_raw_iter_internal (const struct ctf_archive *arc,
568 ctf_archive_raw_member_f *func, void *data)
569 {
570 int rc;
571 size_t i;
572 struct ctf_archive_modent *modent;
573 const char *nametbl;
574
575 modent = (ctf_archive_modent_t *) ((char *) arc
576 + sizeof (struct ctf_archive));
577 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
578
579 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
580 {
581 const char *name;
582 char *fp;
583
584 name = &nametbl[le64toh (modent[i].name_offset)];
585 fp = ((char *) arc + le64toh (arc->ctfa_ctfs)
586 + le64toh (modent[i].ctf_offset));
587
588 if ((rc = func (name, (void *) (fp + sizeof (uint64_t)),
589 le64toh (*((uint64_t *) fp)), data)) != 0)
590 return rc;
591 }
592 return 0;
593 }
594
595 /* Raw iteration over all CTF files in an archive: public entry point.
596
597 Returns -EINVAL if not supported for this sort of archive. */
598 int
599 ctf_archive_raw_iter (const ctf_archive_t *arc,
600 ctf_archive_raw_member_f * func, void *data)
601 {
602 if (arc->ctfi_is_archive)
603 return ctf_archive_raw_iter_internal (arc->ctfi_archive, func, data);
604
605 return -EINVAL; /* Not supported. */
606 }
607
608 /* Iterate over all CTF files in an archive. We pass all CTF files in turn to
609 the specified callback function. */
610 static int
611 ctf_archive_iter_internal (const ctf_archive_t *wrapper,
612 const struct ctf_archive *arc,
613 const ctf_sect_t *symsect,
614 const ctf_sect_t *strsect,
615 ctf_archive_member_f *func, void *data)
616 {
617 int rc;
618 size_t i;
619 ctf_file_t *f;
620 struct ctf_archive_modent *modent;
621 const char *nametbl;
622
623 modent = (ctf_archive_modent_t *) ((char *) arc
624 + sizeof (struct ctf_archive));
625 nametbl = (((const char *) arc) + le64toh (arc->ctfa_names));
626
627 for (i = 0; i < le64toh (arc->ctfa_nfiles); i++)
628 {
629 const char *name;
630
631 name = &nametbl[le64toh (modent[i].name_offset)];
632 if ((f = ctf_arc_open_by_name_internal (arc, symsect, strsect,
633 name, &rc)) == NULL)
634 return rc;
635
636 f->ctf_archive = (ctf_archive_t *) wrapper;
637 if ((rc = func (f, name, data)) != 0)
638 {
639 ctf_file_close (f);
640 return rc;
641 }
642
643 ctf_file_close (f);
644 }
645 return 0;
646 }
647
648 /* Iterate over all CTF files in an archive: public entry point. We pass all
649 CTF files in turn to the specified callback function. */
650 int
651 ctf_archive_iter (const ctf_archive_t *arc, ctf_archive_member_f *func,
652 void *data)
653 {
654 const ctf_sect_t *symsect = &arc->ctfi_symsect;
655 const ctf_sect_t *strsect = &arc->ctfi_strsect;
656
657 if (symsect->cts_name == NULL)
658 symsect = NULL;
659 if (strsect->cts_name == NULL)
660 strsect = NULL;
661
662 if (arc->ctfi_is_archive)
663 return ctf_archive_iter_internal (arc, arc->ctfi_archive, symsect, strsect,
664 func, data);
665
666 return func (arc->ctfi_file, _CTF_SECTION, data);
667 }
668
669 #ifdef HAVE_MMAP
670 /* Map the header in. Only used on new, empty files. */
671 static void *arc_mmap_header (int fd, size_t headersz)
672 {
673 void *hdr;
674 if ((hdr = mmap (NULL, headersz, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
675 0)) == MAP_FAILED)
676 return NULL;
677 return hdr;
678 }
679
680 /* mmap() the whole file, for reading only. (Map it writably, but privately: we
681 need to modify the region, but don't need anyone else to see the
682 modifications.) */
683 static void *arc_mmap_file (int fd, size_t size)
684 {
685 void *arc;
686 if ((arc = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
687 fd, 0)) == MAP_FAILED)
688 return NULL;
689 return arc;
690 }
691
692 /* Persist the header to disk. */
693 static int arc_mmap_writeout (int fd _libctf_unused_, void *header,
694 size_t headersz, const char **errmsg)
695 {
696 if (msync (header, headersz, MS_ASYNC) < 0)
697 {
698 if (errmsg)
699 *errmsg = "arc_mmap_writeout(): Cannot sync after writing to %s: %s\n";
700 return -1;
701 }
702 return 0;
703 }
704
705 /* Unmap the region. */
706 static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg)
707 {
708 if (munmap (header, headersz) < 0)
709 {
710 if (errmsg)
711 *errmsg = "arc_mmap_munmap(): Cannot unmap after writing to %s: %s\n";
712 return -1;
713 }
714 return 0;
715 }
716 #else
717 /* Map the header in. Only used on new, empty files. */
718 static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
719 {
720 void *hdr;
721 if ((hdr = malloc (headersz)) == NULL)
722 return NULL;
723 return hdr;
724 }
725
726 /* Pull in the whole file, for reading only. We assume the current file
727 position is at the start of the file. */
728 static void *arc_mmap_file (int fd, size_t size)
729 {
730 char *data;
731
732 if ((data = malloc (size)) == NULL)
733 return NULL;
734
735 if (ctf_pread (fd, data, size, 0) < 0)
736 {
737 free (data);
738 return NULL;
739 }
740 return data;
741 }
742
743 /* Persist the header to disk. */
744 static int arc_mmap_writeout (int fd, void *header, size_t headersz,
745 const char **errmsg)
746 {
747 ssize_t len;
748 size_t acc = 0;
749 char *data = (char *) header;
750 ssize_t count = headersz;
751
752 if ((lseek (fd, 0, SEEK_SET)) < 0)
753 {
754 if (errmsg)
755 *errmsg = "arc_mmap_writeout(): Cannot seek while writing header to "
756 "%s: %s\n";
757 return -1;
758 }
759
760 while (headersz > 0)
761 {
762 if ((len = write (fd, data, count)) < 0)
763 {
764 if (errmsg)
765 *errmsg = "arc_mmap_writeout(): Cannot write header to %s: %s\n";
766 return len;
767 }
768 if (len == EINTR)
769 continue;
770
771 acc += len;
772 if (len == 0) /* EOF. */
773 break;
774
775 count -= len;
776 data += len;
777 }
778 return 0;
779 }
780
781 /* Unmap the region. */
782 static int arc_mmap_unmap (void *header, size_t headersz _libctf_unused_,
783 const char **errmsg _libctf_unused_)
784 {
785 free (header);
786 return 0;
787 }
788 #endif
This page took 0.045883 seconds and 4 git commands to generate.