[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Bug-tar] Support for Hurd translators
From: |
Marco Gerards |
Subject: |
Re: [Bug-tar] Support for Hurd translators |
Date: |
20 Jan 2004 23:52:19 +0100 |
User-agent: |
Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 |
Marco Gerards <address@hidden> writes:
> Well, I've noticed it has support for this now so I want to add
> support for translators. Is this already possible with the current
> state of tar and what do I need to do? (Is there anything I should
> know before I start hacking?).
I've written quite some code already to implement this. I've included
the patch with this mail, I hope that is ok (otherwise I can upload it
to the savannah patch manager next time, if you are willing to use
it).
This patch is far from perfect, I'm sending it in to get some feedback
if I am doing this the right way.
Before reading the patch you should know a bit about (passive)
translators:
A passive translator described how a translator should be started if
a user accesses a node. For example:
/hurd/iso9660fs /dev/hd2
This will "automount" the CDROM, this can be set on a node like
/mnt/cdrom. But translators will be used for almost everything, like
device access. Storing the major and minor device won't work (hd0 is
0, 0 for example). You will have to store the passive translator, for
hd0 that will be:
/hurd/storeio hd0
And the arguments are (and should be) separated with \0's. Using
spaces is not possible, what if an argument contains a space.
In this patch I escape all special characters (so there is \0, \n and
\\). When listing a node with a translator I replace the \0 with a
space.
I wrote a patch like this a while ago for the `old' tar (without POSIX
support). This one works differently, a translator is not a filetype
anymore. Now the underlying file will be stored as well.
Something that is important to keep in mind is that I avoid starting
translators and reading stat information from the translator, I read
everything from the underlying node (well, only when the user uses
--no-deref-trans option). That's why I test (or should) test if a
node is a translator before accessing a node before accessing it in
case this option is used.
But this patch is not yet done. I should do the following stuff
before it is done:
- Add support to configure.ac to check for features.
- Make sure compare works.
- Test it a bit more.
- Make sure I didn't break stuff for non GNU/Hurd systems.
- Re-read all of my code and clean it a bit up, etc.
- I've added code to files that will be rewritten by Sergey, I must
make sure that the new files work correctly.
- Let the Hurd hackers proof read it.
Can you please tell me if I did something wrong? Perhaps I put some
functions/code in the wrong file or perhaps I've implemented something
that already exists, etc. Please tell me as well if some code sucks, I
know I'm not a that good hacker. And have a close look at my
changelog, my English sucks. :)
I also found a problem with sys/system.h, I had to include <utime.h>
to make it work. Is there some autoconf test failing here? (I have
very little knowledge about autoconf)
If you want to test the patch just have a look at this public Debian
GNU/Hurd box: http://hurd.she.kicks-ass.org:8084/
Well, I hope this mail is not too chaotic, I should not send mail when
I'm really tired. ;)
Thanks for all the help so far.
--
Marco
2004-01-20 Marco Gerards <address@hidden>
* src/common.h (noderef_trans_option): New variable.
(translator_error): New prototype.
* src/compare.c (get_stat_data): Do not dereference if a
translator was set on a node.
* src/create.c (start_header): If a translator was set on a node,
write it to the header.
(dump_file0): Read the translator. Read the underlaying node if
this node is a translator.
* src/extract.c: Include <hurd.h>.
(set_translator): new function.
(extract_archive): Set the translator if there was one in the
archive.
* src/incremen.c (get_directory_contents): Do not dereference if a
translator was set on a node.
* src/names.c (collect_and_sort_names): Likewise.
* src/list.c (print_header): Show the translator.
* src/misc.c: Include <hurd.h>.
(read_trans): New function.
(translator_error): Likewise.
* src/tar.c (long_options): All `--no-deref-trans'.
(OPTION_STRING): Add the option `a' for `--no-deref-trans'.
(decode_options): Parse the `--no-deref-trans' option. Do not
dereference if a translator was set on a node.
(tar_stat_destroy): Free the memory used for a translator.
* src/tar.h (tar_stat_info): New member `translator'.
* src/xheader.c (translator_coder): New function.
(translator_decoder): Likewise.
(xhdr_tab): Added option `GNU.translator'.
* src/system.c: Include <utime.h>.
Common subdirectories: ../../tar/src/CVS and ./CVS
diff -up ../../tar/src/common.h ./common.h
--- ../../tar/src/common.h 2004-01-03 23:24:35.000000000 +0100
+++ ./common.h 2004-01-20 18:15:43.000000000 +0100
@@ -150,6 +150,8 @@ GLOBAL const char *use_compress_program_
GLOBAL bool dereference_option;
+GLOBAL bool noderef_trans_option;
+
/* Print a message if not all links are dumped */
GLOBAL int check_links_option;
@@ -553,6 +555,7 @@ void unlink_error (char const *);
void utime_error (char const *);
void waitpid_error (char const *);
void write_error (char const *);
+void translator_error (char const *);
void write_error_details (char const *, ssize_t, size_t);
void write_fatal (char const *) __attribute__ ((noreturn));
void write_fatal_details (char const *, ssize_t, size_t)
diff -up ../../tar/src/compare.c ./compare.c
--- ../../tar/src/compare.c 2003-11-17 12:05:18.000000000 +0100
+++ ./compare.c 2004-01-20 18:10:40.000000000 +0100
@@ -179,7 +179,12 @@ read_and_process (off_t size, int (*proc
static int
get_stat_data (char const *file_name, struct stat *stat_data)
{
- int status = deref_stat (dereference_option, file_name, stat_data);
+ int status;
+
+ if (!noderef_trans_option || !read_trans (file_name, stat_data, 0))
+ status = deref_stat (dereference_option, file_name, stat_data);
+ else
+ status = 1;
if (status != 0)
{
diff -up ../../tar/src/create.c ./create.c
--- ../../tar/src/create.c 2004-01-03 23:25:24.000000000 +0100
+++ ./create.c 2004-01-20 18:24:00.000000000 +0100
@@ -684,6 +684,8 @@ start_header (struct tar_stat_info *st)
{
xheader_store ("atime", st, NULL);
xheader_store ("ctime", st, NULL);
+ if (st->translator)
+ xheader_store ("GNU.translator", st, NULL);
}
else if (incremental_option)
if (archive_format == OLDGNU_FORMAT)
@@ -1279,11 +1281,15 @@ dump_file0 (struct tar_stat_info *stat,
assign_string (&stat->orig_file_name, p);
assign_string (&stat->file_name, safer_name_suffix (p, false));
- if (deref_stat (dereference_option, p, &stat->stat) != 0)
+ if (!noderef_trans_option || !read_trans (p, &stat->stat, &stat->translator))
{
- stat_diag (p);
- return;
+ if (deref_stat (dereference_option, p, &stat->stat) != 0)
+ {
+ stat_diag (p);
+ return;
+ }
}
+
stat->archive_file_size = stat->stat.st_size;
sys_stat_nanoseconds(stat);
original_ctime = stat->stat.st_ctime;
@@ -1351,8 +1357,9 @@ dump_file0 (struct tar_stat_info *stat,
if (file_dumpable_p (stat))
{
+ int tsflags = stat->translator ? O_NOTRANS : 0;
fd = open (stat->orig_file_name,
- O_RDONLY | O_BINARY);
+ O_RDONLY | O_BINARY | tsflags);
if (fd < 0)
{
if (!top_level && errno == ENOENT)
diff -up ../../tar/src/extract.c ./extract.c
--- ../../tar/src/extract.c 2004-01-03 23:25:24.000000000 +0100
+++ ./extract.c 2004-01-20 18:47:54.000000000 +0100
@@ -22,6 +22,7 @@
#include "system.h"
#include <quotearg.h>
#include <errno.h>
+#include <hurd.h>
#if HAVE_UTIME_H
# include <utime.h>
@@ -199,6 +200,67 @@ check_time (char const *file_name, time_
file_name, tartime (t), (unsigned long) (t - now)));
}
+static void
+set_translator (const char *file_name, const char *translator)
+{
+ int transsize;
+ char *transbuf;
+ char *trans;
+ file_t node;
+ int pos = 0;
+ error_t err;
+
+ transsize = strlen (file_name);
+ transbuf = alloca (transsize);
+ trans = (char *) translator;
+ while (*trans)
+ {
+ char c;
+ if (*trans == '\\')
+ {
+ trans++;
+ if (! *trans)
+ break;
+ switch (*trans)
+ {
+ case '\\':
+ c = '\\';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case '0':
+ c = '\0';
+ break;
+ default:
+ c = *trans;
+ }
+ }
+ else
+ c = *trans;
+ transbuf[pos++] = c;
+ trans++;
+ }
+
+ node = file_name_lookup (file_name, O_NOTRANS, 600);
+
+ if (node == MACH_PORT_NULL)
+ {
+ open_error (file_name);
+ return;
+ }
+
+ err = file_set_translator (node,
+ FS_TRANS_SET | FS_TRANS_EXCL,
+ FS_TRANS_SET | FS_TRANS_EXCL, 0,
+ transbuf, pos, MACH_PORT_NULL,
+ MACH_MSG_TYPE_COPY_SEND);
+ if (err)
+ translator_error (file_name);
+
+ mach_port_deallocate (mach_task_self (), node);
+}
+
/* Restore stat attributes (owner, group, mode and times) for
FILE_NAME, using information given in *STAT_INFO.
If CUR_INFO is nonzero, *CUR_INFO is the
@@ -747,6 +809,10 @@ extract_archive (void)
? UNKNOWN_PERMSTATUS
: ARCHIVED_PERMSTATUS),
typeflag);
+
+ if (current_stat_info.translator)
+ set_translator (file_name, current_stat_info.translator);
+
break;
case SYMTYPE:
diff -up ../../tar/src/incremen.c ./incremen.c
--- ../../tar/src/incremen.c 2003-12-25 11:18:48.000000000 +0100
+++ ./incremen.c 2004-01-20 18:12:17.000000000 +0100
@@ -1,7 +1,7 @@
/* GNU dump extensions to tar.
Copyright (C) 1988, 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -224,11 +224,13 @@ get_directory_contents (char *path, dev_
{
struct stat stat_data;
- if (deref_stat (dereference_option, name_buffer, &stat_data))
- {
- stat_diag (name_buffer);
- continue;
- }
+ if (!noderef_trans_option
+ || !read_trans (name_buffer, &stat_data))
+ if (deref_stat (dereference_option, name_buffer, &stat_data))
+ {
+ stat_diag (name_buffer);
+ continue;
+ }
if (S_ISDIR (stat_data.st_mode))
{
diff -up ../../tar/src/list.c ./list.c
--- ../../tar/src/list.c 2003-12-25 11:19:24.000000000 +0100
+++ ./list.c 2004-01-20 17:20:02.000000000 +0100
@@ -1150,6 +1150,39 @@ print_header (struct tar_stat_info *st,
case FIFOTYPE:
case CONTTYPE:
case GNUTYPE_DUMPDIR:
+ if (st->translator)
+ {
+ char *trans = st->translator;
+ fprintf (stdlis, " => ");
+ while (*trans)
+ {
+ char c;
+
+ if (*trans != '\\')
+ c = *trans;
+ else
+ {
+ trans++;
+ /* XXX: This should not happen. */
+ if (! *trans)
+ break;
+ switch (*trans)
+ {
+ case '\\':
+ c = '\\';
+ break;
+ case 'n':
+ c = ' ';
+ break;
+ case '0':
+ c = ' ';
+ break;
+ }
+ }
+ putc (c, stdlis);
+ trans++;
+ }
+ }
putc ('\n', stdlis);
break;
diff -up ../../tar/src/misc.c ./misc.c
--- ../../tar/src/misc.c 2004-01-03 23:24:35.000000000 +0100
+++ ./misc.c 2004-01-20 18:53:44.000000000 +0100
@@ -1,7 +1,7 @@
/* Miscellaneous functions, not really specific to GNU tar.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -22,6 +22,7 @@
#include "common.h"
#include <quotearg.h>
#include <save-cwd.h>
+#include <hurd.h>
static void call_arg_fatal (char const *, char const *)
__attribute__ ((noreturn));
@@ -412,6 +413,98 @@ undo_last_backup (void)
}
}
+/* Get the stat information of an translator. In case of a
+ translator, return the translator string in a malloced buffer and
+ return the length, else return 0. */
+int
+read_trans (char *const name, struct stat *buf, char **trans)
+{
+ file_t node;
+ error_t err;
+ char tbuf[1024];
+ char *transbuf = tbuf;
+ size_t translen = sizeof (tbuf);
+ int i;
+ char *escbuf;
+ size_t escsize = 0;
+
+ /* Read the translator. */
+ node = file_name_lookup (name, O_NOTRANS, 0);
+ if (node == MACH_PORT_NULL)
+ {
+ open_error (name);
+ return 0;
+ }
+
+ if (io_stat (node, buf) != 0)
+ {
+ mach_port_deallocate (mach_task_self (), node);
+
+ stat_error (name);
+ return 0;
+ }
+
+ err = file_get_translator (node, &transbuf, &translen);
+ mach_port_deallocate (mach_task_self (), node);
+
+ if (err && err != EINVAL)
+ {
+ translator_error (name);
+ return 0;
+ }
+ else if (err == EINVAL)
+ /* No translator was set. */
+ return 0;
+
+ /* Some translator types should not be stored. */
+ if (! strcmp ("/hurd/symlink", transbuf)
+ || ! strcmp ("/hurd/fifo", transbuf))
+ {
+ if (transbuf != tbuf)
+ munmap (transbuf, translen);
+ return 0;
+ }
+ /* Determine the size of the target buffer. */
+ for (i = 0; i < translen; i++)
+ {
+ escsize++;
+ if (transbuf[i] == '\n' || transbuf[i] == '\0'
+ || transbuf[i] == '\\')
+ escsize++;
+ }
+
+ if (! trans)
+ return escsize;
+
+ escbuf = xmalloc (escsize + 1);
+
+ escsize = 0;
+ for (i = 0; i < translen; i++)
+ {
+ switch (transbuf[i])
+ {
+ case '\n':
+ escbuf[escsize++] = '\\';
+ escbuf[escsize++] = 'n';
+ break;
+ case '\0':
+ escbuf[escsize++] = '\\';
+ escbuf[escsize++] = '0';
+ break;
+ case '\\':
+ escbuf[escsize++] = '\\';
+ escbuf[escsize++] = '\\';
+ break;
+ default:
+ escbuf[escsize++] = transbuf[i];
+ }
+ }
+ escbuf[escsize++] = '\0';
+ *trans = escbuf;
+
+ return escsize;
+}
+
/* Depending on DEREF, apply either stat or lstat to (NAME, BUF). */
int
deref_stat (bool deref, char const *name, struct stat *buf)
@@ -875,6 +968,12 @@ write_error (char const *name)
}
void
+translator_error (char const *name)
+{
+ call_arg_error ("translator", name);
+}
+
+void
write_error_details (char const *name, ssize_t status, size_t size)
{
if (status < 0)
diff -up ../../tar/src/names.c ./names.c
--- ../../tar/src/names.c 2003-12-25 11:19:40.000000000 +0100
+++ ./names.c 2004-01-20 18:12:51.000000000 +0100
@@ -1,7 +1,7 @@
/* Various processing of names.
Copyright (C) 1988, 1992, 1994, 1996, 1997, 1998, 1999, 2000, 2001,
- 2003 Free Software Foundation, Inc.
+ 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -831,10 +831,13 @@ collect_and_sort_names (void)
if (name->fake)
continue;
- if (deref_stat (dereference_option, name->name, &statbuf) != 0)
+ if (!noderef_trans_option || !read_trans (name->name, &statbuf))
{
- stat_diag (name->name);
- continue;
+ if (deref_stat (dereference_option, name->name, &statbuf) != 0)
+ {
+ stat_diag (name->name);
+ continue;
+ }
}
if (S_ISDIR (statbuf.st_mode))
{
diff -up ../../tar/src/system.c ./system.c
--- ../../tar/src/system.c 2003-12-25 11:20:19.000000000 +0100
+++ ./system.c 2004-01-20 15:30:34.000000000 +0100
@@ -21,6 +21,7 @@
#include "common.h"
#include "rmt.h"
#include <signal.h>
+#include <utime.h>
void
sys_stat_nanoseconds(struct tar_stat_info *stat)
diff -up ../../tar/src/tar.c ./tar.c
--- ../../tar/src/tar.c 2004-01-03 23:26:11.000000000 +0100
+++ ./tar.c 2004-01-20 18:20:02.000000000 +0100
@@ -1,7 +1,7 @@
/* A tar (tape archiver) program.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000,
- 2001, 2003 Free Software Foundation, Inc.
+ 2001, 2003, 2004 Free Software Foundation, Inc.
Written by John Gilmore, starting 1985-08-25.
@@ -283,6 +283,7 @@ static struct option long_options[] =
{"newer-mtime", required_argument, 0, NEWER_MTIME_OPTION},
{"null", no_argument, 0, NULL_OPTION},
{"no-anchored", no_argument, 0, NO_ANCHORED_OPTION},
+ {"no-deref-trans", no_argument, 0, 'a'},
{"no-ignore-case", no_argument, 0, NO_IGNORE_CASE_OPTION},
{"no-overwrite-dir", no_argument, 0, NO_OVERWRITE_DIR_OPTION},
{"no-wildcards", no_argument, 0, NO_WILDCARDS_OPTION},
@@ -473,6 +474,7 @@ Local file selection:\n\
--no-wildcards-match-slash exclude pattern wildcards do not match '/'\n\
-P, --absolute-names don't strip leading `/'s from file names\n\
-h, --dereference dump instead the files symlinks point to\n\
+ -a, --no-deref-trans dump the passive translator\n\
--no-recursion avoid descending automatically in directories\n\
-l, --one-file-system stay in local file system when creating
archive\n\
-K, --starting-file=NAME begin at file NAME in the archive\n\
@@ -534,7 +536,7 @@ or a file name starting with `/' or `.',
/* Parse the options for tar. */
-/* Available option letters are DEHIJQY and aenqy. Some are reserved:
+/* Available option letters are DEHIJQY and enqy. Some are reserved:
e exit immediately with a nonzero exit status if unexpected errors occur
E use extended headers (draft POSIX headers, that is)
@@ -545,7 +547,7 @@ or a file name starting with `/' or `.',
Y per-block gzip compression */
#define OPTION_STRING \
- "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zb:cdf:g:hijklmoprstuvwxyz"
+ "-01234567ABC:F:GIK:L:MN:OPRST:UV:WX:Zab:cdf:g:hijklmoprstuvwxyz"
static void
set_subcommand_option (enum subcommand subcommand)
@@ -673,6 +675,10 @@ decode_options (int argc, char **argv)
input_files++;
break;
+ case 'a':
+ noderef_trans_option = true;
+ break;
+
case 'A':
set_subcommand_option (CAT_SUBCOMMAND);
break;
@@ -821,11 +827,14 @@ decode_options (int argc, char **argv)
|| *optarg == '.')
{
struct stat st;
- if (deref_stat (dereference_option, optarg, &st) != 0)
- {
- stat_error (optarg);
- USAGE_ERROR ((0, 0, _("Date file not found")));
- }
+ if (!noderef_trans_option || !read_trans (optarg, &st))
+ {
+ if (deref_stat (dereference_option, optarg, &st) != 0)
+ {
+ stat_error (optarg);
+ USAGE_ERROR ((0, 0, _("Date file not found")));
+ }
+ }
newer_mtime_option = st.st_mtime;
}
else
@@ -1541,6 +1550,7 @@ tar_stat_destroy (struct tar_stat_info *
free (st->uname);
free (st->gname);
free (st->sparse_map);
+ free (st->translator);
memset (st, 0, sizeof (*st));
}
diff -up ../../tar/src/tar.h ./tar.h
--- ../../tar/src/tar.h 2003-12-25 11:20:32.000000000 +0100
+++ ./tar.h 2004-01-20 00:16:20.000000000 +0100
@@ -1,7 +1,7 @@
/* GNU tar Archive Format description.
Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 2000, 2001, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -291,6 +291,9 @@ struct tar_stat_info
not sparse */
size_t sparse_map_size; /* Size of the sparse map */
struct sp_array *sparse_map;
+
+ /* A translator as it is used by the Hurd. */
+ char *translator;
};
union block
diff -up ../../tar/src/update.c ./update.c
--- ../../tar/src/update.c 2004-01-03 23:26:30.000000000 +0100
+++ ./update.c 2004-01-20 18:47:14.000000000 +0100
@@ -1,6 +1,6 @@
/* Update a tar archive.
- Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003
+ Copyright (C) 1988, 1992, 1994, 1996, 1997, 1999, 2000, 2001, 2003, 2004
Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
@@ -130,11 +130,18 @@ update_archive (void)
{
struct stat s;
enum archive_format unused;
-
+
decode_header (current_header, ¤t_stat_info, &unused, 0);
chdir_do (name->change_dir);
- if (deref_stat (dereference_option,
current_stat_info.file_name, &s) == 0
- && s.st_mtime <= current_stat_info.stat.st_mtime)
+ if (!noderef_trans_option
+ || !read_trans (current_stat_info.file_name, &s))
+ {
+ if (deref_stat (dereference_option,
+ current_stat_info.file_name, &s) == 0
+ && s.st_mtime <= current_stat_info.stat.st_mtime)
+ add_avoided_name (current_stat_info.file_name);
+ }
+ else
add_avoided_name (current_stat_info.file_name);
}
skip_member ();
diff -up ../../tar/src/xheader.c ./xheader.c
--- ../../tar/src/xheader.c 2003-12-25 11:20:43.000000000 +0100
+++ ./xheader.c 2004-01-20 16:40:27.000000000 +0100
@@ -1,6 +1,6 @@
/* POSIX extended and STAR headers.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -511,6 +511,20 @@ sparse_numbytes_decoder (struct tar_stat
}
}
+
+static void
+translator_coder (struct tar_stat_info const *st, char const *keyword,
+ struct xheader *xhdr, void *data)
+{
+ code_string (st->translator, keyword, xhdr);
+}
+
+static void
+translator_decoder (struct tar_stat_info *st, char const *arg)
+{
+ assign_string (&st->translator, arg);
+}
+
struct xhdr_tab const xhdr_tab[] = {
{ "atime", atime_coder, atime_decoder },
{ "comment", dummy_coder, dummy_decoder },
@@ -531,6 +545,10 @@ struct xhdr_tab const xhdr_tab[] = {
{ "GNU.sparse.offset", sparse_offset_coder, sparse_offset_decoder },
{ "GNU.sparse.numbytes", sparse_numbytes_coder, sparse_numbytes_decoder },
+ /* Extentions for the Hurd. */
+ { "GNU.translator", translator_coder, translator_decoder },
+ /* XXX: missing support for author and the remaining "rwx"-bits. */
+
#if 0 /* GNU private keywords (not yet implemented) */
/* The next directory entry actually contains the names of files