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