Revert patch that disables building libctf for non-ELF based targets.
[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   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