#include <errno.h>
#include <stdlib.h>
#include <time.h>
+#include <unistd.h>
#include "gl/crc.h"
#include "gl/fwriteerror.h"
#include "gl/xalloc.h"
#include "libpspp/message.h"
+#include "libpspp/temp-file.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
{
char *file_name; /* File name, for use in error mesages. */
FILE *file; /* Output stream. */
+ uint32_t offset; /* Offset in output stream. */
uint16_t date, time; /* Date and time in MS-DOS format. */
put_bytes (struct zip_writer *zw, const void *p, size_t n)
{
fwrite (p, 1, n, zw->file);
+ zw->offset += n;
}
static void
time_t now;
FILE *file;
- file = fopen (file_name, "wb");
- if (file == NULL)
+ if (strcmp (file_name, "-"))
{
- msg_error (errno, _("%s: error opening output file"), file_name);
- return NULL;
+ file = fopen (file_name, "wb");
+ if (file == NULL)
+ {
+ msg_error (errno, _("%s: error opening output file"), file_name);
+ return NULL;
+ }
+ }
+ else
+ {
+ if (isatty (STDOUT_FILENO))
+ {
+ msg (ME, _("%s: not writing ZIP file to terminal"), file_name);
+ return NULL;
+ }
+
+ file = stdout;
}
zw = xmalloc (sizeof *zw);
zw->file_name = xstrdup (file_name);
zw->file = file;
+ zw->offset = 0;
zw->ok = true;
zip_writer_add (struct zip_writer *zw, FILE *file, const char *member_name)
{
struct zip_member *member;
- uint32_t offset, size;
+ uint32_t size;
size_t bytes_read;
uint32_t crc;
char buf[4096];
/* Local file header. */
- offset = ftello (zw->file);
+ uint32_t offset = zw->offset;
put_local_header (zw, member_name, 0, 0, 1 << 3);
/* File data. */
with the correct file size and CRC. Otherwise, write data descriptor. */
if (fseeko (zw->file, offset, SEEK_SET) == 0)
{
+ uint32_t save_offset = zw->offset;
put_local_header (zw, member_name, crc, size, 0);
if (fseeko (zw->file, size, SEEK_CUR)
&& zw->ok)
msg_error (errno, _("%s: error seeking in output file"), zw->file_name);
zw->ok = false;
}
+ zw->offset = save_offset;
}
else
{
member->name = xstrdup (member_name);
}
+/* Adds a member named MEMBER_NAME whose contents is the null-terminated string
+ CONTENT. */
+void
+zip_writer_add_string (struct zip_writer *zw, const char *member_name,
+ const char *content)
+{
+ zip_writer_add_memory (zw, member_name, content, strlen (content));
+}
+
+/* Adds a member named MEMBER_NAME whose contents is the SIZE bytes of
+ CONTENT. */
+void
+zip_writer_add_memory (struct zip_writer *zw, const char *member_name,
+ const void *content, size_t size)
+{
+ FILE *fp = create_temp_file ();
+ if (fp == NULL)
+ {
+ msg_error (errno, _("error creating temporary file"));
+ zw->ok = false;
+ return;
+ }
+ fwrite (content, size, 1, fp);
+ zip_writer_add (zw, fp, member_name);
+ close_temp_file (fp);
+}
+
/* Finalizes the contents of ZW and closes it. Returns true if successful,
false if a write error occurred while finalizing the file or at any earlier
time. */
if (zw == NULL)
return true;
- dir_start = ftello (zw->file);
+ dir_start = zw->offset;
for (i = 0; i < zw->n_members; i++)
{
struct zip_member *m = &zw->members[i];
free (m->name);
}
free (zw->members);
- dir_end = ftello (zw->file);
+ dir_end = zw->offset;
/* End of central directory record. */
put_u32 (zw, MAGIC_EOCD); /* end of central dir signature */
put_u16 (zw, 0); /* .ZIP file comment length */
ok = zw->ok;
- if (ok && fwriteerror (zw->file))
+ if (ok && zw->file != stdout && fwriteerror (zw->file))
{
msg_error (errno, _("%s: write failed"), zw->file_name);
ok = false;