/* look in server.c for some explanation of these variables */
extern enum protocol_types Protocol;
extern int max_recv;
-unsigned int smb_echo_count = 0;
extern uint32 global_client_caps;
-extern struct current_user current_user;
extern bool global_encrypted_passwords_negotiated;
/****************************************************************************
const char *s = path;
NTSTATUS ret = NT_STATUS_OK;
bool start_of_name_component = True;
+ bool stream_started = false;
*p_last_component_contains_wcard = False;
while (*s) {
- if (IS_PATH_SEP(*s,posix_path)) {
+ if (stream_started) {
+ switch (*s) {
+ case '/':
+ case '\\':
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ case ':':
+ if (s[1] == '\0') {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ if (strchr_m(&s[1], ':')) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ if (StrCaseCmp(s, ":$DATA") != 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ break;
+ }
+ }
+
+ if (!stream_started && *s == ':') {
+ if (*p_last_component_contains_wcard) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ /* stream names allow more characters than file names */
+ stream_started = true;
+ start_of_name_component = false;
+ posix_path = true;
+
+ if (s[1] == '\0') {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ }
+
+ if (!stream_started && IS_PATH_SEP(*s,posix_path)) {
/*
* Safe to assume is not the second part of a mb char
* as this is handled below.
if (!(*s & 0x80)) {
if (!posix_path) {
- if (*s <= 0x1f) {
+ if (*s <= 0x1f || *s == '|') {
return NT_STATUS_OBJECT_NAME_INVALID;
}
switch (*s) {
}
*d = '\0';
+
return ret;
}
****************************************************************************/
size_t srvstr_get_path_wcard(TALLOC_CTX *ctx,
- const char *inbuf,
+ const char *base_ptr,
uint16 smb_flags2,
char **pp_dest,
const char *src,
*pp_dest = NULL;
- if (src_len == 0) {
- ret = srvstr_pull_buf_talloc(ctx,
- inbuf,
- smb_flags2,
- pp_dest,
- src,
- flags);
- } else {
- ret = srvstr_pull_talloc(ctx,
- inbuf,
- smb_flags2,
- pp_dest,
- src,
- src_len,
- flags);
- }
+ ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src,
+ src_len, flags);
if (!*pp_dest) {
*err = NT_STATUS_INVALID_PARAMETER;
****************************************************************************/
size_t srvstr_get_path(TALLOC_CTX *ctx,
- const char *inbuf,
+ const char *base_ptr,
uint16 smb_flags2,
char **pp_dest,
const char *src,
int flags,
NTSTATUS *err)
{
- size_t ret;
-
- *pp_dest = NULL;
-
- if (src_len == 0) {
- ret = srvstr_pull_buf_talloc(ctx,
- inbuf,
- smb_flags2,
- pp_dest,
- src,
- flags);
- } else {
- ret = srvstr_pull_talloc(ctx,
- inbuf,
- smb_flags2,
- pp_dest,
- src,
- src_len,
- flags);
- }
-
- if (!*pp_dest) {
- *err = NT_STATUS_INVALID_PARAMETER;
- return ret;
- }
-
- if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
- /*
- * For a DFS path the function parse_dfs_path()
- * will do the path processing, just make a copy.
- */
- *err = NT_STATUS_OK;
- return ret;
- }
+ bool ignore;
+ return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src,
+ src_len, flags, err, &ignore);
+}
- if (lp_posix_pathnames()) {
- *err = check_path_syntax_posix(*pp_dest);
- } else {
- *err = check_path_syntax(*pp_dest);
- }
+size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req,
+ char **pp_dest, const char *src, int flags,
+ NTSTATUS *err, bool *contains_wcard)
+{
+ return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2,
+ pp_dest, src, smbreq_bufrem(req, src),
+ flags, err, contains_wcard);
+}
- return ret;
+size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
+ char **pp_dest, const char *src, int flags,
+ NTSTATUS *err)
+{
+ bool ignore;
+ return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src,
+ flags, err, &ignore);
}
/****************************************************************************
****************************************************************************/
bool check_fsp_open(connection_struct *conn, struct smb_request *req,
- files_struct *fsp, struct current_user *user)
+ files_struct *fsp)
{
if (!(fsp) || !(conn)) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return False;
}
- if (((conn) != (fsp)->conn) || user->vuid != (fsp)->vuid) {
+ if (((conn) != (fsp)->conn) || req->vuid != (fsp)->vuid) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
return False;
}
}
/****************************************************************************
- Check if we have a correct fsp pointing to a file. Replacement for the
- CHECK_FSP macro.
+ Check if we have a correct fsp pointing to a file.
****************************************************************************/
bool check_fsp(connection_struct *conn, struct smb_request *req,
- files_struct *fsp, struct current_user *user)
+ files_struct *fsp)
{
- if (!check_fsp_open(conn, req, fsp, user)) {
+ if (!check_fsp_open(conn, req, fsp)) {
return False;
}
if ((fsp)->is_directory) {
return True;
}
+/****************************************************************************
+ Check if we have a correct fsp pointing to a quota fake file. Replacement for
+ the CHECK_NTQUOTA_HANDLE_OK macro.
+****************************************************************************/
+
+bool check_fsp_ntquota_handle(connection_struct *conn, struct smb_request *req,
+ files_struct *fsp)
+{
+ if (!check_fsp_open(conn, req, fsp)) {
+ return false;
+ }
+
+ if (fsp->is_directory) {
+ return false;
+ }
+
+ if (fsp->fake_file_handle == NULL) {
+ return false;
+ }
+
+ if (fsp->fake_file_handle->type != FAKE_FILE_TYPE_QUOTA) {
+ return false;
+ }
+
+ if (fsp->fake_file_handle->private_data == NULL) {
+ return false;
+ }
+
+ return true;
+}
+
/****************************************************************************
Check if we have a correct fsp. Replacement for the FSP_BELONGS_CONN macro
****************************************************************************/
bool fsp_belongs_conn(connection_struct *conn, struct smb_request *req,
- files_struct *fsp, struct current_user *user)
+ files_struct *fsp)
{
if ((fsp) && (conn) && ((conn)==(fsp)->conn)
- && (current_user.vuid==(fsp)->vuid)) {
+ && (req->vuid == (fsp)->vuid)) {
return True;
}
* header.
*/
char outbuf[smb_size];
-
+
static bool already_got_session = False;
*name1 = *name2 = 0;
-
+
memset(outbuf, '\0', sizeof(outbuf));
smb_setlen(outbuf,0);
-
+
switch (msg_type) {
case 0x81: /* session request */
-
+
if (already_got_session) {
exit_server_cleanly("multiple session request not permitted");
}
-
+
SCVAL(outbuf,0,0x82);
SCVAL(outbuf,3,0);
if (name_len(inbuf+4) > 50 ||
already_got_session = True;
break;
-
+
case 0x89: /* session keepalive request
(some old clients produce this?) */
SCVAL(outbuf,0,SMBkeepalive);
SCVAL(outbuf,3,0);
break;
-
+
case 0x82: /* positive session response */
case 0x83: /* negative session response */
case 0x84: /* retarget session response */
DEBUG(0,("Unexpected session response\n"));
break;
-
+
case SMBkeepalive: /* session keepalive */
default:
return;
}
-
+
DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
msg_type, msg_flags));
char *dev = NULL;
int pwlen=0;
NTSTATUS nt_status;
- char *p;
+ const char *p;
DATA_BLOB password_blob;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBtcon);
- if (smb_buflen(req->inbuf) < 4) {
+ if (req->buflen < 4) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBtcon);
return;
}
- p = smb_buf(req->inbuf)+1;
- p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
- &service_buf, p, STR_TERMINATE) + 1;
- pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
- &password, p, STR_TERMINATE) + 1;
- p += pwlen;
- p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2,
- &dev, p, STR_TERMINATE) + 1;
+ p = (const char *)req->buf + 1;
+ p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE);
+ p += 1;
+ pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE);
+ p += pwlen+1;
+ p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE);
+ p += 1;
if (service_buf == NULL || password == NULL || dev == NULL) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
void reply_tcon_and_X(struct smb_request *req)
{
connection_struct *conn = req->conn;
- char *service = NULL;
+ const char *service = NULL;
DATA_BLOB password;
TALLOC_CTX *ctx = talloc_tos();
/* what the cleint thinks the device is */
NTSTATUS nt_status;
int passlen;
char *path = NULL;
- char *p, *q;
+ const char *p, *q;
uint16 tcon_flags;
START_PROFILE(SMBtconX);
return;
}
- passlen = SVAL(req->inbuf,smb_vwv3);
- tcon_flags = SVAL(req->inbuf,smb_vwv2);
+ passlen = SVAL(req->vwv+3, 0);
+ tcon_flags = SVAL(req->vwv+2, 0);
/* we might have to close an old one */
if ((tcon_flags & 0x1) && conn) {
conn = NULL;
}
- if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) {
+ if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) {
reply_doserror(req, ERRDOS, ERRbuftoosmall);
END_PROFILE(SMBtconX);
return;
}
if (global_encrypted_passwords_negotiated) {
- password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
- passlen);
+ password = data_blob_talloc(talloc_tos(), req->buf, passlen);
if (lp_security() == SEC_SHARE) {
/*
* Security = share always has a pad byte
* after the password.
*/
- p = smb_buf(req->inbuf) + passlen + 1;
+ p = (const char *)req->buf + passlen + 1;
} else {
- p = smb_buf(req->inbuf) + passlen;
+ p = (const char *)req->buf + passlen;
}
} else {
- password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf),
- passlen+1);
+ password = data_blob_talloc(talloc_tos(), req->buf, passlen+1);
/* Ensure correct termination */
password.data[passlen]=0;
- p = smb_buf(req->inbuf) + passlen + 1;
+ p = (const char *)req->buf + passlen + 1;
}
- p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p,
- STR_TERMINATE);
+ p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE);
if (path == NULL) {
data_blob_clear_free(&password);
p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2,
&client_devicetype, p,
- MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII);
+ MIN(6, smbreq_bufrem(req, p)), STR_ASCII);
if (client_devicetype == NULL) {
data_blob_clear_free(&password);
SSVAL(req->outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
(lp_csc_policy(SNUM(conn)) << 2));
- init_dfsroot(conn, req->inbuf, req->outbuf);
+ if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) {
+ DEBUG(2,("Serving %s as a Dfs root\n",
+ lp_servicename(SNUM(conn)) ));
+ SSVAL(req->outbuf, smb_vwv2,
+ SMB_SHARE_IN_DFS | SVAL(req->outbuf, smb_vwv2));
+ }
}
return;
}
- device = SVAL(req->inbuf,smb_vwv1);
- function = SVAL(req->inbuf,smb_vwv2);
+ device = SVAL(req->vwv+1, 0);
+ function = SVAL(req->vwv+2, 0);
ioctl_code = (device << 16) + function;
DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
switch (ioctl_code) {
case IOCTL_QUERY_JOB_INFO:
{
- files_struct *fsp = file_fsp(SVAL(req->inbuf,
- smb_vwv0));
+ files_struct *fsp = file_fsp(
+ req, SVAL(req->vwv+0, 0));
if (!fsp) {
reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBioctl);
Strange checkpath NTSTATUS mapping.
****************************************************************************/
-static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status)
+static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status)
{
/* Strange DOS error code semantics only for checkpath... */
- if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) {
+ if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) {
if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) {
/* We need to map to ERRbadpath */
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
START_PROFILE(SMBcheckpath);
- srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name,
- smb_buf(req->inbuf) + 1, 0,
- STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1,
+ STR_TERMINATE, &status);
+
if (!NT_STATUS_IS_OK(status)) {
- status = map_checkpath_error((char *)req->inbuf, status);
+ status = map_checkpath_error(req->flags2, status);
reply_nterror(req, status);
END_PROFILE(SMBcheckpath);
return;
goto path_err;
}
- DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0)));
+ DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0)));
status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
one at a time - if a component fails it expects
ERRbadpath, not ERRbadfile.
*/
- status = map_checkpath_error((char *)req->inbuf, status);
+ status = map_checkpath_error(req->flags2, status);
if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
/*
* Windows returns different error codes if
int mode=0;
SMB_OFF_T size=0;
time_t mtime=0;
- char *p;
+ const char *p;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBgetatr);
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
- 0, STR_TERMINATE, &status);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBgetatr);
SSVAL(req->outbuf, smb_flg2,
SVAL(req->outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
}
-
+
DEBUG(3,("reply_getatr: name=%s mode=%d size=%u\n", fname, mode, (unsigned int)size ) );
END_PROFILE(SMBgetatr);
void reply_setatr(struct smb_request *req)
{
+ struct timespec ts[2];
connection_struct *conn = req->conn;
char *fname = NULL;
int mode;
time_t mtime;
SMB_STRUCT_STAT sbuf;
- char *p;
+ const char *p;
NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBsetatr);
+ ZERO_STRUCT(ts);
+
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
}
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p,
- 0, STR_TERMINATE, &status);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBsetatr);
return;
}
- mode = SVAL(req->inbuf,smb_vwv0);
- mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
+ mode = SVAL(req->vwv+0, 0);
+ mtime = srv_make_unix_date3(req->vwv+1);
+
+ ts[1] = convert_time_t_to_timespec(mtime);
+ status = smb_set_file_time(conn, NULL, fname,
+ &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ END_PROFILE(SMBsetatr);
+ return;
+ }
if (mode != FILE_ATTRIBUTE_NORMAL) {
if (VALID_STAT_OF_DIR(sbuf))
}
}
- if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
- reply_unixerror(req, ERRDOS, ERRnoaccess);
- END_PROFILE(SMBsetatr);
- return;
- }
-
reply_outbuf(req, 0, 0);
-
+
DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
-
+
END_PROFILE(SMBsetatr);
return;
}
void reply_dskattr(struct smb_request *req)
{
connection_struct *conn = req->conn;
- SMB_BIG_UINT dfree,dsize,bsize;
+ uint64_t dfree,dsize,bsize;
START_PROFILE(SMBdskattr);
- if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
+ if (get_dfree_info(conn,".",True,&bsize,&dfree,&dsize) == (uint64_t)-1) {
reply_unixerror(req, ERRHRD, ERRgeneral);
END_PROFILE(SMBdskattr);
return;
}
reply_outbuf(req, 5, 0);
-
+
if (Protocol <= PROTOCOL_LANMAN2) {
double total_space, free_space;
/* we need to scale this to a number that DOS6 can handle. We
total_space = dsize * (double)bsize;
free_space = dfree * (double)bsize;
- dsize = (SMB_BIG_UINT)((total_space+63*512) / (64*512));
- dfree = (SMB_BIG_UINT)((free_space+63*512) / (64*512));
-
+ dsize = (uint64_t)((total_space+63*512) / (64*512));
+ dfree = (uint64_t)((free_space+63*512) / (64*512));
+
if (dsize > 0xFFFF) dsize = 0xFFFF;
if (dfree > 0xFFFF) dfree = 0xFFFF;
void reply_search(struct smb_request *req)
{
connection_struct *conn = req->conn;
- char *mask = NULL;
+ const char *mask = NULL;
char *directory = NULL;
char *fname = NULL;
SMB_OFF_T size;
unsigned int numentries = 0;
unsigned int maxentries = 0;
bool finished = False;
- char *p;
+ const char *p;
int status_len;
char *path = NULL;
char status[21];
bool mask_contains_wcard = False;
bool allow_long_path_components = (req->flags2 & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
TALLOC_CTX *ctx = talloc_tos();
+ bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
START_PROFILE(SMBsearch);
}
if (lp_posix_pathnames()) {
- reply_unknown_new(req, CVAL(req->inbuf, smb_com));
+ reply_unknown_new(req, req->cmd);
END_PROFILE(SMBsearch);
return;
}
/* If we were called as SMBffirst then we must expect close. */
- if(CVAL(req->inbuf,smb_com) == SMBffirst) {
+ if(req->cmd == SMBffirst) {
expect_close = True;
}
reply_outbuf(req, 1, 3);
- maxentries = SVAL(req->inbuf,smb_vwv0);
- dirtype = SVAL(req->inbuf,smb_vwv1);
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path_wcard(ctx,
- (char *)req->inbuf,
- req->flags2,
- &path,
- p,
- 0,
- STR_TERMINATE,
- &nt_status,
- &mask_contains_wcard);
+ maxentries = SVAL(req->vwv+0, 0);
+ dirtype = SVAL(req->vwv+1, 0);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
+ &nt_status, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(nt_status)) {
reply_nterror(req, nt_status);
END_PROFILE(SMBsearch);
}
p = strrchr_m(directory,'/');
- if (!p) {
+ if ((p != NULL) && (*directory != '/')) {
+ mask = p + 1;
+ directory = talloc_strndup(ctx, directory,
+ PTR_DIFF(p, directory));
+ } else {
mask = directory;
directory = talloc_strdup(ctx,".");
- if (!directory) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBsearch);
- return;
- }
- } else {
- *p = 0;
- mask = p+1;
}
- if (*directory == '\0') {
- directory = talloc_strdup(ctx,".");
- if (!directory) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBsearch);
- return;
- }
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBsearch);
+ return;
}
+
memset((char *)status,'\0',21);
SCVAL(status,0,(dirtype & 0x1F));
}
for (i=numentries;(i<maxentries) && !finished;i++) {
- finished = !get_dir_entry(ctx,conn,mask,dirtype,&fname,
- &size,&mode,&date,check_descend);
+ finished = !get_dir_entry(ctx,
+ conn,
+ mask,
+ dirtype,
+ &fname,
+ &size,
+ &mode,
+ &date,
+ check_descend,
+ ask_sharemode);
if (!finished) {
char buf[DIR_STRUCT_SIZE];
memcpy(buf,status,21);
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
- if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) {
+ if(dptr_num >= 0 && req->cmd == SMBfunique) {
dptr_close(&dptr_num);
}
}
DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n",
- smb_fn_name(CVAL(req->inbuf,smb_com)),
+ smb_fn_name(req->cmd),
mask,
directory ? directory : "./",
dirtype,
int status_len;
char status[21];
int dptr_num= -2;
- char *p;
+ const char *p;
char *path = NULL;
NTSTATUS err;
bool path_contains_wcard = False;
START_PROFILE(SMBfclose);
if (lp_posix_pathnames()) {
- reply_unknown_new(req, CVAL(req->inbuf, smb_com));
+ reply_unknown_new(req, req->cmd);
END_PROFILE(SMBfclose);
return;
}
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path_wcard(ctx,
- (char *)req->inbuf,
- req->flags2,
- &path,
- p,
- 0,
- STR_TERMINATE,
- &err,
- &path_contains_wcard);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE,
+ &err, &path_contains_wcard);
if (!NT_STATUS_IS_OK(err)) {
reply_nterror(req, err);
END_PROFILE(SMBfclose);
}
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- deny_mode = SVAL(req->inbuf,smb_vwv0);
- dos_attr = SVAL(req->inbuf,smb_vwv1);
+ deny_mode = SVAL(req->vwv+0, 0);
+ dos_attr = SVAL(req->vwv+1, 0);
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf)+1, 0,
- STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBopen);
return;
}
- status = create_file(conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- fname, /* fname */
- access_mask, /* access_mask */
- share_mode, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- dos_attr, /* file_attributes */
- oplock_request, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &fsp, /* result */
- &info, /* pinfo */
- &sbuf); /* psbuf */
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ true, /* is_dos_path */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ dos_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &info, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
}
size = sbuf.st_size;
- fattr = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
mtime = sbuf.st_mtime;
if (fattr & aDIR) {
- DEBUG(3,("attempt to open a directory %s\n",fname));
- close_file(fsp,ERROR_CLOSE);
+ DEBUG(3,("attempt to open a directory %s\n",fsp->fsp_name));
+ close_file(req, fsp, ERROR_CLOSE);
reply_doserror(req, ERRDOS,ERRnoaccess);
END_PROFILE(SMBopen);
return;
SCVAL(req->outbuf,smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
-
+
if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(req->outbuf,smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
int core_oplock_request;
int oplock_request;
#if 0
- int smb_sattr = SVAL(req->inbuf,smb_vwv4);
- uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6);
+ int smb_sattr = SVAL(req->vwv+4, 0);
+ uint32 smb_time = make_unix_date3(req->vwv+6);
#endif
int smb_ofun;
uint32 fattr=0;
int smb_action = 0;
files_struct *fsp;
NTSTATUS status;
- SMB_BIG_UINT allocation_size;
+ uint64_t allocation_size;
ssize_t retval = -1;
uint32 access_mask;
uint32 share_mode;
return;
}
- open_flags = SVAL(req->inbuf,smb_vwv2);
- deny_mode = SVAL(req->inbuf,smb_vwv3);
- smb_attr = SVAL(req->inbuf,smb_vwv5);
+ open_flags = SVAL(req->vwv+2, 0);
+ deny_mode = SVAL(req->vwv+3, 0);
+ smb_attr = SVAL(req->vwv+5, 0);
ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf);
core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
oplock_request = ex_oplock_request | core_oplock_request;
- smb_ofun = SVAL(req->inbuf,smb_vwv8);
- allocation_size = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv9);
+ smb_ofun = SVAL(req->vwv+8, 0);
+ allocation_size = (uint64_t)IVAL(req->vwv+9, 0);
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(conn)) {
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf), 0, STR_TERMINATE,
- &status);
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBopenX);
return;
}
- status = create_file(conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- fname, /* fname */
- access_mask, /* access_mask */
- share_mode, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- smb_attr, /* file_attributes */
- oplock_request, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &fsp, /* result */
- &smb_action, /* pinfo */
- &sbuf); /* psbuf */
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ true, /* is_dos_path */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ smb_attr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ &smb_action, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) {
fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
- close_file(fsp,ERROR_CLOSE);
+ close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
END_PROFILE(SMBopenX);
return;
}
retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
if (retval < 0) {
- close_file(fsp,ERROR_CLOSE);
+ close_file(req, fsp, ERROR_CLOSE);
reply_nterror(req, NT_STATUS_DISK_FULL);
END_PROFILE(SMBopenX);
return;
sbuf.st_size = get_allocation_size(conn,fsp,&sbuf);
}
- fattr = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
mtime = sbuf.st_mtime;
if (fattr & aDIR) {
- close_file(fsp,ERROR_CLOSE);
+ close_file(req, fsp, ERROR_CLOSE);
reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBopenX);
return;
{
connection_struct *conn = req->conn;
char *fname = NULL;
- int com;
uint32 fattr = 0;
struct timespec ts[2];
files_struct *fsp;
return;
}
- fattr = SVAL(req->inbuf,smb_vwv0);
+ fattr = SVAL(req->vwv+0, 0);
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- com = SVAL(req->inbuf,smb_com);
- ts[1] =convert_time_t_to_timespec(
- srv_make_unix_date3(req->inbuf + smb_vwv1));
+ ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
/* mtime. */
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf) + 1, 0,
- STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcreate);
"please report this\n", fname));
}
- if(com == SMBmknew) {
+ if(req->cmd == SMBmknew) {
/* We should fail if file exists. */
create_disposition = FILE_CREATE;
} else {
create_disposition = FILE_OVERWRITE_IF;
}
- status = create_file(conn, /* conn */
- req, /* req */
- 0, /* root_dir_fid */
- fname, /* fname */
- access_mask, /* access_mask */
- share_mode, /* share_access */
- create_disposition, /* create_disposition*/
- create_options, /* create_options */
- fattr, /* file_attributes */
- oplock_request, /* oplock_request */
- 0, /* allocation_size */
- NULL, /* sd */
- NULL, /* ea_list */
- &fsp, /* result */
- NULL, /* pinfo */
- &sbuf); /* psbuf */
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ true, /* is_dos_path */
+ access_mask, /* access_mask */
+ share_mode, /* share_access */
+ create_disposition, /* create_disposition*/
+ create_options, /* create_options */
+ fattr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
}
ts[0] = get_atimespec(&sbuf); /* atime. */
- file_ntimes(conn, fname, ts);
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name, &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ reply_openerror(req, status);
+ return;
+ }
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
+ DEBUG( 2, ( "reply_mknew: file %s\n", fsp->fsp_name ) );
DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n",
- fname, fsp->fh->fd, (unsigned int)fattr ) );
+ fsp->fsp_name, fsp->fh->fd, (unsigned int)fattr ) );
END_PROFILE(SMBcreate);
return;
return;
}
- fattr = SVAL(req->inbuf,smb_vwv0);
+ fattr = SVAL(req->vwv+0, 0);
oplock_request = CORE_OPLOCK_REQUEST(req->inbuf);
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname,
- smb_buf(req->inbuf)+1, 0, STR_TERMINATE,
- &status);
+ srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBctemp);
return;
}
- status = check_name(conn, CONST_DISCARD(char *,fname));
+ status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBctemp);
SMB_VFS_STAT(conn,fname,&sbuf);
/* We should fail if file does not exist. */
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- FILE_GENERIC_READ | FILE_GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0,
- fattr,
- oplock_request,
- NULL, &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ false, /* is_dos_path */
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ fattr, /* file_attributes */
+ oplock_request, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
/* close fd from smb_mkstemp() */
close(tmpfd);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
/* the returned filename is relative to the directory */
- s = strrchr_m(fname, '/');
+ s = strrchr_m(fsp->fsp_name, '/');
if (!s) {
- s = fname;
+ s = fsp->fsp_name;
} else {
s++;
}
SCVAL(req->outbuf, smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
-
+
if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(req->outbuf, smb_flg,
CVAL(req->outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
}
- DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fname ) );
- DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fname, fsp->fh->fd,
- (unsigned int)sbuf.st_mode ) );
+ DEBUG( 2, ( "reply_ctemp: created temp file %s\n", fsp->fsp_name ) );
+ DEBUG( 3, ( "reply_ctemp %s fd=%d umode=0%o\n", fsp->fsp_name,
+ fsp->fh->fd, (unsigned int)sbuf.st_mode ) );
END_PROFILE(SMBctemp);
return;
return NT_STATUS_OK;
}
- if (fsp->access_mask & DELETE_ACCESS) {
+ if (fsp->access_mask & (DELETE_ACCESS|FILE_WRITE_ATTRIBUTES)) {
return NT_STATUS_OK;
}
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
- status = open_file_ntcreate(conn, req, fname, &sbuf,
- DELETE_ACCESS,
- FILE_SHARE_NONE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- req != NULL ? 0 : INTERNAL_OPEN_ONLY,
- NULL, &fsp);
+ status = SMB_VFS_CREATE_FILE
+ (conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ false, /* is_dos_path */
+ DELETE_ACCESS, /* access_mask */
+ FILE_SHARE_NONE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ FILE_NON_DIRECTORY_FILE, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("open_file_ntcreate failed: %s\n",
+ DEBUG(10, ("SMB_VFS_CREATEFILE failed: %s\n",
nt_errstr(status)));
return status;
}
/* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, True, ¤t_user.ut)) {
- close_file(fsp, NORMAL_CLOSE);
+ if (!set_delete_on_close(fsp, True, &conn->server_info->utok)) {
+ close_file(req, fsp, NORMAL_CLOSE);
return NT_STATUS_ACCESS_DENIED;
}
- return close_file(fsp,NORMAL_CLOSE);
+ return close_file(req, fsp, NORMAL_CLOSE);
}
/****************************************************************************
}
count++;
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
+ DEBUG(3,("unlink_internals: successful unlink [%s]\n",
fname));
TALLOC_FREE(fname);
TALLOC_FREE(dir_hnd);
}
- if (count == 0 && NT_STATUS_IS_OK(status)) {
+ if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
status = map_nt_error_from_unix(errno);
}
return;
}
- dirtype = SVAL(req->inbuf,smb_vwv0);
+ dirtype = SVAL(req->vwv+0, 0);
- srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name,
- smb_buf(req->inbuf) + 1, 0,
- STR_TERMINATE, &status, &path_contains_wcard);
+ srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1,
+ STR_TERMINATE, &status,
+ &path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBunlink);
* reply_readbraw has already checked the length.
*/
- if ( (chain_size == 0) && (nread > 0) &&
+ if ( (chain_size == 0) && (nread > 0) && (fsp->base_fsp == NULL) &&
(fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
char header[4];
DATA_BLOB header_blob;
* return a zero length response here.
*/
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
/*
* We have to do a check_fsp by hand here, as
*/
if (!fsp || !conn || conn != fsp->conn ||
- current_user.vuid != fsp->vuid ||
+ req->vuid != fsp->vuid ||
fsp->is_directory || fsp->fh->fd == -1) {
/*
* fsp could be NULL here so use the value from the packet. JRA.
*/
DEBUG(3,("reply_readbraw: fnum %d not valid "
"- cache prime?\n",
- (int)SVAL(req->inbuf,smb_vwv0)));
+ (int)SVAL(req->vwv+0, 0)));
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
return;
((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) &&
(fsp->access_mask & FILE_EXECUTE)))) {
DEBUG(3,("reply_readbraw: fnum %d not readable.\n",
- (int)SVAL(req->inbuf,smb_vwv0)));
+ (int)SVAL(req->vwv+0, 0)));
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
return;
flush_write_cache(fsp, READRAW_FLUSH);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0);
if(req->wct == 10) {
/*
* This is a large offset (64 bit) read.
*/
#ifdef LARGE_SMB_OFF_T
- startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32);
+ startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32);
#else /* !LARGE_SMB_OFF_T */
* Ensure we haven't been sent a >32 bit offset.
*/
- if(IVAL(req->inbuf,smb_vwv8) != 0) {
+ if(IVAL(req->vwv+8, 0) != 0) {
DEBUG(0,("reply_readbraw: large offset "
"(%x << 32) used and we don't support "
"64 bit offsets.\n",
- (unsigned int)IVAL(req->inbuf,smb_vwv8) ));
+ (unsigned int)IVAL(req->vwv+8, 0) ));
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
return;
}
}
- maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF);
- mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF);
+ maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF);
+ mincount = (SVAL(req->vwv+4, 0) & 0xFFFF);
/* ensure we don't overrun the packet size */
maxcount = MIN(65535,maxcount);
if (is_locked(fsp,(uint32)req->smbpid,
- (SMB_BIG_UINT)maxcount,
- (SMB_BIG_UINT)startpos,
+ (uint64_t)maxcount,
+ (uint64_t)startpos,
READ_LOCK)) {
reply_readbraw_error();
END_PROFILE(SMBreadbraw);
if (nread < mincount)
nread = 0;
#endif
-
+
DEBUG( 3, ( "reply_readbraw: fnum=%d start=%.0f max=%lu "
"min=%lu nread=%lu\n",
fsp->fnum, (double)startpos,
(unsigned long)maxcount,
(unsigned long)mincount,
(unsigned long)nread ) );
-
+
send_file_readbraw(conn, fsp, startpos, nread, mincount);
DEBUG(5,("reply_readbraw finished\n"));
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBlockread);
return;
}
- if (!CHECK_READ(fsp,req->inbuf)) {
+ if (!CHECK_READ(fsp,req)) {
reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBlockread);
return;
release_level_2_oplocks_on_change(fsp);
- numtoread = SVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+ numtoread = SVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread);
reply_outbuf(req, 5, numtoread + 3);
data = smb_buf(req->outbuf) + 3;
-
+
/*
* NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
* protocol request that predates the read/write lock concept.
* for a write lock. JRA.
* Note that the requested lock size is unaffected by max_recv.
*/
-
+
br_lck = do_lock(smbd_messaging_context(),
fsp,
req->smbpid,
- (SMB_BIG_UINT)numtoread,
- (SMB_BIG_UINT)startpos,
+ (uint64_t)numtoread,
+ (uint64_t)startpos,
WRITE_LOCK,
WINDOWS_LOCK,
False, /* Non-blocking lock. */
END_PROFILE(SMBlockread);
return;
}
-
+
srv_set_message((char *)req->outbuf, 5, nread+3, False);
SSVAL(req->outbuf,smb_vwv0,nread);
p = smb_buf(req->outbuf);
SCVAL(p,0,0); /* pad byte. */
SSVAL(p,1,nread);
-
+
DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
fsp->fnum, (int)numtoread, (int)nread));
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBread);
return;
}
- if (!CHECK_READ(fsp,req->inbuf)) {
+ if (!CHECK_READ(fsp,req)) {
reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBread);
return;
}
- numtoread = SVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
+ numtoread = SVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
reply_outbuf(req, 5, numtoread+3);
data = smb_buf(req->outbuf) + 3;
-
- if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtoread,
- (SMB_BIG_UINT)startpos, READ_LOCK)) {
+
+ if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtoread,
+ (uint64_t)startpos, READ_LOCK)) {
reply_doserror(req, ERRDOS,ERRlock);
END_PROFILE(SMBread);
return;
SSVAL(req->outbuf,smb_vwv5,nread+3);
SCVAL(smb_buf(req->outbuf),0,1);
SSVAL(smb_buf(req->outbuf),1,nread);
-
+
DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
fsp->fnum, (int)numtoread, (int)nread ) );
* on a train in Germany :-). JRA.
*/
- if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) &&
- !is_encrypted_packet(req->inbuf) &&
+ if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) &&
+ !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
header = data_blob_const(headerbuf, sizeof(headerbuf));
- construct_reply_common((char *)req->inbuf, (char *)headerbuf);
+ construct_reply_common_req(req, (char *)headerbuf);
setup_readX_header((char *)headerbuf, smb_maxcnt);
if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) {
- /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
- if (errno == ENOSYS) {
+ /* Returning ENOSYS or EINVAL means no data at all was sent.
+ Do this as a normal read. */
+ if (errno == ENOSYS || errno == EINVAL) {
goto normal_read;
}
if ((smb_maxcnt & 0xFF0000) > 0x10000) {
uint8 headerbuf[smb_size + 2*12];
- construct_reply_common((char *)req->inbuf, (char *)headerbuf);
+ construct_reply_common_req(req, (char *)headerbuf);
setup_readX_header((char *)headerbuf, smb_maxcnt);
/* Send out the header. */
}
TALLOC_FREE(req->outbuf);
return;
- } else {
- reply_outbuf(req, 12, smb_maxcnt);
+ }
- nread = read_file(fsp, smb_buf(req->outbuf), startpos,
- smb_maxcnt);
- if (nread < 0) {
- reply_unixerror(req, ERRDOS, ERRnoaccess);
- return;
- }
+ reply_outbuf(req, 12, smb_maxcnt);
- setup_readX_header((char *)req->outbuf, nread);
+ nread = read_file(fsp, smb_buf(req->outbuf), startpos, smb_maxcnt);
+ if (nread < 0) {
+ reply_unixerror(req, ERRDOS, ERRnoaccess);
+ return;
+ }
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ setup_readX_header((char *)req->outbuf, nread);
- chain_reply(req);
+ DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
- return;
- }
+ chain_reply(req);
}
/****************************************************************************
size_t smb_maxcnt;
bool big_readX = False;
#if 0
- size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6);
+ size_t smb_mincnt = SVAL(req->vwv+6, 0);
#endif
START_PROFILE(SMBreadX);
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
- smb_maxcnt = SVAL(req->inbuf,smb_vwv5);
+ fsp = file_fsp(req, SVAL(req->vwv+2, 0));
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
+ smb_maxcnt = SVAL(req->vwv+5, 0);
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(conn)) {
return;
}
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBreadX);
return;
}
- if (!CHECK_READ(fsp,req->inbuf)) {
+ if (!CHECK_READ(fsp,req)) {
reply_doserror(req, ERRDOS,ERRbadaccess);
END_PROFILE(SMBreadX);
return;
}
if (global_client_caps & CAP_LARGE_READX) {
- size_t upper_size = SVAL(req->inbuf,smb_vwv7);
+ size_t upper_size = SVAL(req->vwv+7, 0);
smb_maxcnt |= (upper_size<<16);
if (upper_size > 1) {
/* Can't do this on a chained packet. */
- if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) {
+ if ((CVAL(req->vwv+0, 0) != 0xFF)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
/*
* This is a large offset (64 bit) read.
*/
- startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32);
+ startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32);
#else /* !LARGE_SMB_OFF_T */
* Ensure we haven't been sent a >32 bit offset.
*/
- if(IVAL(req->inbuf,smb_vwv10) != 0) {
+ if(IVAL(req->vwv+10, 0) != 0) {
DEBUG(0,("reply_read_and_X - large offset (%x << 32) "
"used and we don't support 64 bit offsets.\n",
- (unsigned int)IVAL(req->inbuf,smb_vwv10) ));
+ (unsigned int)IVAL(req->vwv+10, 0) ));
END_PROFILE(SMBreadX);
reply_doserror(req, ERRDOS, ERRbadaccess);
return;
}
- if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)smb_maxcnt,
- (SMB_BIG_UINT)startpos, READ_LOCK)) {
+ if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)smb_maxcnt,
+ (uint64_t)startpos, READ_LOCK)) {
END_PROFILE(SMBreadX);
reply_doserror(req, ERRDOS, ERRlock);
return;
}
- /* It is possible for VFS modules to selectively decide whether Async I/O should be used
- for the file or not.
- */
- if ((SMB_VFS_AIO_FORCE(fsp)) &&
- !big_readX &&
+ if (!big_readX &&
schedule_aio_read_and_X(conn, req, fsp, startpos, smb_maxcnt)) {
END_PROFILE(SMBreadX);
return;
void reply_writebraw(struct smb_request *req)
{
connection_struct *conn = req->conn;
- int outsize = 0;
char *buf = NULL;
ssize_t nwritten=0;
ssize_t total_written=0;
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
+ if (!check_fsp(conn, req, fsp)) {
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
return;
return;
}
- tcount = IVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
- write_through = BITSETW(req->inbuf+smb_vwv7,0);
+ tcount = IVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
+ write_through = BITSETW(req->vwv+7,0);
/* We have to deal with slightly different formats depending
on whether we are using the core+ or lanman1.0 protocol */
numtowrite = SVAL(smb_buf(req->inbuf),-2);
data = smb_buf(req->inbuf);
} else {
- numtowrite = SVAL(req->inbuf,smb_vwv10);
- data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11);
+ numtowrite = SVAL(req->vwv+10, 0);
+ data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0);
}
/* Ensure we don't write bytes past the end of this packet. */
return;
}
- if (is_locked(fsp,(uint32)req->smbpid,(SMB_BIG_UINT)tcount,
- (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ if (is_locked(fsp,(uint32)req->smbpid,(uint64_t)tcount,
+ (uint64_t)startpos, WRITE_LOCK)) {
reply_doserror(req, ERRDOS, ERRlock);
error_to_writebrawerr(req);
END_PROFILE(SMBwritebraw);
* it to send more bytes */
memcpy(buf, req->inbuf, smb_size);
- outsize = srv_set_message(buf,
- Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+ srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
SCVAL(buf,smb_com,SMBwritebraw);
SSVALS(buf,smb_vwv0,0xFFFF);
show_msg(buf);
}
/* Now read the raw data into the buffer and write it */
- if (read_smb_length(smbd_server_fd(),buf,
- SMB_SECONDARY_WAIT, get_srv_read_error()) == -1) {
+ status = read_smb_length(smbd_server_fd(), buf, SMB_SECONDARY_WAIT,
+ &numtowrite);
+ if (!NT_STATUS_IS_OK(status)) {
exit_server_cleanly("secondary writebraw failed");
}
- /*
- * Even though this is not an smb message,
- * smb_len returns the generic length of a packet.
- */
-
- numtowrite = smb_len(buf);
-
/* Set up outbuf to return the correct size */
reply_outbuf(req, 1, 0);
(int)tcount,(int)nwritten,(int)numtowrite));
}
- if (read_data(smbd_server_fd(), buf+4, numtowrite,get_srv_read_error())
- != numtowrite ) {
+ status = read_data(smbd_server_fd(), buf+4, numtowrite);
+
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("reply_writebraw: Oversize secondary write "
- "raw read failed (%s). Terminating\n",
- strerror(errno) ));
+ "raw read failed (%s). Terminating\n",
+ nt_errstr(status)));
exit_server_cleanly("secondary writebraw failed");
}
ssize_t nwritten = -1;
size_t numtowrite;
SMB_OFF_T startpos;
- char *data;
+ const char *data;
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp;
END_PROFILE(SMBwriteunlock);
return;
}
-
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
+
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBwriteunlock);
return;
}
return;
}
- numtowrite = SVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
- data = smb_buf(req->inbuf) + 3;
-
+ numtowrite = SVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
+ data = (const char *)req->buf + 3;
+
if (numtowrite
- && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
+ (uint64_t)startpos, WRITE_LOCK)) {
reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwriteunlock);
return;
} else {
nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
-
+
status = sync_file(conn, fsp, False /* write through */);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_writeunlock: sync_file for %s returned %s\n",
status = do_unlock(smbd_messaging_context(),
fsp,
req->smbpid,
- (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos,
+ (uint64_t)numtowrite,
+ (uint64_t)startpos,
WINDOWS_LOCK);
if (NT_STATUS_V(status)) {
}
reply_outbuf(req, 1, 0);
-
+
SSVAL(req->outbuf,smb_vwv0,nwritten);
-
+
DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
fsp->fnum, (int)numtowrite, (int)nwritten));
-
+
END_PROFILE(SMBwriteunlock);
return;
}
size_t numtowrite;
ssize_t nwritten = -1;
SMB_OFF_T startpos;
- char *data;
+ const char *data;
files_struct *fsp;
NTSTATUS status;
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBwrite);
return;
}
return;
}
- numtowrite = SVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
- data = smb_buf(req->inbuf) + 3;
-
- if (is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ numtowrite = SVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
+ data = (const char *)req->buf + 3;
+
+ if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
+ (uint64_t)startpos, WRITE_LOCK)) {
reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwrite);
return;
END_PROFILE(SMBwrite);
return;
}
- } else
+ trigger_write_time_update_immediate(fsp);
+ } else {
nwritten = write_file(req,fsp,data,startpos,numtowrite);
-
+ }
+
status = sync_file(conn, fsp, False);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_write: sync_file for %s returned %s\n",
}
reply_outbuf(req, 1, 0);
-
+
SSVAL(req->outbuf,smb_vwv0,nwritten);
if (nwritten < (ssize_t)numtowrite) {
SCVAL(req->outbuf,smb_rcls,ERRHRD);
SSVAL(req->outbuf,smb_err,ERRdiskfull);
}
-
+
DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
END_PROFILE(SMBwrite);
return;
}
- numtowrite = SVAL(req->inbuf,smb_vwv10);
- smb_doff = SVAL(req->inbuf,smb_vwv11);
+ numtowrite = SVAL(req->vwv+10, 0);
+ smb_doff = SVAL(req->vwv+11, 0);
smblen = smb_len(req->inbuf);
if (req->unread_bytes > 0xFFFF ||
(smblen > smb_doff &&
smblen - smb_doff > 0xFFFF)) {
- numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16);
+ numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16);
}
if (req->unread_bytes) {
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3);
- write_through = BITSETW(req->inbuf+smb_vwv7,0);
+ fsp = file_fsp(req, SVAL(req->vwv+2, 0));
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0);
+ write_through = BITSETW(req->vwv+7,0);
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBwriteX);
return;
}
/*
* This is a large offset (64 bit) write.
*/
- startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32);
+ startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32);
#else /* !LARGE_SMB_OFF_T */
* Ensure we haven't been sent a >32 bit offset.
*/
- if(IVAL(req->inbuf,smb_vwv12) != 0) {
+ if(IVAL(req->vwv+12, 0) != 0) {
DEBUG(0,("reply_write_and_X - large offset (%x << 32) "
"used and we don't support 64 bit offsets.\n",
- (unsigned int)IVAL(req->inbuf,smb_vwv12) ));
+ (unsigned int)IVAL(req->vwv+12, 0) ));
reply_doserror(req, ERRDOS, ERRbadaccess);
END_PROFILE(SMBwriteX);
return;
}
if (is_locked(fsp,(uint32)req->smbpid,
- (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ (uint64_t)numtowrite,
+ (uint64_t)startpos, WRITE_LOCK)) {
reply_doserror(req, ERRDOS, ERRlock);
END_PROFILE(SMBwriteX);
return;
nwritten = 0;
} else {
- /* It is possible for VFS modules to selectively decide whether Async I/O
- should be used for the file or not.
- */
- if ((SMB_VFS_AIO_FORCE(fsp)) && (req->unread_bytes == 0) &&
+ if ((req->unread_bytes == 0) &&
schedule_aio_write_and_X(conn, req, fsp, data, startpos,
numtowrite)) {
END_PROFILE(SMBwriteX);
return;
}
-
+
nwritten = write_file(req,fsp,data,startpos,numtowrite);
}
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
return;
}
flush_write_cache(fsp, SEEK_FLUSH);
- mode = SVAL(req->inbuf,smb_vwv1) & 3;
+ mode = SVAL(req->vwv+1, 0) & 3;
/* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
- startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2);
+ startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0);
switch (mode) {
case 0:
reply_outbuf(req, 2, 0);
SIVAL(req->outbuf,smb_vwv0,res);
-
+
DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
fsp->fnum, (double)startpos, (double)res, mode));
return;
}
- fnum = SVAL(req->inbuf,smb_vwv0);
- fsp = file_fsp(fnum);
+ fnum = SVAL(req->vwv+0, 0);
+ fsp = file_fsp(req, fnum);
- if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp, ¤t_user)) {
+ if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) {
return;
}
-
+
if (!fsp) {
file_sync_all(conn);
} else {
return;
}
}
-
+
reply_outbuf(req, 0, 0);
DEBUG(3,("flush\n"));
return;
}
- /* If it's an IPC, pass off to the pipe handler. */
- if (IS_IPC(conn)) {
- reply_pipe_close(conn, req);
- END_PROFILE(SMBclose);
- return;
- }
-
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
/*
- * We can only use CHECK_FSP if we know it's not a directory.
+ * We can only use check_fsp if we know it's not a directory.
*/
- if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
+ if(!fsp || (fsp->conn != conn) || (fsp->vuid != req->vuid)) {
reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBclose);
return;
* Special case - close NT SMB directory handle.
*/
DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
- status = close_file(fsp,NORMAL_CLOSE);
+ status = close_file(req, fsp, NORMAL_CLOSE);
} else {
+ time_t t;
/*
* Close ordinary file.
*/
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
fsp->fh->fd, fsp->fnum,
conn->num_files_open));
-
+
/*
* Take care of any time sent in the close.
*/
- fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
- srv_make_unix_date3(
- req->inbuf+smb_vwv1)));
+ t = srv_make_unix_date3(req->vwv+1);
+ set_close_write_time(fsp, convert_time_t_to_timespec(t));
/*
* close_file() returns the unix errno if an error
* was detected on close - normally this is due to
* a disk full error. If not then it was probably an I/O error.
*/
-
- status = close_file(fsp,NORMAL_CLOSE);
+
+ status = close_file(req, fsp, NORMAL_CLOSE);
}
if (!NT_STATUS_IS_OK(status)) {
ssize_t nwritten = -1;
NTSTATUS close_status = NT_STATUS_OK;
SMB_OFF_T startpos;
- char *data;
+ const char *data;
struct timespec mtime;
files_struct *fsp;
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBwriteclose);
return;
}
return;
}
- numtowrite = SVAL(req->inbuf,smb_vwv1);
- startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2);
- mtime = convert_time_t_to_timespec(srv_make_unix_date3(
- req->inbuf+smb_vwv4));
- data = smb_buf(req->inbuf) + 1;
-
+ numtowrite = SVAL(req->vwv+1, 0);
+ startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
+ mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
+ data = (const char *)req->buf + 1;
+
if (numtowrite
- && is_locked(fsp, (uint32)req->smbpid, (SMB_BIG_UINT)numtowrite,
- (SMB_BIG_UINT)startpos, WRITE_LOCK)) {
+ && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite,
+ (uint64_t)startpos, WRITE_LOCK)) {
reply_doserror(req, ERRDOS,ERRlock);
END_PROFILE(SMBwriteclose);
return;
}
-
+
nwritten = write_file(req,fsp,data,startpos,numtowrite);
- set_filetime(conn, fsp->fsp_name, mtime);
-
+ set_close_write_time(fsp, mtime);
+
/*
* More insanity. W2K only closes the file if writelen > 0.
* JRA.
if (numtowrite) {
DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
fsp->fsp_name ));
- close_status = close_file(fsp,NORMAL_CLOSE);
+ close_status = close_file(req, fsp, NORMAL_CLOSE);
}
DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
fsp->fnum, (int)numtowrite, (int)nwritten,
conn->num_files_open));
-
+
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
reply_doserror(req, ERRHRD, ERRdiskfull);
END_PROFILE(SMBwriteclose);
return;
}
-
+
if(!NT_STATUS_IS_OK(close_status)) {
reply_nterror(req, close_status);
END_PROFILE(SMBwriteclose);
}
reply_outbuf(req, 1, 0);
-
+
SSVAL(req->outbuf,smb_vwv0,nwritten);
END_PROFILE(SMBwriteclose);
return;
void reply_lock(struct smb_request *req)
{
connection_struct *conn = req->conn;
- SMB_BIG_UINT count,offset;
+ uint64_t count,offset;
NTSTATUS status;
files_struct *fsp;
struct byte_range_lock *br_lck = NULL;
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBlock);
return;
}
release_level_2_oplocks_on_change(fsp);
- count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
- offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
+ count = (uint64_t)IVAL(req->vwv+1, 0);
+ offset = (uint64_t)IVAL(req->vwv+3, 0);
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
void reply_unlock(struct smb_request *req)
{
connection_struct *conn = req->conn;
- SMB_BIG_UINT count,offset;
+ uint64_t count,offset;
NTSTATUS status;
files_struct *fsp;
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBunlock);
return;
}
-
- count = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv1);
- offset = (SMB_BIG_UINT)IVAL(req->inbuf,smb_vwv3);
-
+
+ count = (uint64_t)IVAL(req->vwv+1, 0);
+ offset = (uint64_t)IVAL(req->vwv+3, 0);
+
status = do_unlock(smbd_messaging_context(),
fsp,
req->smbpid,
connection_struct *conn = req->conn;
int smb_reverb;
int seq_num;
- unsigned int data_len = smb_buflen(req->inbuf);
START_PROFILE(SMBecho);
return;
}
- if (data_len > BUFFER_SIZE) {
- DEBUG(0,("reply_echo: data_len too large.\n"));
- reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES);
- END_PROFILE(SMBecho);
- return;
- }
-
- smb_reverb = SVAL(req->inbuf,smb_vwv0);
+ smb_reverb = SVAL(req->vwv+0, 0);
- reply_outbuf(req, 1, data_len);
+ reply_outbuf(req, 1, req->buflen);
/* copy any incoming data back out */
- if (data_len > 0) {
- memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len);
+ if (req->buflen > 0) {
+ memcpy(smb_buf(req->outbuf), req->buf, req->buflen);
}
if (smb_reverb > 100) {
TALLOC_FREE(req->outbuf);
- smb_echo_count++;
-
END_PROFILE(SMBecho);
return;
}
connection_struct *conn = req->conn;
files_struct *fsp;
NTSTATUS status;
-
+
START_PROFILE(SMBsplopen);
if (req->wct < 2) {
return;
}
+ status = file_new(req, conn, &fsp);
+ if(!NT_STATUS_IS_OK(status)) {
+ reply_nterror(req, status);
+ END_PROFILE(SMBsplopen);
+ return;
+ }
+
/* Open for exclusive use, write only. */
- status = print_fsp_open(conn, NULL, &fsp);
+ status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
-
+
DEBUG(3,("openprint fd=%d fnum=%d\n",
fsp->fh->fd, fsp->fnum));
START_PROFILE(SMBsplclose);
- if (req->wct < 3) {
+ if (req->wct < 1) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBsplclose);
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBsplclose);
return;
}
END_PROFILE(SMBsplclose);
return;
}
-
+
DEBUG(3,("printclose fd=%d fnum=%d\n",
fsp->fh->fd,fsp->fnum));
-
- status = close_file(fsp,NORMAL_CLOSE);
+
+ status = close_file(req, fsp, NORMAL_CLOSE);
if(!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
return;
}
+ reply_outbuf(req, 0, 0);
+
END_PROFILE(SMBsplclose);
return;
}
return;
}
- max_count = SVAL(req->inbuf,smb_vwv0);
- start_index = SVAL(req->inbuf,smb_vwv1);
+ max_count = SVAL(req->vwv+0, 0);
+ start_index = SVAL(req->vwv+1, 0);
/* we used to allow the client to get the cnum wrong, but that
is really quite gross and only worked when there was only
SSVAL(req->outbuf,smb_vwv1,0);
SCVAL(smb_buf(req->outbuf),0,1);
SSVAL(smb_buf(req->outbuf),1,0);
-
+
DEBUG(3,("printqueue start_index=%d max_count=%d\n",
start_index, max_count));
num_to_get = 0;
else
num_to_get = MIN(num_to_get,count-first);
-
+
for (i=first;i<first+num_to_get;i++) {
char blob[28];
}
SAFE_FREE(queue);
-
+
DEBUG(3,("%d entries returned in queue\n",count));
}
-
+
END_PROFILE(SMBsplretq);
return;
}
{
connection_struct *conn = req->conn;
int numtowrite;
- char *data;
+ const char *data;
files_struct *fsp;
START_PROFILE(SMBsplwr);
END_PROFILE(SMBsplwr);
return;
}
-
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
+
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBsplwr);
return;
}
return;
}
- numtowrite = SVAL(smb_buf(req->inbuf),1);
+ numtowrite = SVAL(req->buf, 1);
- if (smb_buflen(req->inbuf) < numtowrite + 3) {
+ if (req->buflen < numtowrite + 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBsplwr);
return;
}
- data = smb_buf(req->inbuf) + 3;
+ data = (const char *)req->buf + 3;
if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) {
reply_unixerror(req, ERRHRD, ERRdiskfull);
START_PROFILE(SMBmkdir);
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
- smb_buf(req->inbuf) + 1, 0,
- STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBmkdir);
}
}
- /* We only have veto files/directories. Recursive delete. */
+ /* We only have veto files/directories.
+ * Are we allowed to delete them ? */
+
+ if(!lp_recursive_veto_delete(SNUM(conn))) {
+ TALLOC_FREE(dir_hnd);
+ errno = ENOTEMPTY;
+ goto err;
+ }
+ /* Do a recursive delete. */
RewindDir(dir_hnd,&dirpos);
while ((dname = ReadDirName(dir_hnd,&dirpos))) {
char *fullname = NULL;
break;
}
if(st.st_mode & S_IFDIR) {
- if(lp_recursive_veto_delete(SNUM(conn))) {
- if(!recursive_rmdir(ctx, conn, fullname))
- break;
+ if(!recursive_rmdir(ctx, conn, fullname)) {
+ break;
}
if(SMB_VFS_RMDIR(conn,fullname) != 0) {
break;
START_PROFILE(SMBrmdir);
- srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory,
- smb_buf(req->inbuf) + 1, 0,
- STR_TERMINATE, &status);
+ srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1,
+ STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBrmdir);
char *ext1 = NULL;
char *ext2 = NULL;
char *p,*p2, *pname1, *pname2;
-
+
name2_copy = talloc_strdup(ctx, name2);
if (!name2_copy) {
return False;
if (!pname1 || !pname2) {
return False;
}
-
+
/* Truncate the copy of name2 at the last '/' */
*pname2 = '\0';
sharepaths we need to manipulate relative paths. */
/* TODO - create the absolute path and manipulate the newname
relative to the sharepath. */
- if (fsp->conn != conn) {
+ if (!strequal(fsp->conn->connectpath, conn->connectpath)) {
continue;
}
DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ if(replace_if_exists && dst_exists) {
+ if (is_ntfs_stream_name(newname)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+
if (dst_exists) {
struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf1);
files_struct *dst_fsp = file_find_di_first(fileid);
return NT_STATUS_ACCESS_DENIED;
}
- lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
+ NULL);
/*
* We have the file open ourselves, so not being able to get the
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
- rename_open_files(conn, lck, newname);
-
notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
+ rename_open_files(conn, lck, newname);
+
/*
* A rename acts as a new file create w.r.t. allowing an initial delete
* on close, probably because in Windows there is a new handle to the
uint32 attrs,
bool replace_if_exists,
bool src_has_wild,
- bool dest_has_wild)
+ bool dest_has_wild,
+ uint32_t access_mask)
{
char *directory = NULL;
char *mask = NULL;
struct smb_Dir *dir_hnd = NULL;
const char *dname;
long offset = 0;
+ int create_options = 0;
ZERO_STRUCT(sbuf1);
ZERO_STRUCT(sbuf2);
ZERO_STRUCT(sbuf1);
SMB_VFS_STAT(conn, directory, &sbuf1);
- status = S_ISDIR(sbuf1.st_mode) ?
- open_directory(conn, req, directory, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, NULL,
- &fsp)
- : open_file_ntcreate(conn, req, directory, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, 0, NULL,
- &fsp);
+ if (S_ISDIR(sbuf1.st_mode)) {
+ create_options |= FILE_DIRECTORY_FILE;
+ }
+
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ directory, /* fname */
+ false, /* is_dos_path */
+ access_mask, /* access_mask */
+ (FILE_SHARE_READ | /* share_access */
+ FILE_SHARE_WRITE),
+ FILE_OPEN, /* create_disposition*/
+ create_options, /* create_options */
+ 0, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not open rename source %s: %s\n",
last_component_dest,
attrs, replace_if_exists);
- close_file(fsp, NORMAL_CLOSE);
+ close_file(req, fsp, NORMAL_CLOSE);
DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
nt_errstr(status), directory,newname));
ZERO_STRUCT(sbuf1);
SMB_VFS_STAT(conn, fname, &sbuf1);
- status = S_ISDIR(sbuf1.st_mode) ?
- open_directory(conn, req, fname, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, NULL,
- &fsp)
- : open_file_ntcreate(conn, req, fname, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, 0, NULL,
- &fsp);
+ create_options = 0;
+
+ if (S_ISDIR(sbuf1.st_mode)) {
+ create_options |= FILE_DIRECTORY_FILE;
+ }
+
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ req, /* req */
+ 0, /* root_dir_fid */
+ fname, /* fname */
+ false, /* is_dos_path */
+ access_mask, /* access_mask */
+ (FILE_SHARE_READ | /* share_access */
+ FILE_SHARE_WRITE),
+ FILE_OPEN, /* create_disposition*/
+ create_options, /* create_options */
+ 0, /* file_attributes */
+ 0, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL, /* pinfo */
+ &sbuf1); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("rename_internals: open_file_ntcreate "
+ DEBUG(3,("rename_internals: SMB_VFS_CREATE_FILE "
"returned %s rename %s -> %s\n",
nt_errstr(status), directory, newname));
break;
status = rename_internals_fsp(conn, fsp, destname, dname,
attrs, replace_if_exists);
- close_file(fsp, NORMAL_CLOSE);
+ close_file(req, fsp, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("rename_internals_fsp returned %s for "
}
TALLOC_FREE(dir_hnd);
- if (count == 0 && NT_STATUS_IS_OK(status)) {
+ if (count == 0 && NT_STATUS_IS_OK(status) && errno != 0) {
status = map_nt_error_from_unix(errno);
}
connection_struct *conn = req->conn;
char *name = NULL;
char *newname = NULL;
- char *p;
+ const char *p;
uint32 attrs;
NTSTATUS status;
bool src_has_wcard = False;
return;
}
- attrs = SVAL(req->inbuf,smb_vwv0);
+ attrs = SVAL(req->vwv+0, 0);
- p = smb_buf(req->inbuf) + 1;
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
- 0, STR_TERMINATE, &status,
- &src_has_wcard);
+ p = (const char *)req->buf + 1;
+ p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
+ &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBmv);
return;
}
p++;
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
- 0, STR_TERMINATE, &status,
- &dest_has_wcard);
+ p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
+ &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBmv);
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
status = rename_internals(ctx, conn, req, name, newname, attrs, False,
- src_has_wcard, dest_has_wcard);
+ src_has_wcard, dest_has_wcard, DELETE_ACCESS);
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(req->mid)) {
/* We have re-scheduled this call. */
}
}
- status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
- FILE_GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY,
- NULL, &fsp1);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ NULL, /* req */
+ 0, /* root_dir_fid */
+ src, /* fname */
+ false, /* is_dos_path */
+ FILE_GENERIC_READ, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ INTERNAL_OPEN_ONLY, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp1, /* result */
+ NULL, /* pinfo */
+ &src_sbuf); /* psbuf */
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(dest);
ZERO_STRUCTP(&sbuf2);
}
- status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
- FILE_GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- new_create_disposition,
- 0,
- dosattrs,
- INTERNAL_OPEN_ONLY,
- NULL, &fsp2);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ NULL, /* req */
+ 0, /* root_dir_fid */
+ dest, /* fname */
+ false, /* is_dos_path */
+ FILE_GENERIC_WRITE, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ new_create_disposition, /* create_disposition*/
+ 0, /* create_options */
+ dosattrs, /* file_attributes */
+ INTERNAL_OPEN_ONLY, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp2, /* result */
+ NULL, /* pinfo */
+ &sbuf2); /* psbuf */
TALLOC_FREE(dest);
if (!NT_STATUS_IS_OK(status)) {
- close_file(fsp1,ERROR_CLOSE);
+ close_file(NULL, fsp1, ERROR_CLOSE);
return status;
}
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
}
- close_file(fsp1,NORMAL_CLOSE);
+ close_file(NULL, fsp1, NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
+ set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
/*
* As we are opening fsp1 read-only we only expect
* Thus we don't look at the error return from the
* close of fsp1.
*/
- status = close_file(fsp2,NORMAL_CLOSE);
+ status = close_file(NULL, fsp2, NORMAL_CLOSE);
if (!NT_STATUS_IS_OK(status)) {
return status;
char *name = NULL;
char *newname = NULL;
char *directory = NULL;
- char *mask = NULL;
- char *p;
+ const char *mask = NULL;
+ const char mask_star[] = "*";
+ const char *p;
int count=0;
int error = ERRnoaccess;
int err = 0;
return;
}
- tid2 = SVAL(req->inbuf,smb_vwv0);
- ofun = SVAL(req->inbuf,smb_vwv1);
- flags = SVAL(req->inbuf,smb_vwv2);
+ tid2 = SVAL(req->vwv+0, 0);
+ ofun = SVAL(req->vwv+1, 0);
+ flags = SVAL(req->vwv+2, 0);
- p = smb_buf(req->inbuf);
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p,
- 0, STR_TERMINATE, &status,
- &source_has_wild);
+ p = (const char *)req->buf;
+ p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE,
+ &status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcopy);
return;
}
- p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p,
- 0, STR_TERMINATE, &status,
- &dest_has_wild);
+ p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE,
+ &status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
reply_nterror(req, status);
END_PROFILE(SMBcopy);
}
p = strrchr_m(name,'/');
- if (!p) {
+ if (p != NULL) {
+ directory = talloc_strndup(ctx, name, PTR_DIFF(p, name));
+ mask = p+1;
+ } else {
directory = talloc_strdup(ctx, "./");
- if (!directory) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
- }
mask = name;
- } else {
- *p = 0;
- directory = talloc_strdup(ctx, name);
- if (!directory) {
- reply_nterror(req, NT_STATUS_NO_MEMORY);
- END_PROFILE(SMBcopy);
- return;
- }
- mask = p+1;
+ }
+
+ if (!directory) {
+ reply_nterror(req, NT_STATUS_NO_MEMORY);
+ END_PROFILE(SMBcopy);
+ return;
}
/*
long offset = 0;
if (strequal(mask,"????????.???")) {
- mask[0] = '*';
- mask[1] = '\0';
+ mask = mask_star;
}
status = check_name(conn, directory);
Get a lock pid, dealing with large count requests.
****************************************************************************/
-uint32 get_lock_pid( char *data, int data_offset, bool large_file_format)
+uint32 get_lock_pid(const uint8_t *data, int data_offset,
+ bool large_file_format)
{
if(!large_file_format)
return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset));
Get a lock count, dealing with large count requests.
****************************************************************************/
-SMB_BIG_UINT get_lock_count( char *data, int data_offset, bool large_file_format)
+uint64_t get_lock_count(const uint8_t *data, int data_offset,
+ bool large_file_format)
{
- SMB_BIG_UINT count = 0;
+ uint64_t count = 0;
if(!large_file_format) {
- count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
+ count = (uint64_t)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
} else {
#if defined(HAVE_LONGLONG)
- count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
- ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
+ count = (((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
+ ((uint64_t) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
#else /* HAVE_LONGLONG */
/*
SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
}
- count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
+ count = (uint64_t)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
#endif /* HAVE_LONGLONG */
}
unsigned int i;
uint32 mask = 0;
uint32 highcopy = high;
-
+
/*
* Try and find out how many significant bits there are in high.
*/
-
+
for(i = 0; highcopy; i++)
highcopy >>= 1;
-
+
/*
* We use 31 bits not 32 here as POSIX
* lock offsets may not be negative.
*/
-
+
mask = (~0) << (31 - i);
-
+
if(low & mask)
return 0; /* Fail. */
-
+
high <<= (31 - i);
-
+
return (high|low);
}
#endif /* !defined(HAVE_LONGLONG) */
Get a lock offset, dealing with large offset requests.
****************************************************************************/
-SMB_BIG_UINT get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err)
+uint64_t get_lock_offset(const uint8_t *data, int data_offset,
+ bool large_file_format, bool *err)
{
- SMB_BIG_UINT offset = 0;
+ uint64_t offset = 0;
*err = False;
if(!large_file_format) {
- offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
+ offset = (uint64_t)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
} else {
#if defined(HAVE_LONGLONG)
- offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
- ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
+ offset = (((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
+ ((uint64_t) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
#else /* HAVE_LONGLONG */
/*
* negotiated. For boxes without large unsigned ints mangle the
* lock offset by mapping the top 32 bits onto the lower 32.
*/
-
+
if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
if((new_low = map_lock_offset(high, low)) == 0) {
*err = True;
- return (SMB_BIG_UINT)-1;
+ return (uint64_t)-1;
}
DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
}
- offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
+ offset = (uint64_t)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
#endif /* HAVE_LONGLONG */
}
unsigned char oplocklevel;
uint16 num_ulocks;
uint16 num_locks;
- SMB_BIG_UINT count = 0, offset = 0;
+ uint64_t count = 0, offset = 0;
uint32 lock_pid;
int32 lock_timeout;
int i;
- char *data;
+ const uint8_t *data;
bool large_file_format;
bool err;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
END_PROFILE(SMBlockingX);
return;
}
-
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv2));
- locktype = CVAL(req->inbuf,smb_vwv3);
- oplocklevel = CVAL(req->inbuf,smb_vwv3+1);
- num_ulocks = SVAL(req->inbuf,smb_vwv6);
- num_locks = SVAL(req->inbuf,smb_vwv7);
- lock_timeout = IVAL(req->inbuf,smb_vwv4);
+
+ fsp = file_fsp(req, SVAL(req->vwv+2, 0));
+ locktype = CVAL(req->vwv+3, 0);
+ oplocklevel = CVAL(req->vwv+3, 1);
+ num_ulocks = SVAL(req->vwv+6, 0);
+ num_locks = SVAL(req->vwv+7, 0);
+ lock_timeout = IVAL(req->vwv+4, 0);
large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
- if (!check_fsp(conn, req, fsp, ¤t_user)) {
+ if (!check_fsp(conn, req, fsp)) {
END_PROFILE(SMBlockingX);
return;
}
-
- data = smb_buf(req->inbuf);
+
+ data = req->buf;
if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
/* we don't support these - and CANCEL_LOCK makes w2k
END_PROFILE(SMBlockingX);
return;
}
-
+
/* Check if this is an oplock break on a file
we have granted an oplock on.
*/
* Make sure we have granted an exclusive or batch oplock on
* this file.
*/
-
+
if (fsp->oplock_type == 0) {
/* The Samba4 nbench simulator doesn't understand
} else {
result = downgrade_oplock(fsp);
}
-
+
if (!result) {
DEBUG(0, ("reply_lockingX: error in removing "
"oplock on file %s\n", fsp->fsp_name));
if (num_locks == 0 && num_ulocks == 0) {
/* Sanity check - ensure a pure oplock break is not a
chained request. */
- if(CVAL(req->inbuf,smb_vwv0) != 0xff)
+ if(CVAL(req->vwv+0, 0) != 0xff)
DEBUG(0,("reply_lockingX: Error : pure oplock "
"break is a chained %d request !\n",
- (unsigned int)CVAL(req->inbuf,
- smb_vwv0) ));
+ (unsigned int)CVAL(req->vwv+0, 0)));
END_PROFILE(SMBlockingX);
return;
}
* We do this check *after* we have checked this is not a oplock break
* response message. JRA.
*/
-
+
release_level_2_oplocks_on_change(fsp);
- if (smb_buflen(req->inbuf) <
+ if (req->buflen <
(num_ulocks + num_locks) * (large_file_format ? 20 : 10)) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
END_PROFILE(SMBlockingX);
return;
}
-
+
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for(i = 0; i < (int)num_ulocks; i++) {
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
-
+
/*
* There is no error code marked "stupid client bug".... :-).
*/
DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
"pid %u, file %s\n", (double)offset, (double)count,
(unsigned int)lock_pid, fsp->fsp_name ));
-
+
status = do_unlock(smbd_messaging_context(),
fsp,
lock_pid,
if (!lp_blocking_locks(SNUM(conn))) {
lock_timeout = 0;
}
-
+
/* Now do any requested locks */
data += ((large_file_format ? 20 : 10)*num_ulocks);
-
+
/* Data now points at the beginning of the list
of smb_lkrng structs */
-
+
for(i = 0; i < (int)num_locks; i++) {
enum brl_type lock_type = ((locktype & LOCKING_ANDX_SHARED_LOCK) ?
READ_LOCK:WRITE_LOCK);
lock_pid = get_lock_pid( data, i, large_file_format);
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format, &err);
-
+
/*
* There is no error code marked "stupid client bug".... :-).
*/
reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
-
+
DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
"%u, file %s timeout = %d\n", (double)offset,
(double)count, (unsigned int)lock_pid,
fsp->fsp_name, (int)lock_timeout ));
-
+
if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
if (lp_blocking_locks(SNUM(conn))) {
return;
}
}
-
+
/* If any of the above locks failed, then we must unlock
all of the previous locks (X/Open spec). */
count = get_lock_count( data, i, large_file_format);
offset = get_lock_offset( data, i, large_file_format,
&err);
-
+
/*
* There is no error code marked "stupid client
* bug".... :-).
reply_doserror(req, ERRDOS, ERRnoaccess);
return;
}
-
+
do_unlock(smbd_messaging_context(),
fsp,
lock_pid,
}
reply_outbuf(req, 2, 0);
-
+
DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
-
+
END_PROFILE(SMBlockingX);
chain_reply(req);
}
connection_struct *conn = req->conn;
struct timespec ts[2];
files_struct *fsp;
+ SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
START_PROFILE(SMBsetattrE);
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
if(!fsp || (fsp->conn != conn)) {
reply_doserror(req, ERRDOS, ERRbadfid);
*/
ts[0] = convert_time_t_to_timespec(
- srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */
+ srv_make_unix_date2(req->vwv+3)); /* atime. */
ts[1] = convert_time_t_to_timespec(
- srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */
-
+ srv_make_unix_date2(req->vwv+5)); /* mtime. */
+
reply_outbuf(req, 0, 0);
/*
* Sometimes times are sent as zero - ignore them.
*/
- if (null_timespec(ts[0]) && null_timespec(ts[1])) {
- /* Ignore request */
- if( DEBUGLVL( 3 ) ) {
- dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
- dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
+ /* Ensure we have a valid stat struct for the source. */
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetattrE);
+ return;
+ }
+ } else {
+ if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetattrE);
+ return;
}
- END_PROFILE(SMBsetattrE);
- return;
- } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
- /* set modify time = to access time if modify time was unset */
- ts[1] = ts[0];
}
- /* Set the date on this file */
- /* Should we set pending modtime here ? JRA */
- if(file_ntimes(conn, fsp->fsp_name, ts)) {
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name,
+ &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
reply_doserror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsetattrE);
return;
}
-
+
DEBUG( 3, ( "reply_setattrE fnum=%d actime=%u modtime=%u\n",
fsp->fnum,
(unsigned int)ts[0].tv_sec,
SMB_STRUCT_STAT sbuf;
int mode;
files_struct *fsp;
+ struct timespec create_ts;
START_PROFILE(SMBgetattrE);
return;
}
- fsp = file_fsp(SVAL(req->inbuf,smb_vwv0));
+ fsp = file_fsp(req, SVAL(req->vwv+0, 0));
if(!fsp || (fsp->conn != conn)) {
reply_doserror(req, ERRDOS, ERRbadfid);
END_PROFILE(SMBgetattrE);
return;
}
-
+
mode = dos_mode(conn,fsp->fsp_name,&sbuf);
-
+
/*
* Convert the times into dos times. Set create
* date to be last modify date as UNIX doesn't save
reply_outbuf(req, 11, 0);
- srv_put_dos_date2((char *)req->outbuf, smb_vwv0,
- get_create_time(&sbuf,
- lp_fake_dir_create_times(SNUM(conn))));
+ create_ts = get_create_timespec(&sbuf,
+ lp_fake_dir_create_times(SNUM(conn)));
+ srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
srv_put_dos_date2((char *)req->outbuf, smb_vwv2, sbuf.st_atime);
/* Should we check pending modtime here ? JRA */
srv_put_dos_date2((char *)req->outbuf, smb_vwv4, sbuf.st_mtime);
SIVAL(req->outbuf, smb_vwv8, allocation_size);
}
SSVAL(req->outbuf,smb_vwv10, mode);
-
+
DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
-
+
END_PROFILE(SMBgetattrE);
return;
}