diff options
Diffstat (limited to 'libctf/ctf-archive.c')
-rw-r--r-- | libctf/ctf-archive.c | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/libctf/ctf-archive.c b/libctf/ctf-archive.c index a13bac8..8de11d6 100644 --- a/libctf/ctf-archive.c +++ b/libctf/ctf-archive.c @@ -47,17 +47,17 @@ static int arc_mmap_unmap (void *header, size_t headersz, const char **errmsg); /* 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; @@ -68,15 +68,9 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, off_t nameoffs; struct ctf_archive_modent *modent; - ctf_dprintf ("Writing archive %s with %lu files\n", file, + ctf_dprintf ("Writing CTF archive with %lu files\n", (unsigned long) 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; - } - /* Figure out the size of the mmap()ed header, including the ctf_archive_modent array. We assume that all of this needs no padding: a likely assumption, given that it's all made up of @@ -91,20 +85,20 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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 @@ -137,7 +131,7 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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; } @@ -154,12 +148,12 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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; } @@ -181,7 +175,7 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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); @@ -191,7 +185,7 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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; @@ -202,29 +196,64 @@ ctf_arc_write (const char *file, ctf_file_t ** ctf_files, size_t ctf_file_cnt, 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 |