libctf: work on platforms without O_CLOEXEC.
[external/binutils.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