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