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