-/*
+/*
Unix SMB/Netbios implementation.
SMB client library implementation
Copyright (C) Andrew Tridgell 1998
Copyright (C) Richard Sharpe 2000, 2002
Copyright (C) John Terpstra 2000
- Copyright (C) Tom Jansen (Ninja ISD) 2002
+ Copyright (C) Tom Jansen (Ninja ISD) 2002
Copyright (C) Derrell Lipman 2003-2008
Copyright (C) Jeremy Allison 2007, 2008
*/
#include "includes.h"
+#include "libsmb/libsmb.h"
#include "libsmbclient.h"
#include "libsmb_internal.h"
-
+#include "../libcli/smb/smbXcli_base.h"
/*
* Routine to open() a file ...
SMBCSRV *srv = NULL;
SMBCFILE *file = NULL;
uint16_t fd;
+ uint16_t port = 0;
NTSTATUS status = NT_STATUS_OBJECT_PATH_INVALID;
TALLOC_CTX *frame = talloc_stackframe();
fname,
&workgroup,
&server,
+ &port,
&share,
&path,
&user,
}
srv = SMBC_server(frame, context, True,
- server, share, &workgroup, &user, &password);
+ server, port, share, &workgroup, &user, &password);
if (!srv) {
if (errno == EPERM) errno = EACCES;
TALLOC_FREE(frame);
ZERO_STRUCTP(file);
/*d_printf(">>>open: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- srv->cli, path,
- &targetcli, &targetpath)) {
+ status = cli_resolve_path(
+ frame, "", context->internal->auth_info,
+ srv->cli, path, &targetcli, &targetpath);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("Could not resolve %s\n", path);
errno = ENOENT;
SAFE_FREE(file);
file->srv = srv;
file->offset = 0;
file->file = True;
+ /*
+ * targetcli is either equal to srv->cli or
+ * is a subsidiary DFS connection. Either way
+ * file->cli_fd belongs to it so we must cache
+ * it for read/write/close, not re-resolve each time.
+ * Re-resolving is both slow and incorrect.
+ */
+ file->targetcli = targetcli;
DLIST_ADD(context->internal->files, file);
}
/*
- * Routine to create a file
+ * Routine to create a file
*/
SMBCFILE *
void *buf,
size_t count)
{
- int ret;
- char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
- char *path = NULL;
- char *targetpath = NULL;
- struct cli_state *targetcli = NULL;
+ size_t ret;
TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status;
/*
* offset:
return -1;
}
- /*d_printf(">>>read: parsing %s\n", file->fname);*/
- if (SMBC_parse_path(frame,
- context,
- file->fname,
- NULL,
- &server,
- &share,
- &path,
- &user,
- &password,
- NULL)) {
- errno = EINVAL;
+ status = cli_read(file->targetcli, file->cli_fd, (char *)buf, offset,
+ count, &ret);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = SMBC_errno(context, file->targetcli);
TALLOC_FREE(frame);
- return -1;
- }
+ return -1;
+ }
- /*d_printf(">>>read: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- file->srv->cli, path,
- &targetcli, &targetpath)) {
- d_printf("Could not resolve %s\n", path);
- errno = ENOENT;
+ file->offset += ret;
+
+ DEBUG(4, (" --> %ld\n", (unsigned long)ret));
+
+ TALLOC_FREE(frame);
+ return ret; /* Success, ret bytes of data ... */
+}
+
+off_t
+SMBC_splice_ctx(SMBCCTX *context,
+ SMBCFILE *srcfile,
+ SMBCFILE *dstfile,
+ off_t count,
+ int (*splice_cb)(off_t n, void *priv),
+ void *priv)
+{
+ off_t written;
+ TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status;
+
+ if (!context || !context->internal->initialized) {
+ errno = EINVAL;
TALLOC_FREE(frame);
return -1;
}
- /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
- ret = cli_read(targetcli, file->cli_fd, (char *)buf, offset, count);
+ if (!srcfile ||
+ !SMBC_dlist_contains(context->internal->files, srcfile))
+ {
+ errno = EBADF;
+ TALLOC_FREE(frame);
+ return -1;
+ }
- if (ret < 0) {
- errno = SMBC_errno(context, targetcli);
+ if (!dstfile ||
+ !SMBC_dlist_contains(context->internal->files, dstfile))
+ {
+ errno = EBADF;
TALLOC_FREE(frame);
return -1;
}
- file->offset += ret;
+ status = cli_splice(srcfile->targetcli, dstfile->targetcli,
+ srcfile->cli_fd, dstfile->cli_fd,
+ count, srcfile->offset, dstfile->offset, &written,
+ splice_cb, priv);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = SMBC_errno(context, srcfile->targetcli);
+ TALLOC_FREE(frame);
+ return -1;
+ }
- DEBUG(4, (" --> %d\n", ret));
+ srcfile->offset += written;
+ dstfile->offset += written;
TALLOC_FREE(frame);
- return ret; /* Success, ret bytes of data ... */
+ return written;
}
/*
const void *buf,
size_t count)
{
- int ret;
off_t offset;
- char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
- char *path = NULL;
- char *targetpath = NULL;
- struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status;
/* First check all pointers before dereferencing them */
offset = file->offset; /* See "offset" comment in SMBC_read_ctx() */
- /*d_printf(">>>write: parsing %s\n", file->fname);*/
- if (SMBC_parse_path(frame,
- context,
- file->fname,
- NULL,
- &server,
- &share,
- &path,
- &user,
- &password,
- NULL)) {
- errno = EINVAL;
- TALLOC_FREE(frame);
- return -1;
- }
-
- /*d_printf(">>>write: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- file->srv->cli, path,
- &targetcli, &targetpath)) {
- d_printf("Could not resolve %s\n", path);
- errno = ENOENT;
- TALLOC_FREE(frame);
- return -1;
- }
- /*d_printf(">>>write: resolved path as %s\n", targetpath);*/
-
- ret = cli_write(targetcli, file->cli_fd,
- 0, (char *)buf, offset, count);
- if (ret <= 0) {
- errno = SMBC_errno(context, targetcli);
+ status = cli_writeall(file->targetcli, file->cli_fd,
+ 0, (const uint8_t *)buf, offset, count, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ errno = map_errno_from_nt_status(status);
TALLOC_FREE(frame);
return -1;
}
- file->offset += ret;
+ file->offset += count;
TALLOC_FREE(frame);
- return ret; /* Success, 0 bytes of data ... */
+ return count; /* Success, 0 bytes of data ... */
}
/*
SMBC_close_ctx(SMBCCTX *context,
SMBCFILE *file)
{
- SMBCSRV *srv;
- char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
- char *path = NULL;
- char *targetpath = NULL;
- struct cli_state *targetcli = NULL;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
return smbc_getFunctionClosedir(context)(context, file);
}
- /*d_printf(">>>close: parsing %s\n", file->fname);*/
- if (SMBC_parse_path(frame,
- context,
- file->fname,
- NULL,
- &server,
- &share,
- &path,
- &user,
- &password,
- NULL)) {
- errno = EINVAL;
- TALLOC_FREE(frame);
- return -1;
- }
-
- /*d_printf(">>>close: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- file->srv->cli, path,
- &targetcli, &targetpath)) {
- d_printf("Could not resolve %s\n", path);
- errno = ENOENT;
- TALLOC_FREE(frame);
- return -1;
- }
- /*d_printf(">>>close: resolved path as %s\n", targetpath);*/
-
- if (!NT_STATUS_IS_OK(cli_close(targetcli, file->cli_fd))) {
- DEBUG(3, ("cli_close failed on %s. purging server.\n",
+ if (!NT_STATUS_IS_OK(cli_close(file->targetcli, file->cli_fd))) {
+ SMBCSRV *srv;
+ DEBUG(3, ("cli_close failed on %s. purging server.\n",
file->fname));
- /* Deallocate slot and remove the server
+ /* Deallocate slot and remove the server
* from the server cache if unused */
- errno = SMBC_errno(context, targetcli);
+ errno = SMBC_errno(context, file->targetcli);
srv = file->srv;
DLIST_REMOVE(context->internal->files, file);
SAFE_FREE(file->fname);
bool
SMBC_getatr(SMBCCTX * context,
SMBCSRV *srv,
- char *path,
- uint16 *mode,
- SMB_OFF_T *size,
+ const char *path,
+ uint16_t *mode,
+ off_t *size,
struct timespec *create_time_ts,
struct timespec *access_time_ts,
struct timespec *write_time_ts,
struct cli_state *targetcli = NULL;
time_t write_time;
TALLOC_CTX *frame = talloc_stackframe();
+ NTSTATUS status;
if (!context || !context->internal->initialized) {
errno = EINVAL;
}
DEBUG(4,("SMBC_getatr: sending qpathinfo\n"));
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- srv->cli, fixedpath,
- &targetcli, &targetpath)) {
+ status = cli_resolve_path(frame, "", context->internal->auth_info,
+ srv->cli, fixedpath,
+ &targetcli, &targetpath);
+ if (!NT_STATUS_IS_OK(status)) {
d_printf("Couldn't resolve %s\n", path);
errno = ENOENT;
TALLOC_FREE(frame);
return True;
}
- /* if this is NT then don't bother with the getatr */
- if (targetcli->capabilities & CAP_NT_SMBS) {
- errno = EPERM;
+ srv->no_pathinfo2 = True;
+
+ if (!srv->no_pathinfo3 &&
+ NT_STATUS_IS_OK(cli_qpathinfo3(targetcli, targetpath,
+ create_time_ts,
+ access_time_ts,
+ write_time_ts,
+ change_time_ts,
+ size, mode, ino))) {
TALLOC_FREE(frame);
- return False;
+ return True;
+ }
+
+ srv->no_pathinfo3 = True;
+
+ /* if this is NT then don't bother with the getatr */
+ if (smb1cli_conn_capabilities(targetcli->conn) & CAP_NT_SMBS) {
+ goto all_failed;
}
if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) {
if (change_time_ts != NULL) {
*change_time_ts = w_time_ts;
}
- srv->no_pathinfo2 = True;
+ if (ino) {
+ *ino = 0;
+ }
TALLOC_FREE(frame);
return True;
}
+all_failed:
+ srv->no_pathinfo2 = False;
+ srv->no_pathinfo3 = False;
+
errno = EPERM;
TALLOC_FREE(frame);
return False;
* "mode" (attributes) parameter may be set to -1 if it is not to be set.
*/
bool
-SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
+SMBC_setatr(SMBCCTX * context, SMBCSRV *srv, char *path,
time_t create_time,
time_t access_time,
time_t write_time,
time_t change_time,
- uint16 mode)
+ uint16_t mode)
{
uint16_t fd;
int ret;
mode))) {
/*
- * setpathinfo is not supported; go to plan B.
+ * setpathinfo is not supported; go to plan B.
*
* cli_setatr() does not work on win98, and it also doesn't
* support setting the access time (only the modification
* cli_setatr() for that, and with only this parameter, it
* seems to work on win98.
*/
- if (ret && mode != (uint16) -1) {
+ if (ret && mode != (uint16_t) -1) {
ret = NT_STATUS_IS_OK(cli_setatr(srv->cli, path, mode, 0));
}
off_t offset,
int whence)
{
- SMB_OFF_T size;
- char *server = NULL, *share = NULL, *user = NULL, *password = NULL;
- char *path = NULL;
- char *targetpath = NULL;
- struct cli_state *targetcli = NULL;
+ off_t size;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
file->offset += offset;
break;
case SEEK_END:
- /*d_printf(">>>lseek: parsing %s\n", file->fname);*/
- if (SMBC_parse_path(frame,
- context,
- file->fname,
- NULL,
- &server,
- &share,
- &path,
- &user,
- &password,
- NULL)) {
- errno = EINVAL;
- TALLOC_FREE(frame);
- return -1;
- }
-
- /*d_printf(">>>lseek: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- file->srv->cli, path,
- &targetcli, &targetpath)) {
- d_printf("Could not resolve %s\n", path);
- errno = ENOENT;
- TALLOC_FREE(frame);
- return -1;
- }
-
- /*d_printf(">>>lseek: resolved path as %s\n", targetpath);*/
if (!NT_STATUS_IS_OK(cli_qfileinfo_basic(
- targetcli, file->cli_fd, NULL,
+ file->targetcli, file->cli_fd, NULL,
&size, NULL, NULL, NULL, NULL,
NULL))) {
- SMB_OFF_T b_size = size;
- if (!NT_STATUS_IS_OK(cli_getattrE(targetcli, file->cli_fd,
+ off_t b_size = size;
+ if (!NT_STATUS_IS_OK(cli_getattrE(file->targetcli, file->cli_fd,
NULL, &b_size, NULL, NULL, NULL))) {
errno = EINVAL;
TALLOC_FREE(frame);
SMBCFILE *file,
off_t length)
{
- SMB_OFF_T size = length;
- char *server = NULL;
- char *share = NULL;
- char *user = NULL;
- char *password = NULL;
- char *path = NULL;
- char *targetpath = NULL;
- struct cli_state *targetcli = NULL;
+ off_t size = length;
TALLOC_CTX *frame = talloc_stackframe();
if (!context || !context->internal->initialized) {
return -1;
}
- /*d_printf(">>>fstat: parsing %s\n", file->fname);*/
- if (SMBC_parse_path(frame,
- context,
- file->fname,
- NULL,
- &server,
- &share,
- &path,
- &user,
- &password,
- NULL)) {
- errno = EINVAL;
- TALLOC_FREE(frame);
- return -1;
- }
-
- /*d_printf(">>>fstat: resolving %s\n", path);*/
- if (!cli_resolve_path(frame, "", context->internal->auth_info,
- file->srv->cli, path,
- &targetcli, &targetpath)) {
- d_printf("Could not resolve %s\n", path);
- errno = ENOENT;
- TALLOC_FREE(frame);
- return -1;
- }
- /*d_printf(">>>fstat: resolved path as %s\n", targetpath);*/
-
- if (!NT_STATUS_IS_OK(cli_ftruncate(targetcli, file->cli_fd, (uint64_t)size))) {
+ if (!NT_STATUS_IS_OK(cli_ftruncate(file->targetcli, file->cli_fd, (uint64_t)size))) {
errno = EINVAL;
TALLOC_FREE(frame);
return -1;