/* bsearch() internal state. */
static __thread char *search_nametbl;
-/* Write out a CTF archive. The entries in CTF_FILES are referenced by name:
- the names are passed in the names array, which must have CTF_FILES entries.
+/* Write out a CTF archive to the start of the file referenced by the passed-in
+ fd. The entries in CTF_FILES are referenced by name: the names are passed in
+ the names array, which must have CTF_FILES entries.
Returns 0 on success, or an errno, or an ECTF_* value. */
int
-ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
- const char **names, size_t threshold)
+ctf_arc_write_fd (int fd, ctf_file_t **ctf_files, size_t ctf_file_cnt,
+ const char **names, size_t threshold)
{
const char *errmsg;
struct ctf_archive *archdr;
- int fd;
size_t i;
char dummy = 0;
size_t headersz;
off_t nameoffs;
struct ctf_archive_modent *modent;
- ctf_dprintf ("Writing archive %s with %zi files\n", file, ctf_file_cnt);
-
- if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
- {
- errmsg = "ctf_arc_write(): cannot create %s: %s\n";
- goto err;
- }
+ ctf_dprintf ("Writing CTF archive with %lu files\n",
+ (unsigned long) ctf_file_cnt);
/* Figure out the size of the mmap()ed header, including the
ctf_archive_modent array. We assume that all of this needs no
uint64_t's. */
headersz = sizeof (struct ctf_archive)
+ (ctf_file_cnt * sizeof (uint64_t) * 2);
- ctf_dprintf ("headersz is %zi\n", headersz);
+ ctf_dprintf ("headersz is %lu\n", (unsigned long) headersz);
/* From now on we work in two pieces: an mmap()ed region from zero up to the
headersz, and a region updated via write() starting after that, containing
ctf_startoffs = headersz;
if (lseek (fd, ctf_startoffs - 1, SEEK_SET) < 0)
{
- errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
- goto err_close;
+ errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
+ goto err;
}
if (write (fd, &dummy, 1) < 0)
{
- errmsg = "ctf_arc_write(): cannot extend file while writing %s: %s\n";
- goto err_close;
+ errmsg = "ctf_arc_write(): cannot extend file while writing: %s\n";
+ goto err;
}
if ((archdr = arc_mmap_header (fd, headersz)) == NULL)
{
- errmsg = "ctf_arc_write(): Cannot mmap() %s: %s\n";
- goto err_close;
+ errmsg = "ctf_arc_write(): Cannot mmap(): %s\n";
+ goto err;
}
/* Fill in everything we can, which is everything other than the name
nametbl = malloc (namesz);
if (nametbl == NULL)
{
- errmsg = "Error writing named CTF to %s: %s\n";
+ errmsg = "Error writing named CTF to archive: %s\n";
goto err_unmap;
}
if ((off < 0) && (off > -ECTF_BASE))
{
errmsg = "ctf_arc_write(): Cannot determine file "
- "position while writing %s: %s";
+ "position while writing to archive: %s";
goto err_free;
}
if (off < 0)
{
- errmsg = "ctf_arc_write(): Cannot write CTF file to %s: %s\n";
+ errmsg = "ctf_arc_write(): Cannot write CTF file to archive: %s\n";
errno = off * -1;
goto err_free;
}
modent++;
}
- qsort_r ((ctf_archive_modent_t *) ((char *) archdr
- + sizeof (struct ctf_archive)),
- le64toh (archdr->ctfa_nfiles),
- sizeof (struct ctf_archive_modent), sort_modent_by_name, nametbl);
+ ctf_qsort_r ((ctf_archive_modent_t *) ((char *) archdr
+ + sizeof (struct ctf_archive)),
+ le64toh (archdr->ctfa_nfiles),
+ sizeof (struct ctf_archive_modent), sort_modent_by_name,
+ nametbl);
/* Now the name table. */
if ((nameoffs = lseek (fd, 0, SEEK_CUR)) < 0)
{
errmsg = "ctf_arc_write(): Cannot get current file position "
- "in %s: %s\n";
+ "in archive: %s\n";
goto err_free;
}
archdr->ctfa_names = htole64 (nameoffs);
ssize_t len;
if ((len = write (fd, np, namesz)) < 0)
{
- errmsg = "ctf_arc_write(): Cannot write name table in %s: %s\n";
+ errmsg = "ctf_arc_write(): Cannot write name table to archive: %s\n";
goto err_free;
}
namesz -= len;
if (arc_mmap_writeout (fd, archdr, headersz, &errmsg) < 0)
goto err_unmap;
if (arc_mmap_unmap (archdr, headersz, &errmsg) < 0)
- goto err_unlink;
- if (close (fd) < 0)
- {
- errmsg = "ctf_arc_write(): Cannot close after writing to %s: %s\n";
- goto err_unlink;
- }
-
+ goto err;
return 0;
err_free:
free (nametbl);
err_unmap:
arc_mmap_unmap (archdr, headersz, NULL);
-err_close:
- close (fd);
-err_unlink:
- unlink (file);
err:
- ctf_dprintf (errmsg, file, errno < ECTF_BASE ? strerror (errno) :
+ ctf_dprintf (errmsg, errno < ECTF_BASE ? strerror (errno) :
ctf_errmsg (errno));
return errno;
}
+/* Write out a CTF archive. The entries in CTF_FILES are referenced by name:
+ the names are passed in the names array, which must have CTF_FILES entries.
+
+ If the filename is NULL, create a temporary file and return a pointer to it.
+
+ Returns 0 on success, or an errno, or an ECTF_* value. */
+int
+ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt,
+ const char **names, size_t threshold)
+{
+ int err;
+ int fd;
+
+ if ((fd = open (file, O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC, 0666)) < 0)
+ {
+ ctf_dprintf ("ctf_arc_write(): cannot create %s: %s\n", file,
+ strerror (errno));
+ return errno;
+ }
+
+ err = ctf_arc_write_fd (fd, ctf_files, ctf_file_cnt, names, threshold);
+ if (err)
+ goto err;
+
+ if ((err = close (fd)) < 0)
+ {
+ ctf_dprintf ("ctf_arc_write(): Cannot close after writing to archive: "
+ "%s\n", strerror (errno));
+ goto err_close;
+ }
+
+ err:
+ close (fd);
+ if (err < 0)
+ unlink (file);
+
+ return err;
+
+ err_close:
+ if (err < 0)
+ unlink (file);
+
+ return err;
+}
+
/* Write one CTF file out. Return the file position of the written file (or
rather, of the file-size uint64_t that precedes it): negative return is a
negative errno or ctf_errno value. On error, the file position may no longer
size_t ctfsz_len;
int (*writefn) (ctf_file_t * fp, int fd);
+ if (ctf_serialize (f) < 0)
+ return f->ctf_errno * -1;
+
if ((off = lseek (fd, 0, SEEK_CUR)) < 0)
return errno * -1;
else
ctf_file_close (arc->ctfi_file);
free ((void *) arc->ctfi_symsect.cts_data);
- free ((void *) arc->ctfi_strsect.cts_data);
+ /* Do not free the ctfi_strsect: it is bound to the bfd. */
free (arc->ctfi_data);
+ if (arc->ctfi_bfd_close)
+ arc->ctfi_bfd_close (arc);
free (arc);
}
ctf_sect_t ctfsect;
ctf_file_t *fp;
- ctf_dprintf ("ctf_arc_open_by_offset(%zi): opening\n", offset);
+ ctf_dprintf ("ctf_arc_open_by_offset(%lu): opening\n", (unsigned long) offset);
memset (&ctfsect, 0, sizeof (ctf_sect_t));
}
#else
/* Map the header in. Only used on new, empty files. */
-static void *arc_mmap_header (int fd, size_t headersz)
+static void *arc_mmap_header (int fd _libctf_unused_, size_t headersz)
{
void *hdr;
if ((hdr = malloc (headersz)) == NULL)