From 19e949a91ba342ec1de2c01e5bfddf8392cb68b5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Fri, 20 Aug 2004 20:13:05 +0000 Subject: r1966: further work on and cleanup of the net-migration-tool. It's now possible to migrate files preserving dos-attributes and correct timestamps. Also added some small docu- and syntax-fixes. Guenther (This used to be commit 0e990582a0416933a8671ca660d22e980f828402) --- source3/utils/net.c | 14 ++++-- source3/utils/net.h | 2 + source3/utils/net_help.c | 28 ++++++----- source3/utils/net_rpc.c | 77 +++++++++++++++++++++++++----- source3/utils/net_rpc_printer.c | 103 ++++++++++++++++++++++++++++------------ 5 files changed, 164 insertions(+), 60 deletions(-) diff --git a/source3/utils/net.c b/source3/utils/net.c index 6a1a97914a..2c7ee7a224 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -79,6 +79,8 @@ BOOL opt_domaingroup = False; const char *opt_newntname = ""; int opt_rid = 0; int opt_acls = 0; +int opt_attrs = 0; +int opt_timestamps = 0; const char *opt_exclude = NULL; BOOL opt_have_ip = False; @@ -209,9 +211,9 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, /** * Connect the local server and open a given pipe * - * @param cli_local A cli_state to the local spoolss-server + * @param cli_local A cli_state * @param pipe The pipe to open - * @param got_pipe boolean to that stores if got a pipe + * @param got_pipe boolean that stores if we got a pipe * * @return Normal NTSTATUS return. **/ @@ -222,13 +224,13 @@ NTSTATUS connect_local_pipe(struct cli_state **cli_local, int pipe_num, BOOL *go char *server_name = strdup("127.0.0.1"); struct cli_state *cli_tmp = NULL; - /* make a connection to smbd via loopback */ + /* make a connection to local named pipe via loopback */ nt_status = connect_to_ipc(&cli_tmp, &loopback_ip, server_name); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; if (!cli_nt_session_open(cli_tmp, pipe_num)) { - DEBUG(0, ("couldn't not initialise spoolss pipe\n")); + DEBUG(0, ("couldn't not initialize pipe\n")); cli_shutdown(cli_tmp); return NT_STATUS_UNSUCCESSFUL; } @@ -738,7 +740,9 @@ static struct functable net_func[] = { {"ntname", 'N', POPT_ARG_STRING, &opt_newntname}, {"rid", 'R', POPT_ARG_INT, &opt_rid}, /* Options for 'net rpc share migrate' */ - {"acls", 'a', POPT_ARG_NONE, &opt_acls}, + {"acls", 0, POPT_ARG_NONE, &opt_acls}, + {"attrs", 0, POPT_ARG_NONE, &opt_attrs}, + {"timestamps", 0, POPT_ARG_NONE, &opt_timestamps}, {"exclude", 'e', POPT_ARG_STRING, &opt_exclude}, POPT_COMMON_SAMBA diff --git a/source3/utils/net.h b/source3/utils/net.h index cb38907ff9..29498b9108 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -63,6 +63,8 @@ extern BOOL opt_domaingroup; extern const char *opt_newntname; extern int opt_rid; extern int opt_acls; +extern int opt_attrs; +extern int opt_timestamps; extern const char *opt_exclude; extern BOOL opt_have_ip; diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index c17824cb27..a0fc07cb5a 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -139,8 +139,11 @@ int net_help_share(int argc, const char **argv) d_printf( "\t-C or --comment=\tdescriptive comment (for add only)\n" "\t-M or --maxusers=\t\tmax users allowed for share\n" - "\t-a or --acls\t\t\tcopies ACLs as well\n" - "\t-e or --exclude\t\t\tlist of shares to be excluded from mirroring\n"); + "\t --acls\t\t\tcopies ACLs as well\n" + "\t --attrs\t\t\tcopies DOS Attributes as well\n" + "\t --timestampes\t\tpreserve timestampes while copying files\n" + "\t-e or --exclude\t\t\tlist of shares to be excluded from mirroring\n" + "\t-v or --verbose\t\t\tgive verbose output\n"); return -1; } @@ -163,25 +166,28 @@ int net_help_file(int argc, const char **argv) int net_help_printer(int argc, const char **argv) { - d_printf("net rpc printer LIST [printer]\n"\ + d_printf("net rpc printer LIST [printer] [misc. options] [targets]\n"\ "\tlists all printers on print-server\n\n"); - d_printf("net rpc printer DRIVER [printer]\n"\ + d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"\ "\tlists all printer-drivers on print-server\n\n"); - d_printf("net rpc printer MIGRATE PRINTERS [printer]"\ + d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"\ "\n\tmigrates printers from remote to local server\n\n"); - d_printf("net rpc printer MIGRATE SETTINGS [printer]"\ + d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"\ "\n\tmigrates printer-settings from remote to local server\n\n"); - d_printf("net rpc printer MIGRATE DRIVERS [printer]"\ + d_printf("net rpc printer MIGRATE DRIVERS [printer] [misc. options] [targets]"\ "\n\tmigrates printer-drivers from remote to local server\n\n"); - d_printf("net rpc printer MIGRATE FORMS [printer]"\ + d_printf("net rpc printer MIGRATE FORMS [printer] [misc. options] [targets]"\ "\n\tmigrates printer-forms from remote to local server\n\n"); - d_printf("net rpc printer MIGRATE SECURITY [printer]"\ + d_printf("net rpc printer MIGRATE SECURITY [printer] [misc. options] [targets]"\ "\n\tmigrates printer-ACLs from remote to local server\n\n"); - d_printf("net rpc printer MIGRATE ALL [printer]\n"\ - "\tmigrates drivers, forms, queues, settings and acls from\n"\ + d_printf("net rpc printer MIGRATE ALL [printer] [misc. options] [targets]"\ + "\n\tmigrates drivers, forms, queues, settings and acls from\n"\ "\tremote to local print-server\n\n"); net_common_methods_usage(argc, argv); net_common_flags_usage(argc, argv); + d_printf( + "\t-v or --verbose\t\t\tgive verbose output\n"); + return -1; } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 47e47f079f..26bcb51fa5 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -2576,7 +2576,7 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain /* only work with file-shares */ if (!cli_send_tconX(cli, netname, "A:", "", 0)) { - d_printf("skipping [%s]. not a file share.\n", netname); + d_printf("skipping [%s]: not a file share.\n", netname); continue; } @@ -2600,10 +2600,10 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain level, share_sd); if (W_ERROR_V(result) == W_ERROR_V(WERR_ALREADY_EXISTS)) { - printf("share does already exist\n"); + printf(" [%s] does already exist\n", netname); continue; - } - + } + if (!W_ERROR_IS_OK(result)) { printf("cannot add share: %s\n", dos_errstr(result)); goto done; @@ -2635,6 +2635,11 @@ done: static int rpc_share_migrate_shares(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } + return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv); @@ -2681,7 +2686,10 @@ static void copy_fn(file_info *f, const char *mask, void *state) local_state->cli_share_src, local_state->cli_share_dst, dir, dir, - opt_acls? True : False, False); + opt_acls? True : False, + opt_attrs? True : False, + opt_timestamps? True : False, + False); if (!NT_STATUS_IS_OK(nt_status)) printf("could not copy dir %s: %s\n", @@ -2713,7 +2721,10 @@ static void copy_fn(file_info *f, const char *mask, void *state) local_state->cli_share_src, local_state->cli_share_dst, filename, filename, - opt_acls? True : False, True); + opt_acls? True : False, + opt_attrs? True : False, + opt_timestamps? True: False, + True); if (!NT_STATUS_IS_OK(nt_status)) printf("could not copy file %s: %s\n", @@ -2826,26 +2837,29 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_ continue; if (strequal(netname, "print$") || netname[1] == '$') { - d_printf("skipping [%s]: builtin/hidden share\n", netname); + d_printf("skipping [%s]: builtin/hidden share\n", netname); continue; } if (opt_exclude && in_list(netname, (char *)opt_exclude, False)) { - printf("excluding [%s]\n", netname); + printf("excluding [%s]\n", netname); continue; } /* only work with file-shares */ if (!cli_send_tconX(cli, netname, "A:", "", 0)) { - d_printf("skipping [%s]: not a file share.\n", netname); + d_printf("skipping [%s]: not a file share.\n", netname); continue; } if (!cli_tdis(cli)) return NT_STATUS_UNSUCCESSFUL; - printf("syncing [%s] files and directories %s ACLs\n", - netname, opt_acls ? "including" : "without"); + printf("syncing [%s] files and directories %s ACLs, %s DOS Attributes %s\n", + netname, + opt_acls ? "including" : "without", + opt_attrs ? "including" : "without", + opt_timestamps ? "(preserving timestamps)" : ""); /* open share source */ @@ -2893,13 +2907,19 @@ done: static int rpc_share_migrate_files(int argc, const char **argv) { + + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } + return run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_files_internals, argc, argv); } /** - * Migrate shares (including share-definitions, share-acls and files with acls) + * Migrate shares (including share-definitions, share-acls and files with acls/attrs) * from one server to another * * @param argc Standard main() style argc @@ -2913,6 +2933,11 @@ static int rpc_share_migrate_all(int argc, const char **argv) { int ret; + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } + ret = run_rpc_command(NULL, PI_SRVSVC, 0, rpc_share_migrate_shares_internals, argc, argv); if (ret) return ret; @@ -2937,6 +2962,7 @@ static int rpc_share_migrate(int argc, const char **argv) struct functable func[] = { {"all", rpc_share_migrate_all}, {"files", rpc_share_migrate_files}, + {"help", rpc_share_usage}, /* {"security", rpc_share_migrate_security},*/ {"shares", rpc_share_migrate_shares}, {NULL, NULL} @@ -4044,6 +4070,11 @@ static int rpc_printer_migrate_all(int argc, const char **argv) { int ret; + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } + ret = run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, argc, argv); if (ret) return ret; @@ -4075,6 +4106,10 @@ static int rpc_printer_migrate_all(int argc, const char **argv) **/ static int rpc_printer_migrate_drivers(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_drivers_internals, @@ -4092,6 +4127,10 @@ static int rpc_printer_migrate_drivers(int argc, const char **argv) **/ static int rpc_printer_migrate_forms(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_forms_internals, @@ -4109,6 +4148,10 @@ static int rpc_printer_migrate_forms(int argc, const char **argv) **/ static int rpc_printer_migrate_printers(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_printers_internals, @@ -4126,6 +4169,10 @@ static int rpc_printer_migrate_printers(int argc, const char **argv) **/ static int rpc_printer_migrate_security(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_security_internals, @@ -4143,6 +4190,10 @@ static int rpc_printer_migrate_security(int argc, const char **argv) **/ static int rpc_printer_migrate_settings(int argc, const char **argv) { + if (!opt_host) { + printf("no server to migrate\n"); + return -1; + } return run_rpc_command(NULL, PI_SPOOLSS, 0, rpc_printer_migrate_settings_internals, @@ -4265,7 +4316,7 @@ int net_rpc_usage(int argc, const char **argv) d_printf(" net rpc user \t\t\tto add, delete and list users\n"); d_printf(" net rpc password [] -Uadmin_username%%admin_pass"); d_printf(" net rpc group \t\tto list groups\n"); - d_printf(" net rpc share \t\tto add, delete, and list shares\n"); + d_printf(" net rpc share \t\tto add, delete, list and migrate shares\n"); d_printf(" net rpc printer \t\tto list and migrate printers\n"); d_printf(" net rpc file \t\t\tto list open files\n"); d_printf(" net rpc changetrustpw \tto change the trust account password\n"); diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index e4197d72ce..7684878677 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/utils/net_rpc_printer.c @@ -283,6 +283,8 @@ static void display_reg_value(pstring subkey, REGISTRY_VALUE value) * @param src_file The source file-name * @param dst_file The destination file-name * @param copy_acls Whether to copy acls + * @param copy_attrs Whether to copy DOS attributes + * @param copy_timestamps Whether to preserve timestamps * @param is_file Whether this file is a file or a dir * * @return Normal NTSTATUS return. @@ -291,7 +293,8 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, struct cli_state *cli_share_src, struct cli_state *cli_share_dst, char *src_name, char *dst_name, - BOOL copy_acls, BOOL is_file) + BOOL copy_acls, BOOL copy_attrs, + BOOL copy_timestamps, BOOL is_file) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; int fnum_src = 0; @@ -302,6 +305,8 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, off_t start = 0; off_t nread = 0; SEC_DESC *sd = NULL; + uint16 attr; + time_t atime, ctime, mtime; /* open on the originating server */ @@ -349,7 +354,20 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, /* get the security descriptor */ sd = cli_query_secdesc(cli_share_src, fnum_src, mem_ctx); if (!sd) { - DEBUG(0, ("failed to get security descriptor\n")); + DEBUG(0, ("failed to get security descriptor: %s\n", + cli_errstr(cli_share_src))); + nt_status = cli_nt_error(cli_share_src); + goto out; + } + } + + if (copy_attrs || copy_timestamps) { + + /* get dos attributes */ + if (!cli_getattrE(cli_share_src, fnum_src, &attr, NULL, + &ctime, &atime, &mtime)) { + DEBUG(0, ("failed to get file-attrs: %s\n", + cli_errstr(cli_share_src))); nt_status = cli_nt_error(cli_share_src); goto out; } @@ -358,10 +376,13 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, /* copying file */ if (opt_verbose) { - d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] %s acls.\n", - cli_share_src->desthost, cli_share_src->share, src_name, + d_printf("copying [\\\\%s\\%s%s] => [\\\\%s\\%s%s] " + "%s acls and %s DOS Attributes %s\n", + cli_share_src->desthost, cli_share_src->share, src_name, cli_share_dst->desthost, cli_share_dst->share, dst_name, - copy_acls ? "with" : "without" ); + copy_acls ? "with" : "without", + copy_attrs ? "with" : "without", + copy_timestamps ? "(preserving timestamps)" : "" ); if (DEBUGLEVEL >= 3 && copy_acls) display_sec_desc(sd); @@ -392,7 +413,7 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, /* creating dir */ if (!is_file && !cli_chkpath(cli_share_dst, dst_name)) { - DEBUGADD(1,("creating dir %s on the destination server\n", + DEBUGADD(3,("creating dir %s on the destination server\n", dst_name)); if (!cli_mkdir(cli_share_dst, dst_name)) { @@ -408,47 +429,67 @@ NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, } } - - /* closing files */ - if (!cli_close(cli_share_src, fnum_src)) { - d_printf("could not close file on originating server: %s\n", - cli_errstr(cli_share_src)); - nt_status = cli_nt_error(cli_share_src); - goto out; - } - - if (is_file && !cli_close(cli_share_dst, fnum_dst)) { - d_printf("could not close file on destinantion server: %s\n", - cli_errstr(cli_share_dst)); + /* open the file/dir a second time */ + fnum_dst = cli_nt_create(cli_share_dst, dst_name, + WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); + + if (fnum_dst == -1) { + DEBUG(0,("failed to open file/dir again: %s: %s\n", + dst_name, cli_errstr(cli_share_dst))); nt_status = cli_nt_error(cli_share_dst); goto out; } + /* set timestamps */ + if (copy_timestamps) { + + if (!cli_setattrE(cli_share_dst, fnum_dst, ctime, atime, mtime)) { + DEBUG(0,("failed to set file-attrs (timestamps): %s\n", + cli_errstr(cli_share_dst))); + nt_status = cli_nt_error(cli_share_dst); + goto out; + } + } - /* finally set acls */ + /* set acls */ if (copy_acls) { - /* Open the file/dir a second time */ - fnum_dst = cli_nt_create(cli_share_dst, dst_name, - WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS); - - if (fnum_dst == -1) { - DEBUG(0, ("failed to open file/dir again: %s: %s\n", - dst_name, cli_errstr(cli_share_dst))); + if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) { + DEBUG(0,("could not set secdesc on %s %s: %s\n", + is_file? "file":"dir", dst_name, + cli_errstr(cli_share_dst))); nt_status = cli_nt_error(cli_share_dst); goto out; } + } - if (!cli_set_secdesc(cli_share_dst, fnum_dst, sd)) { - DEBUG(0, ("could not set secdesc on %s %s: %s\n", - is_file? "file":"dir", dst_name, + /* set attrs */ + if (copy_attrs) { + + if (!cli_setatr(cli_share_dst, dst_name, attr, 0)) { + DEBUG(0,("failed to set file-attrs: %s\n", cli_errstr(cli_share_dst))); nt_status = cli_nt_error(cli_share_dst); goto out; } } - + /* closing files */ + if (!cli_close(cli_share_src, fnum_src)) { + d_printf("could not close file on originating server: %s\n", + cli_errstr(cli_share_src)); + nt_status = cli_nt_error(cli_share_src); + goto out; + } + + if (is_file && !cli_close(cli_share_dst, fnum_dst)) { + d_printf("could not close file on destination server: %s\n", + cli_errstr(cli_share_dst)); + nt_status = cli_nt_error(cli_share_dst); + goto out; + } + + nt_status = NT_STATUS_OK; out: @@ -520,7 +561,7 @@ static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx, /* finally copy the file */ nt_status = net_copy_file(mem_ctx, cli_share_src, cli_share_dst, - src_name, dst_name, False, True); + src_name, dst_name, False, False, False, True); if (!NT_STATUS_IS_OK(nt_status)) goto out; -- cgit