Commits

winebarrel  committed e815357

r2678@LENOVO-6D4C2336: sugawara | 2008-09-16 14:23:39 +0900

  • Participants
  • Parent commits 0a17fd9

Comments (0)

Files changed (3)

File ext/libtar/lib/append.c

 	return 0;
 }
 
+static int
+tar_append_function0(TAR *t, void *data, int (*f)(char *b, int l, void *d))
+{
+	char block[T_BLOCKSIZE];
+	int filefd;
+	int i, j;
+	size_t size;
 
+	size = th_get_size(t);
+	for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
+	{
+		j = f(block, T_BLOCKSIZE, data);
+		if (j != T_BLOCKSIZE)
+		{
+			if (j != -1)
+				errno = EINVAL;
+			return -1;
+		}
+		if (tar_block_write(t, &block) == -1)
+			return -1;
+	}
+
+	if (i > 0)
+	{
+		j = f(block, i, data);
+		if (j == -1)
+			return -1;
+		memset(&(block[i]), 0, T_BLOCKSIZE - i);
+		if (tar_block_write(t, &block) == -1)
+			return -1;
+	}
+
+	return 0;
+}
+
+int
+tar_append_function(TAR *t, char *savename, int size, void *data, int (*f)(char *b, int l, void *d))
+{
+	/* set header block */
+	memset(&(t->th_buf), 0, sizeof(struct tar_header));
+	t->th_buf.typeflag = REGTYPE;
+	th_set_user(t, 0);
+	th_set_group(t, 0);
+	th_set_mode(t, 0644);
+	th_set_mtime(t, 0);
+	th_set_size(t, size);
+
+	/* set the header path */
+	th_set_path(t, savename);
+
+	/* print file info */
+	if (t->options & TAR_VERBOSE)
+		th_print_long_ls(t);
+
+	/* write header */
+	if (th_write(t) != 0)
+	{
+		return -1;
+	}
+
+	/* if it's a regular file, write the contents as well */
+	if (tar_append_function0(t, data, f) != 0)
+		return -1;
+
+	return 0;
+}

File ext/libtar/lib/libtar.h

 /* add file contents to a tarchive */
 int tar_append_regfile(TAR *t, char *realname);
 
+int tar_append_function(TAR *t, char *savename, int size, void *data, int (*f)(char *b, int l, void *d));
 
 /***** block.c *************************************************************/
 

File ext/tarruby.c

   return Qnil;
 }
 
+static int tarruby_append_buffer0(char *buf, int len, void *data) {
+  char **p_buffer = (char **) data;
+  memcpy(buf, *p_buffer, len);
+  p_buffer += len;
+  return len;
+}
+
+/* */
+static VALUE tarruby_append_buffer(VALUE self, VALUE savename, VALUE buffer) {
+  struct tarruby_tar *p_tar;
+  char *s_savename, *s_buffer;
+  int i_size;
+
+  Check_Type(savename, T_STRING);
+  Check_Type(buffer, T_STRING);
+  s_savename = RSTRING_PTR(savename);
+  strip_sep(s_savename);
+  s_buffer = RSTRING_PTR(buffer);
+  i_size = RSTRING_LEN(buffer);
+
+  Data_Get_Struct(self, struct tarruby_tar, p_tar);
+
+  if (tar_append_function(p_tar->tar, s_savename, i_size, (void *) &s_buffer, tarruby_append_buffer0) != 0) {
+    rb_raise(Error, "Append buffer failed: %s", strerror(errno));
+  }
+
+  return Qnil;
+}
+
 /* */
 static VALUE tarruby_append_tree(int argc, VALUE *argv, VALUE self) {
   VALUE realdir, savedir;
 static int tarruby_extract_buffer0(char *buf, int len, void *data) {
   VALUE buffer = (VALUE) data;
   rb_str_buf_cat(buffer, buf, len);
-  return 0;
+  return len;
 }
 
 /* */
 #endif
   rb_define_method(Tar, "close", tarruby_close, 0);
   rb_define_method(Tar, "append_file", tarruby_append_file, -1);
+  rb_define_method(Tar, "append_buffer", tarruby_append_buffer, 2);
   rb_define_method(Tar, "append_tree", tarruby_append_tree, -1);
   rb_define_method(Tar, "extract_file", tarruby_extract_file, 1);
   rb_define_method(Tar, "extract_buffer", tarruby_extract_buffer, 0);