summaryrefslogtreecommitdiffstats
path: root/source3/client
diff options
context:
space:
mode:
authorAurélien Aptel <aurelien.aptel@gmail.com>2013-07-23 16:55:50 +0200
committerAndreas Schneider <asn@samba.org>2014-02-19 18:22:28 +0100
commit5cd72b39b35efc5129596ed258187def57f2f209 (patch)
treef536c5d1ab11c0f627a7ee383a7bda455c19af3b /source3/client
parent82dce8f7a8d340a39e08dcc12fb38b8ed254dc64 (diff)
downloadsamba-5cd72b39b35efc5129596ed258187def57f2f209.tar.gz
samba-5cd72b39b35efc5129596ed258187def57f2f209.tar.xz
samba-5cd72b39b35efc5129596ed258187def57f2f209.zip
clitar.c: documentation
Signed-off-by: Aurélien Aptel <aurelien.aptel@gmail.com> Reviewed-by: David Disseldorp <ddiss@samba.org> Reviewed-by: Andreas Schneider <asn@samba.org>
Diffstat (limited to 'source3/client')
-rw-r--r--source3/client/clitar.c192
1 files changed, 183 insertions, 9 deletions
diff --git a/source3/client/clitar.c b/source3/client/clitar.c
index adb0ab4bfa..063a83b432 100644
--- a/source3/client/clitar.c
+++ b/source3/client/clitar.c
@@ -17,6 +17,55 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * # General overview of the tar extension
+ *
+ * All tar_xxx() functions work on a `struct tar` which store most of
+ * the context of the backup process.
+ *
+ * The current tar context can be accessed via the global variable
+ * `tar_ctx`. It's not static but you should avoid accessing it
+ * directly.
+ *
+ * A tar context is first configured through tar_parse_args() which
+ * can be called from either the CLI (in client.c) or the interactive
+ * session (via the cmd_tar() callback).
+ *
+ * Once the configuration is done (successfully), the context is ready
+ * for processing and tar_to_process() returns true.
+ *
+ * The next step is to call tar_process() which dispatch the
+ * processing to either tar_create() or tar_extract(), depending on
+ * the context.
+ *
+ * ## Archive creation
+ *
+ * tar_create() creates an archive using the libarchive API then
+ *
+ * - iterates on the requested paths if the context is in inclusion
+ * mode with tar_create_from_list()
+ *
+ * - or iterates on the whole share (starting from the current dir) if
+ * in exclusion mode or if no specific path were requested
+ *
+ * The do_list() function from client.c is used to list recursively
+ * the share. In particular it takes a DOS path mask (eg. \mydir\*)
+ * and a callback function which will be called with each file name
+ * and attributes. The tar callback function is get_file_callback().
+ *
+ * The callback function checks whether the file should be skipped
+ * according the the configuration via tar_create_skip_path(). If it's
+ * not skipped it's downloaded and written to the archive in
+ * tar_get_file().
+ *
+ * ## Archive extraction
+ *
+ * tar_extract() opens the archive and iterates on each file in
+ * it. For each file tar_extract_skip_path() checks whether it should
+ * be skipped according to the config. If it's not skipped it's
+ * uploaded on the server in tar_send_file().
+ */
+
#include "includes.h"
#include "system/filesys.h"
#include "client/client_proto.h"
@@ -77,15 +126,15 @@ struct tar {
/* flags */
struct tar_mode {
enum tar_operation operation; /* create, extract */
- enum tar_selection selection; /* inc, inc from file, exclude */
- int blocksize; /* size in bytes of a block in the tar file */
+ enum tar_selection selection; /* include, exclude */
+ int blocksize; /* size in TAR_BLOCK_UNIT of a tar file block */
bool hidden; /* backup hidden file? */
bool system; /* backup system file? */
bool incremental; /* backup _only_ archived file? */
bool reset; /* unset archive bit? */
bool dry; /* don't write tar file? */
bool regex; /* XXX: never actually using regex... */
- bool verbose;
+ bool verbose; /* XXX: ignored */
} mode;
/* nb of bytes received */
@@ -102,15 +151,29 @@ struct tar {
struct archive *archive;
};
+/**
+ * Global context imported in client.c when needed.
+ *
+ * Default options.
+ */
struct tar tar_ctx = {
.mode.selection = TAR_INCLUDE,
.mode.blocksize = TAR_DEFAULT_BLOCK_SIZE,
.mode.hidden = true,
.mode.system = true,
.mode.incremental = false,
+ .mode.reset = false,
.mode.dry = false,
+ .mode.regex = false,
+ .mode.verbose = false,
};
+
+/**
+ * fix_unix_path - convert @path to a DOS path
+ * @path: path to convert
+ * @removeprefix: if true, remove leading ./ or /.
+ */
static char *fix_unix_path (char *path, bool removeprefix)
{
char *from = path, *to = path;
@@ -148,6 +211,11 @@ static char *fix_unix_path (char *path, bool removeprefix)
return path;
}
+/**
+ * path_base_name - return @path basename
+ *
+ * If @path doesn't contain any directory separator return NULL.
+ */
static char *path_base_name (const char *path)
{
TALLOC_CTX *ctx = talloc_tos();
@@ -175,6 +243,10 @@ static char *path_base_name (const char *path)
#define XSTR(v) DBG(2, ("DUMP:%-20.20s = %s\n", #v, v ? v : "NULL"))
#define XINT(v) DBG(2, ("DUMP:%-20.20s = %d\n", #v, v))
#define XUINT64(v) DBG(2, ("DUMP:%-20.20s = %" PRIu64 "\n", #v, v))
+
+/**
+ * tar_dump - dump tar structure on stdout
+ */
static void tar_dump(struct tar *t)
{
int i;
@@ -216,6 +288,10 @@ static void tar_dump(struct tar *t)
#undef XSTR
#undef XINT
+/**
+ * tar_add_selection_path - add a path to the path list
+ * @path: path to add
+ */
static void tar_add_selection_path(struct tar *t, const char *path)
{
TALLOC_CTX *ctx = talloc_tos();
@@ -229,6 +305,9 @@ static void tar_add_selection_path(struct tar *t, const char *path)
fix_unix_path(t->path_list[t->path_list_size - 1], true);
}
+/**
+ * tar_set_blocksize - set block size in TAR_BLOCK_UNIT
+ */
static int tar_set_blocksize(struct tar *t, int size)
{
if (size <= 0 || size > TAR_MAX_BLOCK_SIZE) {
@@ -240,6 +319,17 @@ static int tar_set_blocksize(struct tar *t, int size)
return 0;
}
+/**
+ * tar_set_newer_than - set date threshold of saved files
+ * @filename: local path to a file
+ *
+ * Only files newer than the modification time of @filename will be
+ * saved.
+ *
+ * Note: this function set the global variable newer_than from
+ * client.c. Thus the time is not a field of the tar structure. See
+ * cmd_newer() to change its value from an interactive session.
+ */
static int tar_set_newer_than(struct tar *t, const char *filename)
{
extern time_t newer_than;
@@ -255,6 +345,12 @@ static int tar_set_newer_than(struct tar *t, const char *filename)
return 0;
}
+/**
+ * tar_read_inclusion_file - set path list from file
+ * @filename: path to the list file
+ *
+ * Read and add each line of @filename to the path list.
+ */
static int tar_read_inclusion_file (struct tar *t, const char* filename)
{
char *line;
@@ -274,7 +370,11 @@ static int tar_read_inclusion_file (struct tar *t, const char* filename)
return 0;
}
-/* skip leading slashes or dots */
+/**
+ * skip_useless_char_in_path - skip leading slashes/dots
+ *
+ * Skip leading slashes, backslashes and dot-slashes.
+ */
static const char* skip_useless_char_in_path(const char *p)
{
while (p) {
@@ -290,11 +390,14 @@ static const char* skip_useless_char_in_path(const char *p)
return p;
}
-
/**
- * return true if the path @sub is a subpath of @full.
+ * is_subpath - return true if the path @sub is a subpath of @full.
+ * @sub: path to test
+ * @full: container path
*
- * case-insensitive, true if @sub = @full
+ * String comparaison is case-insensitive.
+ *
+ * Return true if @sub = @full
*/
static bool is_subpath(const char *sub, const char *full)
{
@@ -323,6 +426,17 @@ static bool is_subpath(const char *sub, const char *full)
return *full == *sub;
}
+/**
+ * tar_path_in_list - return true if @path is in the path list
+ * @path: path to find
+ * @reverse: when true also try to find path list element in @path
+ *
+ * Look at each path of the path list and return true if @path is a
+ * subpath of one of them.
+ *
+ * If you want /path to be in the path list (path/a/, path/b/) set
+ * @reverse to true to try to match the other way around.
+ */
static bool tar_path_in_list(struct tar *t, const char *path, bool reverse)
{
int i;
@@ -349,6 +463,12 @@ static bool tar_path_in_list(struct tar *t, const char *path, bool reverse)
return false;
}
+/**
+ * tar_extract_skip_path - return true if @entry should be skipped
+ * @entry: current tar entry
+ *
+ * Skip predicate for tar extraction (archive to server) only.
+ */
static bool tar_extract_skip_path(struct tar *t,
struct archive_entry *entry)
{
@@ -373,6 +493,13 @@ static bool tar_extract_skip_path(struct tar *t,
return in ? !skip : skip;
}
+/**
+ * tar_create_skip_path - return true if @fullpath shoud be skipped
+ * @fullpath: full remote path of the current file
+ * @finfo: remote file attributes
+ *
+ * Skip predicate for tar creation (server to archive) only.
+ */
static bool tar_create_skip_path(struct tar *t,
const char *fullpath,
const struct file_info *finfo)
@@ -428,6 +555,11 @@ static bool tar_create_skip_path(struct tar *t,
return in ? skip : !skip;
}
+/**
+ * tar_to_process - return true if @t is ready to be processed
+ *
+ * @t is ready if it properly parsed command line arguments.
+ */
bool tar_to_process (struct tar *t)
{
return t->to_process;
@@ -622,6 +754,12 @@ int cmd_setmode(void)
return 0;
}
+/**
+ * make_remote_path - recursively make remote dirs
+ * @full_path: full hierarchy to create
+ *
+ * Create @full_path and each parent directories as needed.
+ */
static int make_remote_path(const char *full_path)
{
extern struct cli_state *cli;
@@ -672,6 +810,13 @@ static int make_remote_path(const char *full_path)
return err;
}
+/**
+ * tar_send_file - send @entry to the remote server
+ * @entry: current archive entry
+ *
+ * Handle the creation of the parent directories and transfer the
+ * entry to a new remote file.
+ */
static int tar_send_file(struct tar *t, struct archive_entry *entry)
{
extern struct cli_state *cli;
@@ -752,6 +897,11 @@ static int tar_send_file(struct tar *t, struct archive_entry *entry)
return err;
}
+/**
+ * tar_get_file - fetch a remote file to the local archive
+ * @full_dos_path: path to the file to fetch
+ * @finfo: attributes of the file to fetch
+ */
static int tar_get_file(struct tar *t, const char *full_dos_path,
struct file_info *finfo)
{
@@ -855,6 +1005,13 @@ static int tar_get_file(struct tar *t, const char *full_dos_path,
return err;
}
+/**
+ * get_file_callback - do_list callback
+ *
+ * Callback for client.c do_list(). Called for each file found on the
+ * share matching do_list mask. Recursively call do_list() with itself
+ * as callback when the current file is a directory.
+ */
static NTSTATUS get_file_callback(struct cli_state *cli,
struct file_info *finfo,
const char *dir)
@@ -905,6 +1062,9 @@ static NTSTATUS get_file_callback(struct cli_state *cli,
return err;
}
+/**
+ * tar_create_from_list - fetch from path list in include mode
+ */
static int tar_create_from_list(struct tar *t)
{
TALLOC_CTX *ctx = talloc_tos();
@@ -944,6 +1104,9 @@ static int tar_create_from_list(struct tar *t)
return err;
}
+/**
+ * tar_create - create archive and fetch files
+ */
static int tar_create(struct tar* t)
{
TALLOC_CTX *ctx = talloc_tos();
@@ -963,6 +1126,11 @@ static int tar_create(struct tar* t)
goto out;
}
+ /*
+ * Use PAX restricted format which is not the most
+ * conservative choice but has useful extensions and is widely
+ * supported
+ */
r = archive_write_set_format_pax_restricted(t->archive);
if (r != ARCHIVE_OK) {
DBG(0, ("Can't use pax restricted format: %s\n",
@@ -1021,7 +1189,7 @@ static int tar_create(struct tar* t)
}
/**
- * Return upper limit for the number of token in @str.
+ * max_token - return upper limit for the number of token in @str
*
* The result is not exact, the actual number of token might be less
* than what is returned.
@@ -1091,6 +1259,9 @@ int cmd_tar(void)
return err;
}
+/**
+ * tar_extract - open archive and send files.
+ */
static int tar_extract(struct tar *t)
{
int err = 0;
@@ -1152,6 +1323,9 @@ static int tar_extract(struct tar *t)
return err;
}
+/**
+ * tar_process - start processing archive
+ */
int tar_process(struct tar *t)
{
int rc = 0;
@@ -1187,7 +1361,7 @@ int tar_process(struct tar *t)
* in the interactive session:
* tar f1f2f3 v1 v2 v3 TARFILE PATHS...
*
- * opt has only flags (eg. "f1f2f3") and val has the arguments
+ * @flag has only flags (eg. "f1f2f3") and @val has the arguments
* (values) following them (eg. ["v1", "v2", "v3", "TARFILE", "PATH1",
* "PATH2"]).
*