}
}
+/****************************************************************************
+ Local name cleanup before sending to server. SMB1 allows relative pathnames,
+ but SMB2 does not, so we need to resolve them locally.
+****************************************************************************/
+
+char *client_clean_name(TALLOC_CTX *ctx, const char *name)
+{
+ char *newname = NULL;
+ if (name == NULL) {
+ return NULL;
+ }
+
+ /* First ensure any path separators are correct. */
+ newname = talloc_strdup(ctx, name);
+ if (newname == NULL) {
+ return NULL;
+ }
+ normalize_name(newname);
+
+ /* Now remove any relative (..) path components. */
+ if (cli->requested_posix_capabilities & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
+ newname = unix_clean_name(ctx, newname);
+ } else {
+ newname = clean_name(ctx, newname);
+ }
+ if (newname == NULL) {
+ return NULL;
+ }
+ return newname;
+}
+
/****************************************************************************
Change directory - inner section.
****************************************************************************/
}
client_set_cur_dir(new_cd);
- new_cd = clean_name(ctx, new_cd);
+ new_cd = client_clean_name(ctx, new_cd);
client_set_cur_dir(new_cd);
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
client_set_cur_dir(saved_dir);
goto out;
}
- targetpath = clean_name(ctx, targetpath);
+ targetpath = client_clean_name(ctx, targetpath);
if (!targetpath) {
client_set_cur_dir(saved_dir);
goto out;
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
+
if (showacls) {
/* cwd is only used if showacls is on */
client_set_cwd(client_get_cur_dir());
} else {
mask = talloc_strdup(ctx, "*");
}
+ if (!mask) {
+ return 1;
+ }
+
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = do_list(mask, attribute, do_du, recurse, true);
if (!NT_STATUS_IS_OK(status)) {
if (!rname) {
return 1;
}
- rname = clean_name(ctx, rname);
+ rname = client_clean_name(ctx, rname);
if (!rname) {
return 1;
}
if (!rname) {
return NT_STATUS_NO_MEMORY;
}
+ rname = client_clean_name(ctx, rname);
+ if (rname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
do_get(rname, finfo->name, false);
TALLOC_FREE(rname);
return NT_STATUS_OK;
if (!new_cd) {
return NT_STATUS_NO_MEMORY;
}
+ new_cd = client_clean_name(ctx, new_cd);
+ if (new_cd == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
client_set_cur_dir(new_cd);
string_replace(finfo->name,'\\','/');
return NT_STATUS_NO_MEMORY;
}
+ mget_mask = client_clean_name(ctx, mget_mask);
+ if (mget_mask == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
status = do_list(mget_mask,
(FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
if (!rname) {
return 1;
}
- rname = clean_name(ctx,rname);
+ rname = client_clean_name(ctx,rname);
if (!rname) {
return 1;
}
if (!mget_mask) {
return 1;
}
+ mget_mask = client_clean_name(ctx, mget_mask);
+ if (mget_mask == NULL) {
+ return 1;
+ }
status = do_list(mget_mask, attribute, do_mget, false, true);
if (!NT_STATUS_IS_OK(status)) {
return 1;
if (!mget_mask) {
return 1;
}
+ mget_mask = client_clean_name(ctx, mget_mask);
+ if (mget_mask == NULL) {
+ return 1;
+ }
status = do_list(mget_mask, attribute, do_mget, false, true);
if (!NT_STATUS_IS_OK(status)) {
return 1;
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
if (recurse) {
char *ddir = NULL;
if (!name) {
return 1;
}
+ name = client_clean_name(ctx, name);
+ if (name == NULL) {
+ return 1;
+ }
do_altname(name);
return 0;
}
if (!name) {
return 1;
}
-
+ name = client_clean_name(ctx, name);
+ if (name == NULL) {
+ return 1;
+ }
do_allinfo(name);
return 0;
return 1;
}
- rname = clean_name(ctx, rname);
+ rname = client_clean_name(ctx, rname);
if (!rname) {
return 1;
}
for (list = l_head; list; list = next) {
next = list->next;
DLIST_REMOVE(l_head, list);
- SAFE_FREE(list->file_path);
- SAFE_FREE(list);
+ TALLOC_FREE(list);
}
}
match must be always set to true when calling this function
****************************************************************************/
-static int file_find(struct file_list **list, const char *directory,
- const char *expression, bool match)
+static int file_find(TALLOC_CTX *ctx,
+ struct file_list **list,
+ const char *directory,
+ const char *expression,
+ bool match)
{
DIR *dir;
struct file_list *entry;
if (!strcmp(".", dname))
continue;
- if (asprintf(&path, "%s/%s", directory, dname) <= 0) {
+ path = talloc_asprintf(ctx, "%s/%s", directory, dname);
+ if (path == NULL) {
continue;
}
if (ret == 0) {
if (S_ISDIR(statbuf.st_mode)) {
isdir = true;
- ret = file_find(list, path, expression, false);
+ ret = file_find(ctx,
+ list,
+ path,
+ expression,
+ false);
}
} else {
d_printf("file_find: cannot stat file %s\n", path);
}
if (ret == -1) {
- SAFE_FREE(path);
+ TALLOC_FREE(path);
closedir(dir);
return -1;
}
}
- entry = SMB_MALLOC_P(struct file_list);
+ entry = talloc_zero(ctx, struct file_list);
if (!entry) {
d_printf("Out of memory in file_find\n");
closedir(dir);
return -1;
}
- entry->file_path = path;
+ entry->file_path = talloc_move(entry, &path);
entry->isdir = isdir;
DLIST_ADD(*list, entry);
} else {
- SAFE_FREE(path);
+ TALLOC_FREE(path);
}
}
file_list = NULL;
- ret = file_find(&file_list, ".", p, true);
+ ret = file_find(ctx, &file_list, ".", p, true);
if (ret) {
free_file_list(file_list);
continue;
break;
}
normalize_name(rname);
+ {
+ char *tmp_rname =
+ client_clean_name(ctx, rname);
+ if (tmp_rname == NULL) {
+ break;
+ }
+ SAFE_FREE(rname);
+ rname = smb_xstrdup(tmp_rname);
+ TALLOC_FREE(tmp_rname);
+ if (rname == NULL) {
+ break;
+ }
+ }
if (!NT_STATUS_IS_OK(cli_chkpath(cli, rname)) &&
!do_mkdir(rname)) {
DEBUG (0, ("Unable to make dir, skipping..."));
normalize_name(rname);
+ {
+ char *tmp_rname = client_clean_name(ctx, rname);
+ if (tmp_rname == NULL) {
+ break;
+ }
+ SAFE_FREE(rname);
+ rname = smb_xstrdup(tmp_rname);
+ TALLOC_FREE(tmp_rname);
+ if (rname == NULL) {
+ break;
+ }
+ }
do_put(rname, lname, false);
}
free_file_list(file_list);
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = do_list(mask,attribute,do_del,false,false);
if (!NT_STATUS_IS_OK(status)) {
return 0;
}
+/****************************************************************************
+ Delete some files.
+****************************************************************************/
+
+static NTSTATUS delete_remote_files_list(struct cli_state *cli_state,
+ struct file_list *flist)
+{
+ NTSTATUS status = NT_STATUS_OK;
+ struct file_list *deltree_list_iter = NULL;
+
+ for (deltree_list_iter = flist;
+ deltree_list_iter != NULL;
+ deltree_list_iter = deltree_list_iter->next) {
+ if (CLI_DIRSEP_CHAR == '/') {
+ /* POSIX. */
+ status = cli_posix_unlink(cli_state,
+ deltree_list_iter->file_path);
+ } else if (deltree_list_iter->isdir) {
+ status = cli_rmdir(cli_state,
+ deltree_list_iter->file_path);
+ } else {
+ status = cli_unlink(cli_state,
+ deltree_list_iter->file_path,
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("%s deleting remote %s %s\n",
+ nt_errstr(status),
+ deltree_list_iter->isdir ?
+ "directory" : "file",
+ deltree_list_iter->file_path);
+ return status;
+ }
+ }
+ return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ Save a list of files to delete.
+****************************************************************************/
+
+static struct file_list *deltree_list_head;
+
+static NTSTATUS do_deltree_list(struct cli_state *cli_state,
+ struct file_info *finfo,
+ const char *dir)
+{
+ struct file_list **file_list_head_pp = &deltree_list_head;
+ struct file_list *dt = NULL;
+
+ if (!do_this_one(finfo)) {
+ return NT_STATUS_OK;
+ }
+
+ /* skip if this is . or .. */
+ if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
+ return NT_STATUS_OK;
+ }
+
+ dt = talloc_zero(NULL, struct file_list);
+ if (dt == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* create absolute filename for cli_ntcreate() */
+ dt->file_path = talloc_asprintf(dt,
+ "%s%s%s",
+ dir,
+ CLI_DIRSEP_STR,
+ finfo->name);
+ if (dt->file_path == NULL) {
+ TALLOC_FREE(dt);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
+ dt->isdir = true;
+ }
+
+ DLIST_ADD(*file_list_head_pp, dt);
+ return NT_STATUS_OK;
+}
+
+static int cmd_deltree(void)
+{
+ TALLOC_CTX *ctx = talloc_tos();
+ char *buf = NULL;
+ NTSTATUS status = NT_STATUS_OK;
+ struct file_list *deltree_list_norecurse = NULL;
+ struct file_list *deltree_list_iter = NULL;
+ uint16_t attribute = FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN |
+ FILE_ATTRIBUTE_DIRECTORY;
+ bool ok;
+ char *mask = talloc_strdup(ctx, client_get_cur_dir());
+ if (mask == NULL) {
+ return 1;
+ }
+ ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
+ if (!ok) {
+ d_printf("deltree <filename>\n");
+ return 1;
+ }
+ mask = talloc_asprintf_append(mask, "%s", buf);
+ if (mask == NULL) {
+ return 1;
+ }
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
+
+ deltree_list_head = NULL;
+
+ /*
+ * Get the list of directories to
+ * delete (in case mask has a wildcard).
+ */
+ status = do_list(mask, attribute, do_deltree_list, false, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
+ deltree_list_norecurse = deltree_list_head;
+ deltree_list_head = NULL;
+
+ for (deltree_list_iter = deltree_list_norecurse;
+ deltree_list_iter != NULL;
+ deltree_list_iter = deltree_list_iter->next) {
+
+ if (deltree_list_iter->isdir == false) {
+ /* Just a regular file. */
+ if (CLI_DIRSEP_CHAR == '/') {
+ /* POSIX. */
+ status = cli_posix_unlink(cli,
+ deltree_list_iter->file_path);
+ } else {
+ status = cli_unlink(cli,
+ deltree_list_iter->file_path,
+ FILE_ATTRIBUTE_SYSTEM |
+ FILE_ATTRIBUTE_HIDDEN);
+ }
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
+ continue;
+ }
+
+ /*
+ * Get the list of files or directories to
+ * delete in depth order.
+ */
+ status = do_list(deltree_list_iter->file_path,
+ attribute,
+ do_deltree_list,
+ true,
+ true);
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
+ status = delete_remote_files_list(cli, deltree_list_head);
+ free_file_list(deltree_list_head);
+ deltree_list_head = NULL;
+ if (!NT_STATUS_IS_OK(status)) {
+ goto err;
+ }
+ }
+
+ free_file_list(deltree_list_norecurse);
+ free_file_list(deltree_list_head);
+ return 0;
+
+ err:
+
+ free_file_list(deltree_list_norecurse);
+ free_file_list(deltree_list_head);
+ deltree_list_head = NULL;
+ return 1;
+}
+
+
/****************************************************************************
Wildcard delete some files.
****************************************************************************/
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, mask, &targetcli, &targetname);
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
+
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, mask, &targetcli, &targetname);
if (!NT_STATUS_IS_OK(status)) {
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_open <filename> 0<mode>\n");
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
if (!next_token_talloc(ctx, &cmd_ptr,&buf,NULL)) {
d_printf("posix_mkdir <filename> 0<mode>\n");
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, mask, &targetcli, &targetname);
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, mask, &targetcli, &targetname);
if (!mask) {
return 1;
}
+ mask = client_clean_name(ctx, mask);
+ if (mask == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, mask, &targetcli, &targetname);
if (!oldname) {
return 1;
}
+ oldname = client_clean_name(ctx, oldname);
+ if (oldname == NULL) {
+ return 1;
+ }
newname = talloc_asprintf(ctx,
"%s%s",
client_get_cur_dir(),
if (!newname) {
return 1;
}
+ newname = client_clean_name(ctx, newname);
+ if (newname == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, oldname, &targetcli, &targetname);
if (!name) {
return 1;
}
+ name = client_clean_name(ctx, name);
+ if (name == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, name, &targetcli, &targetname);
if (!newname) {
return 1;
}
+ newname = client_clean_name(ctx, newname);
+ if (newname == NULL) {
+ return 1;
+ }
/* New name must be present in share namespace. */
status = cli_resolve_path(ctx, "",
popt_get_cmdline_auth_info(), cli, newname,
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
mode = (mode_t)strtol(buf, NULL, 8);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (!NT_STATUS_IS_OK(status)) {
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
dest = talloc_asprintf(ctx,
"%s%s",
if (!dest) {
return 1;
}
+ dest = client_clean_name(ctx, dest);
+ if (dest == NULL) {
+ return 1;
+ }
if (next_token_talloc(ctx, &cmd_ptr, &buf, NULL) &&
strcsequal(buf, "-f")) {
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
dest = talloc_asprintf(ctx,
"%s%s",
if (!dest) {
return 1;
}
+ dest = client_clean_name(ctx, dest);
+ if (dest == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetsrc);
if (!src) {
return 1;
}
+ src = client_clean_name(ctx, src);
+ if (src == NULL) {
+ return 1;
+ }
dest = talloc_asprintf(ctx,
"%s%s",
if (!dest) {
return 1;
}
+ dest = client_clean_name(ctx, dest);
+ if (dest == NULL) {
+ return 1;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, src, &targetcli, &targetname);
if (name == NULL) {
goto fail;
}
+ name = client_clean_name(talloc_tos(), name);
+ if (name == NULL) {
+ return 1;
+ }
status = cli_ntcreate(
cli, name, 0, FILE_READ_DATA, 0,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
if (!remote_name) {
return 1;
}
- remote_name = clean_name(ctx,remote_name);
+ remote_name = client_clean_name(ctx,remote_name);
if (!remote_name) {
return 1;
}
return 1;
}
- remote_name = clean_name(ctx, remote_name);
+ remote_name = client_clean_name(ctx, remote_name);
if (!remote_name) {
return 1;
}
return 0;
}
+/**
+ * set_remote_times - set times of a remote file
+ * @filename: path to the file name
+ * @create_time: New create time
+ * @access_time: New access time
+ * @write_time: New write time
+ * @change_time: New metadata change time
+ *
+ * Update the file times with the ones provided.
+ */
+static int set_remote_times(const char *filename, time_t create_time,
+ time_t access_time, time_t write_time,
+ time_t change_time)
+{
+ extern struct cli_state *cli;
+ NTSTATUS status;
+
+ status = cli_setpathinfo_basic(cli, filename, create_time,
+ access_time, write_time,
+ change_time, -1);
+ if (!NT_STATUS_IS_OK(status)) {
+ d_printf("cli_setpathinfo_basic failed: %s\n",
+ nt_errstr(status));
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * cmd_utimes - interactive command to set the four times
+ *
+ * Read a filename and four times from the client command line and update
+ * the file times. A value of -1 for a time means don't change.
+ */
+static int cmd_utimes(void)
+{
+ const extern char *cmd_ptr;
+ char *buf;
+ char *fname = NULL;
+ time_t times[4] = {0, 0, 0, 0};
+ int time_count = 0;
+ int err = 0;
+ bool ok;
+ TALLOC_CTX *ctx = talloc_new(NULL);
+ if (ctx == NULL) {
+ return 1;
+ }
+
+ ok = next_token_talloc(ctx, &cmd_ptr, &buf, NULL);
+ if (!ok) {
+ d_printf("utimes <filename> <create-time> <access-time> "
+ "<write-time> <change-time>\n");
+ d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
+ "or -1 for no change\n");
+ err = 1;
+ goto out;
+ }
+
+ fname = talloc_asprintf(ctx,
+ "%s%s",
+ client_get_cur_dir(),
+ buf);
+ if (fname == NULL) {
+ err = 1;
+ goto out;
+ }
+ fname = client_clean_name(ctx, fname);
+ if (fname == NULL) {
+ err = 1;
+ goto out;
+ }
+
+ while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL) &&
+ time_count < 4) {
+ const char *s = buf;
+ struct tm tm = {0,};
+ char *ret;
+
+ if (strlen(s) == 2 && strcmp(s, "-1") == 0) {
+ times[time_count] = 0;
+ time_count++;
+ continue;
+ } else {
+ ret = strptime(s, "%y:%m:%d-%H:%M:%S", &tm);
+ }
+
+ /* We could not match all the chars, so print error */
+ if (ret == NULL || *ret != 0) {
+ d_printf("Invalid date format: %s\n", s);
+ d_printf("utimes <filename> <create-time> "
+ "<access-time> <write-time> <change-time>\n");
+ d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
+ "or -1 for no change\n");
+ err = 1;
+ goto out;
+ }
+
+ /* Convert tm to a time_t */
+ times[time_count] = mktime(&tm);
+ time_count++;
+ }
+
+ if (time_count < 4) {
+ d_printf("Insufficient dates: %d\n", time_count);
+ d_printf("utimes <filename> <create-time> <access-time> "
+ "<write-time> <change-time>\n");
+ d_printf("Dates should be in YY:MM:DD-HH:MM:SS format "
+ "or -1 for no change\n");
+ err = 1;
+ goto out;
+ }
+
+ DEBUG(10, ("times\nCreate: %sAccess: %s Write: %sChange: %s\n",
+ talloc_strdup(ctx, ctime(×[0])),
+ talloc_strdup(ctx, ctime(×[1])),
+ talloc_strdup(ctx, ctime(×[2])),
+ talloc_strdup(ctx, ctime(×[3]))));
+
+ set_remote_times(fname, times[0], times[1], times[2], times[3]);
+out:
+ talloc_free(ctx);
+ return err;
+}
+
/**
* set_remote_attr - set DOS attributes of a remote file
* @filename: path to the file name
err = 1;
goto out;
}
+ fname = client_clean_name(ctx, fname);
+ if (fname == NULL) {
+ err = 1;
+ goto out;
+ }
while (next_token_talloc(ctx, &cmd_ptr, &buf, NULL)) {
const char *s = buf;
{"chown",cmd_chown,"<src> <uid> <gid> chown a file using UNIX uids and gids",{COMPL_REMOTE,COMPL_NONE}},
{"close",cmd_close,"<fid> close a file given a fid",{COMPL_REMOTE,COMPL_NONE}},
{"del",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
+ {"deltree",cmd_deltree,"<mask> recursively delete all matching files and directories",{COMPL_REMOTE,COMPL_NONE}},
{"dir",cmd_dir,"<mask> list the contents of the current directory",{COMPL_REMOTE,COMPL_NONE}},
{"du",cmd_du,"<mask> computes the total size of the current directory",{COMPL_REMOTE,COMPL_NONE}},
{"echo",cmd_echo,"ping the server",{COMPL_NONE,COMPL_NONE}},
{"tcon",cmd_tcon,"connect to a share" ,{COMPL_NONE,COMPL_NONE}},
{"tdis",cmd_tdis,"disconnect from a share",{COMPL_NONE,COMPL_NONE}},
{"tid",cmd_tid,"show or set the current tid (tree-id)",{COMPL_NONE,COMPL_NONE}},
+ {"utimes", cmd_utimes,"<file name> <create_time> <access_time> <mod_time> "
+ "<ctime> set times", {COMPL_REMOTE,COMPL_NONE}},
{"logoff",cmd_logoff,"log off (close the session)",{COMPL_NONE,COMPL_NONE}},
{"..",cmd_cd_oneup,"change the remote directory (up one level)",{COMPL_REMOTE,COMPL_NONE}},
if (!dirmask) {
goto cleanup;
}
+ dirmask = client_clean_name(ctx, dirmask);
+ if (dirmask == NULL) {
+ goto cleanup;
+ }
status = cli_resolve_path(ctx, "", popt_get_cmdline_auth_info(),
cli, dirmask, &targetcli, &targetpath);
/* Ping the server to keep the connection alive using SMBecho. */
memset(garbage, 0xf0, sizeof(garbage));
status = cli_echo(cli, 1, data_blob_const(garbage, sizeof(garbage)));
- if (NT_STATUS_IS_OK(status)) {
+ if (NT_STATUS_IS_OK(status) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+ /*
+ * Even if server returns NT_STATUS_INVALID_PARAMETER
+ * it still responded.
+ * BUG: https://bugzilla.samba.org/show_bug.cgi?id=13007
+ */
return;
}
{
int rc = 0;
- d_printf("Try \"help\" do get a list of possible commands.\n");
+ d_printf("Try \"help\" to get a list of possible commands.\n");
while (!finished) {
TALLOC_CTX *frame = talloc_stackframe();
}
}
+ if (lp_client_min_protocol() > PROTOCOL_NT1) {
+ d_printf("SMB1 disabled -- no workgroup available\n");
+ goto out;
+ }
+
if (lp_disable_netbios()) {
+ d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
goto out;
}
*/
cli_shutdown(cli);
+ d_printf("Reconnecting with SMB1 for workgroup listing.\n");
status = cli_cm_open(talloc_tos(), NULL,
have_ip ? dest_ss_str : query_host,
"IPC$", popt_get_cmdline_auth_info(),
smb_encrypt, max_proto,
NBT_SMB_PORT, name_type, &cli);
if (!NT_STATUS_IS_OK(status)) {
- cli = NULL;
+ d_printf("Failed to connect with SMB1 "
+ "-- no workgroup available\n");
+ return 0;
}
}
- if (cli == NULL) {
- d_printf("NetBIOS over TCP disabled -- no workgroup available\n");
- return 0;
- }
-
cli_set_timeout(cli, io_timeout*1000);
list_servers(lp_workgroup());
out: