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