#include "includes.h"
/* look in server.c for some explanation of these variables */
-extern int Protocol;
+extern enum protocol_types Protocol;
extern int max_send;
extern int max_recv;
-extern char magic_char;
-extern BOOL case_sensitive;
-extern BOOL case_preserve;
-extern BOOL short_case_preserve;
-extern int global_oplock_break;
unsigned int smb_echo_count = 0;
+extern uint32 global_client_caps;
+extern struct current_user current_user;
extern BOOL global_encrypted_passwords_negotiated;
/****************************************************************************
- Ensure we check the path in *exactly* the same way as W2K.
+ Ensure we check the path in *exactly* the same way as W2K for regular pathnames.
We're assuming here that '/' is not the second byte in any multibyte char
set (a safe assumption). '\\' *may* be the second byte in a multibyte char
set.
char *d = destname;
const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
+ BOOL start_of_name_component = True;
+ unsigned int num_bad_components = 0;
while (*s) {
if (IS_DIRECTORY_SEP(*s)) {
while (IS_DIRECTORY_SEP(*s)) {
s++;
}
- if ((s[0] == '.') && (s[1] == '\0')) {
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- }
if ((d != destname) && (*s != '\0')) {
/* We only care about non-leading or trailing '/' or '\\' */
*d++ = '/';
}
- } else if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
- /* Uh oh - "../" or "..\\" or "..\0" ! */
- /*
- * No mb char starts with '.' so we're safe checking the directory separator here.
- */
+ start_of_name_component = True;
+ continue;
+ }
- /* If we just added a '/', delete it. */
+ if (start_of_name_component) {
+ if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+ /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
+
+ /*
+ * No mb char starts with '.' so we're safe checking the directory separator here.
+ */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- if (d == (destname + 1)) {
+ /* If we just added a '/' - delete it */
+ if ((d > destname) && (*(d-1) == '/')) {
+ *(d-1) = '\0';
d--;
- } else {
- d -= 2;
}
+
+ /* Are we at the start ? Can't go back further if so. */
+ if (d <= destname) {
+ ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ break;
+ }
+ /* Go back one level... */
+ /* We know this is safe as '/' cannot be part of a mb sequence. */
+ /* NOTE - if this assumption is invalid we are not in good shape... */
+ /* Decrement d first as d points to the *next* char to write into. */
+ for (d--; d > destname; d--) {
+ if (*d == '/')
+ break;
+ }
+ s += 2; /* Else go past the .. */
+ /* We're still at the start of a name component, just the previous one. */
+
+ if (num_bad_components) {
+ /* Hmmm. Should we only decrement the bad_components if
+ we're removing a bad component ? Need to check this. JRA. */
+ num_bad_components--;
+ }
+
+ continue;
+
+ } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
+ /* Component of pathname can't be "." only. */
+ ret = NT_STATUS_OBJECT_NAME_INVALID;
+ num_bad_components++;
+ *d++ = *s++;
+ continue;
}
- /* Are we at the start ? Can't go back further if so. */
- if (d == destname) {
- ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
- break;
+ }
+
+ if (!(*s & 0x80)) {
+ if (*s <= 0x1f) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
}
- /* Go back one level... */
- /* We know this is safe as '/' cannot be part of a mb sequence. */
- /* NOTE - if this assumption is invalid we are not in good shape... */
- while (d > destname) {
- if (*d == '/')
+ switch (*s) {
+ case '*':
+ case '?':
+ case '<':
+ case '>':
+ case '"':
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ default:
+ *d++ = *s++;
break;
- d--;
}
- s += 3;
- } else if ((s[0] == '.') && (IS_DIRECTORY_SEP(s[1]) || (s[1] == '\0'))) {
+ } else {
+ switch(next_mb_char_size(s)) {
+ case 4:
+ *d++ = *s++;
+ case 3:
+ *d++ = *s++;
+ case 2:
+ *d++ = *s++;
+ case 1:
+ *d++ = *s++;
+ break;
+ default:
+ DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
+ *d = '\0';
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ if (start_of_name_component && num_bad_components) {
+ num_bad_components++;
+ }
+ start_of_name_component = False;
+ }
+
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
+ if (num_bad_components > 1) {
+ ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+
+ *d = '\0';
+ return ret;
+}
+
+/****************************************************************************
+ Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext
+ path or anything including wildcards.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption). '\\' *may* be the second byte in a multibyte char
+ set.
+****************************************************************************/
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname)
+{
+ char *d = destname;
+ const char *s = srcname;
+ NTSTATUS ret = NT_STATUS_OK;
+ BOOL start_of_name_component = True;
+ unsigned int num_bad_components = 0;
+
+ while (*s) {
+ if (IS_DIRECTORY_SEP(*s)) {
/*
- * No mb char starts with '.' so we're safe checking the directory separator here.
+ * Safe to assume is not the second part of a mb char as this is handled below.
*/
+ /* Eat multiple '/' or '\\' */
+ while (IS_DIRECTORY_SEP(*s)) {
+ s++;
+ }
+ if ((d != destname) && (*s != '\0')) {
+ /* We only care about non-leading or trailing '/' or '\\' */
+ *d++ = '/';
+ }
- /* "./" or ".\\" fails with a different error depending on where it is... */
+ start_of_name_component = True;
+ continue;
+ }
- if (s == srcname) {
- ret = NT_STATUS_OBJECT_NAME_INVALID;
- break;
- } else {
- if (s[1] != '\0' && s[2] == '\0') {
- ret = NT_STATUS_INVALID_PARAMETER;
+ if (start_of_name_component) {
+ if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) {
+ /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */
+
+ /*
+ * No mb char starts with '.' so we're safe checking the directory separator here.
+ */
+
+ /* If we just added a '/' - delete it */
+ if ((d > destname) && (*(d-1) == '/')) {
+ *(d-1) = '\0';
+ d--;
+ }
+
+ /* Are we at the start ? Can't go back further if so. */
+ if (d <= destname) {
+ ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
break;
}
- ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
- break;
+ /* Go back one level... */
+ /* We know this is safe as '/' cannot be part of a mb sequence. */
+ /* NOTE - if this assumption is invalid we are not in good shape... */
+ /* Decrement d first as d points to the *next* char to write into. */
+ for (d--; d > destname; d--) {
+ if (*d == '/')
+ break;
+ }
+ s += 2; /* Else go past the .. */
+ /* We're still at the start of a name component, just the previous one. */
+
+ if (num_bad_components) {
+ /* Hmmm. Should we only decrement the bad_components if
+ we're removing a bad component ? Need to check this. JRA. */
+ num_bad_components--;
+ }
+
+ continue;
+
+ } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) {
+ /* Component of pathname can't be "." only. */
+ ret = NT_STATUS_OBJECT_NAME_INVALID;
+ num_bad_components++;
+ *d++ = *s++;
+ continue;
}
- s++;
+ }
+
+ if (!(*s & 0x80)) {
+ if (*s <= 0x1f) {
+ return NT_STATUS_OBJECT_NAME_INVALID;
+ }
+ *d++ = *s++;
} else {
- if (!(*s & 0x80)) {
- *d++ = *s++;
- } else {
- switch(next_mb_char_size(s)) {
- case 4:
- *d++ = *s++;
- case 3:
- *d++ = *s++;
- case 2:
- *d++ = *s++;
- case 1:
- *d++ = *s++;
+ switch(next_mb_char_size(s)) {
+ case 4:
+ *d++ = *s++;
+ case 3:
+ *d++ = *s++;
+ case 2:
+ *d++ = *s++;
+ case 1:
+ *d++ = *s++;
+ break;
+ default:
+ DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n"));
+ *d = '\0';
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ if (start_of_name_component && num_bad_components) {
+ num_bad_components++;
+ }
+ start_of_name_component = False;
+ }
+
+ if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) {
+ /* For some strange reason being called from findfirst changes
+ the num_components number to cause the error return to change. JRA. */
+ if (num_bad_components > 2) {
+ ret = NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ }
+
+ *d = '\0';
+ return ret;
+}
+
+/****************************************************************************
+ Check the path for a POSIX client.
+ We're assuming here that '/' is not the second byte in any multibyte char
+ set (a safe assumption).
+****************************************************************************/
+
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
+{
+ char *d = destname;
+ const char *s = srcname;
+ NTSTATUS ret = NT_STATUS_OK;
+ BOOL start_of_name_component = True;
+
+ while (*s) {
+ if (*s == '/') {
+ /*
+ * Safe to assume is not the second part of a mb char as this is handled below.
+ */
+ /* Eat multiple '/' or '\\' */
+ while (*s == '/') {
+ s++;
+ }
+ if ((d != destname) && (*s != '\0')) {
+ /* We only care about non-leading or trailing '/' */
+ *d++ = '/';
+ }
+
+ start_of_name_component = True;
+ continue;
+ }
+
+ if (start_of_name_component) {
+ if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
+ /* Uh oh - "/../" or "/..\0" ! */
+
+ /*
+ * No mb char starts with '.' so we're safe checking the directory separator here.
+ */
+
+ /* If we just added a '/' - delete it */
+ if ((d > destname) && (*(d-1) == '/')) {
+ *(d-1) = '\0';
+ d--;
+ }
+
+ /* Are we at the start ? Can't go back further if so. */
+ if (d <= destname) {
+ ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
+ break;
+ }
+ /* Go back one level... */
+ /* We know this is safe as '/' cannot be part of a mb sequence. */
+ /* NOTE - if this assumption is invalid we are not in good shape... */
+ /* Decrement d first as d points to the *next* char to write into. */
+ for (d--; d > destname; d--) {
+ if (*d == '/')
break;
- default:
- DEBUG(0,("check_path_syntax: character length assumptions invalid !\n"));
- *d = '\0';
- return NT_STATUS_INVALID_PARAMETER;
}
+ s += 2; /* Else go past the .. */
+ continue;
+
+ } else if ((s[0] == '.') && ((s[1] == '\0') || (s[1] == '/'))) {
+ /* Eat the '.' */
+ s++;
+ continue;
+ }
+ }
+
+ if (!(*s & 0x80)) {
+ *d++ = *s++;
+ } else {
+ switch(next_mb_char_size(s)) {
+ case 4:
+ *d++ = *s++;
+ case 3:
+ *d++ = *s++;
+ case 2:
+ *d++ = *s++;
+ case 1:
+ *d++ = *s++;
+ break;
+ default:
+ DEBUG(0,("check_path_syntax_posix: character length assumptions invalid !\n"));
+ *d = '\0';
+ return NT_STATUS_INVALID_PARAMETER;
}
}
+ start_of_name_component = False;
}
+
*d = '\0';
return ret;
}
Pull a string and check the path - provide for error return.
****************************************************************************/
-size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
+size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err, BOOL allow_wcard_names)
{
pstring tmppath;
char *tmppath_ptr = tmppath;
} else {
ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
- *err = check_path_syntax(dest, tmppath);
+ if (lp_posix_pathnames()) {
+ *err = check_path_syntax_posix(dest, tmppath);
+ } else if (allow_wcard_names) {
+ *err = check_path_syntax_wcard(dest, tmppath);
+ } else {
+ *err = check_path_syntax(dest, tmppath);
+ }
return ret;
}
reload_services(True);
reopen_logs();
- claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
-
already_got_session = True;
break;
int passlen = SVAL(inbuf,smb_vwv3);
pstring path;
char *p, *q;
- extern BOOL global_encrypted_passwords_negotiated;
START_PROFILE(SMBtconX);
}
SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
- srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
+ if (conn) {
+ srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
+ }
break;
}
}
int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int outsize = 0;
- int mode;
pstring name;
BOOL ok = False;
BOOL bad_path = False;
START_PROFILE(SMBchkpth);
- srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBchkpth);
return ERROR_NT(status);
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
unix_convert(name,conn,0,&bad_path,&sbuf);
-
- mode = SVAL(inbuf,smb_vwv0);
+ if (bad_path) {
+ END_PROFILE(SMBchkpth);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (check_name(name,conn)) {
if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
* the parent directory is valid but not the
* last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
* for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
- * if the path is invalid.
+ * if the path is invalid. This is different from set_bad_path_error()
+ * in the non-NT error case.
*/
- if (bad_path) {
- END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
- } else {
- END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
- }
- } else if (errno == ENOTDIR) {
END_PROFILE(SMBchkpth);
- return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
+ return ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpath);
}
END_PROFILE(SMBchkpth);
}
outsize = set_message(outbuf,0,0,True);
-
- DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+ DEBUG(3,("chkpth %s mode=%d\n", name, (int)SVAL(inbuf,smb_vwv0)));
END_PROFILE(SMBchkpth);
return(outsize);
START_PROFILE(SMBgetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
return ERROR_NT(status);
ok = True;
} else {
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBgetatr);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (check_name(fname,conn)) {
if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
mode = dos_mode(conn,fname,&sbuf);
START_PROFILE(SMBsetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
return ERROR_NT(status);
}
+ RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
+
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBsetatr);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
mode = SVAL(inbuf,smb_vwv0);
mtime = make_unix_date3(inbuf+smb_vwv1);
mode &= ~aDIR;
if (check_name(fname,conn)) {
- ok = (file_set_dosmode(conn,fname,mode,NULL) == 0);
+ ok = (file_set_dosmode(conn,fname,mode,&sbuf,False) == 0);
}
} else {
ok = True;
SMB_BIG_UINT dfree,dsize,bsize;
START_PROFILE(SMBdskattr);
- SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
+ if (SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
+ END_PROFILE(SMBdskattr);
+ return(UNIXERROR(ERRHRD,ERRgeneral));
+ }
outsize = set_message(outbuf,5,0,True);
pstring directory;
pstring fname;
SMB_OFF_T size;
- int mode;
+ uint32 mode;
time_t date;
- int dirtype;
+ uint32 dirtype;
int outsize = 0;
unsigned int numentries = 0;
unsigned int maxentries = 0;
BOOL can_open = True;
BOOL bad_path = False;
NTSTATUS nt_status;
+ BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False;
+
+ if (lp_posix_pathnames()) {
+ return reply_unknown(inbuf, outbuf);
+ }
+
START_PROFILE(SMBsearch);
*mask = *directory = *fname = 0;
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status);
+ p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, True);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
}
+
+ RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf);
+
p++;
status_len = SVAL(p, 0);
p += 2;
ok = True;
if (status_len == 0) {
- dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
+ dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid), mask, dirtype);
if (dptr_num < 0) {
if(dptr_num == -2) {
END_PROFILE(SMBsearch);
END_PROFILE(SMBsearch);
return ERROR_DOS(ERRDOS,ERRnofids);
}
- dptr_set_wcard(dptr_num, strdup(mask));
- dptr_set_attr(dptr_num, dirtype);
} else {
dirtype = dptr_attr(dptr_num);
}
if (ok) {
if ((dirtype&0x1F) == aVOLID) {
memcpy(p,status,21);
- make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
+ make_dir_struct(p,"???????????",volume_label(SNUM(conn)),
+ 0,aVOLID,0,!allow_long_path_components);
dptr_fill(p+12,dptr_num);
if (dptr_zero(p+12) && (status_len==0))
numentries = 1;
finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
if (!finished) {
memcpy(p,status,21);
- make_dir_struct(p,mask,fname,size,mode,date);
- dptr_fill(p+12,dptr_num);
+ make_dir_struct(p,mask,fname,size, mode,date,
+ !allow_long_path_components);
+ if (!dptr_fill(p+12,dptr_num)) {
+ break;
+ }
numentries++;
+ p += DIR_STRUCT_SIZE;
}
- p += DIR_STRUCT_SIZE;
}
}
} /* if (ok ) */
and no entries were found then return error and close dirptr
(X/Open spec) */
- if(ok && expect_close && numentries == 0 && status_len == 0) {
- if (Protocol < PROTOCOL_NT1) {
- SCVAL(outbuf,smb_rcls,ERRDOS);
- SSVAL(outbuf,smb_err,ERRnofiles);
- }
- /* Also close the dptr - we know it's gone */
+ if (numentries == 0 || !ok) {
dptr_close(&dptr_num);
- } else if (numentries == 0 || !ok) {
- if (Protocol < PROTOCOL_NT1) {
- SCVAL(outbuf,smb_rcls,ERRDOS);
- SSVAL(outbuf,smb_err,ERRnofiles);
- }
+ } else if(ok && expect_close && status_len == 0) {
+ /* Close the dptr - we know it's gone */
dptr_close(&dptr_num);
}
/* If we were called as SMBfunique, then we can close the dirptr now ! */
- if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
+ if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique) {
dptr_close(&dptr_num);
+ }
+
+ if ((numentries == 0) && !ms_has_wild(mask)) {
+ return ERROR_BOTH(STATUS_NO_MORE_FILES,ERRDOS,ERRnofiles);
+ }
SSVAL(outbuf,smb_vwv0,numentries);
SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
SCVAL(smb_buf(outbuf),0,5);
SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
- if (Protocol >= PROTOCOL_NT1)
- SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
-
+ /* The replies here are never long name. */
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME));
+ if (!allow_long_path_components) {
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS));
+ }
+
+ /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */
+ SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
+
outsize += DIR_STRUCT_SIZE*numentries;
smb_setlen(outbuf,outsize - 4);
char *p;
NTSTATUS err;
+ if (lp_posix_pathnames()) {
+ return reply_unknown(inbuf, outbuf);
+ }
+
START_PROFILE(SMBfclose);
outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err);
+ p += srvstr_get_path(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, True);
if (!NT_STATUS_IS_OK(err)) {
END_PROFILE(SMBfclose);
return ERROR_NT(err);
{
pstring fname;
int outsize = 0;
- int fmode=0;
- int share_mode;
+ uint32 fattr=0;
SMB_OFF_T size = 0;
time_t mtime=0;
- int rmode=0;
+ int info;
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
- uint16 dos_attr = SVAL(inbuf,smb_vwv1);
+ int deny_mode;
+ uint32 dos_attr = SVAL(inbuf,smb_vwv1);
+ uint32 access_mask;
+ uint32 share_mode;
+ uint32 create_disposition;
+ uint32 create_options = 0;
NTSTATUS status;
START_PROFILE(SMBopen);
- share_mode = SVAL(inbuf,smb_vwv0);
+ deny_mode = SVAL(inbuf,smb_vwv0);
- srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
return ERROR_NT(status);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBopen);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
- fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
- (uint32)dos_attr, oplock_request,&rmode,NULL);
+ if (!map_open_params_to_ntcreate(fname, deny_mode, OPENX_FILE_EXISTS_OPEN,
+ &access_mask, &share_mode, &create_disposition, &create_options)) {
+ END_PROFILE(SMBopen);
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
+ }
+
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ dos_attr,
+ oplock_request,
+ &info);
if (!fsp) {
END_PROFILE(SMBopen);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
size = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
+ if (fattr & aDIR) {
DEBUG(3,("attempt to open a directory %s\n",fname));
close_file(fsp,False);
END_PROFILE(SMBopen);
outsize = set_message(outbuf,7,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
- SSVAL(outbuf,smb_vwv1,fmode);
- if(lp_dos_filetime_resolution(SNUM(conn)) )
+ SSVAL(outbuf,smb_vwv1,fattr);
+ if(lp_dos_filetime_resolution(SNUM(conn)) ) {
put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
- else
+ } else {
put_dos_date3(outbuf,smb_vwv2,mtime);
+ }
SIVAL(outbuf,smb_vwv4,(uint32)size);
- SSVAL(outbuf,smb_vwv6,rmode);
+ SSVAL(outbuf,smb_vwv6,GET_OPENX_MODE(deny_mode));
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
END_PROFILE(SMBopen);
return(outsize);
}
int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
pstring fname;
- int smb_mode = SVAL(inbuf,smb_vwv3);
- int smb_attr = SVAL(inbuf,smb_vwv5);
+ uint16 open_flags = SVAL(inbuf,smb_vwv2);
+ int deny_mode = SVAL(inbuf,smb_vwv3);
+ uint32 smb_attr = SVAL(inbuf,smb_vwv5);
/* Breakout the oplock request bits so we can set the
reply bits separately. */
BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
BOOL oplock_request = ex_oplock_request | core_oplock_request;
#if 0
- int open_flags = SVAL(inbuf,smb_vwv2);
int smb_sattr = SVAL(inbuf,smb_vwv4);
uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
SMB_OFF_T size=0;
- int fmode=0,mtime=0,rmode=0;
+ uint32 fattr=0;
+ int mtime=0;
SMB_STRUCT_STAT sbuf;
int smb_action = 0;
BOOL bad_path = False;
files_struct *fsp;
NTSTATUS status;
+ SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9);
+ ssize_t retval = -1;
+ uint32 access_mask;
+ uint32 share_mode;
+ uint32 create_disposition;
+ uint32 create_options = 0;
+
START_PROFILE(SMBopenX);
/* If it's an IPC, pass off the pipe handler. */
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
return ERROR_NT(status);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
-
- fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr,
- oplock_request, &rmode,&smb_action);
+ if (bad_path) {
+ END_PROFILE(SMBopenX);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
+
+ if (!map_open_params_to_ntcreate(fname, deny_mode, smb_ofun,
+ &access_mask,
+ &share_mode,
+ &create_disposition,
+ &create_options)) {
+ END_PROFILE(SMBopenX);
+ return ERROR_DOS(ERRDOS, ERRbadaccess);
+ }
+
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ smb_attr,
+ oplock_request,
+ &smb_action);
if (!fsp) {
END_PROFILE(SMBopenX);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
size = sbuf.st_size;
- fmode = dos_mode(conn,fname,&sbuf);
+
+ /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
+ if the file is truncated or created. */
+ 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,False);
+ END_PROFILE(SMBntcreateX);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size);
+ if (retval < 0) {
+ close_file(fsp,False);
+ END_PROFILE(SMBwrite);
+ return ERROR_NT(NT_STATUS_DISK_FULL);
+ }
+ size = get_allocation_size(conn,fsp,&sbuf);
+ }
+
+ fattr = dos_mode(conn,fname,&sbuf);
mtime = sbuf.st_mtime;
- if (fmode & aDIR) {
+ if (fattr & aDIR) {
close_file(fsp,False);
END_PROFILE(SMBopenX);
return ERROR_DOS(ERRDOS,ERRnoaccess);
correct bit for extended oplock reply.
*/
- if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
- if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
smb_action |= EXTENDED_OPLOCK_GRANTED;
+ }
/* If the caller set the core oplock request bit
and we granted one (by whatever means) - set the
correct bit for core oplock reply.
*/
- if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- set_message(outbuf,15,0,True);
+ if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+ set_message(outbuf,19,0,True);
+ } else {
+ set_message(outbuf,15,0,True);
+ }
SSVAL(outbuf,smb_vwv2,fsp->fnum);
- SSVAL(outbuf,smb_vwv3,fmode);
- if(lp_dos_filetime_resolution(SNUM(conn)) )
+ SSVAL(outbuf,smb_vwv3,fattr);
+ if(lp_dos_filetime_resolution(SNUM(conn)) ) {
put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
- else
+ } else {
put_dos_date3(outbuf,smb_vwv4,mtime);
+ }
SIVAL(outbuf,smb_vwv6,(uint32)size);
- SSVAL(outbuf,smb_vwv8,rmode);
+ SSVAL(outbuf,smb_vwv8,GET_OPENX_MODE(deny_mode));
SSVAL(outbuf,smb_vwv11,smb_action);
+ if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
+ SIVAL(outbuf, smb_vwv15, STD_RIGHT_ALL_ACCESS);
+ }
+
END_PROFILE(SMBopenX);
return chain_reply(inbuf,outbuf,length,bufsize);
}
pstring fname;
int com;
int outsize = 0;
- int createmode;
- int ofun = 0;
+ uint32 fattr = SVAL(inbuf,smb_vwv0);
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
SMB_STRUCT_STAT sbuf;
NTSTATUS status;
+ uint32 access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
+ uint32 create_disposition;
+ uint32 create_options = 0;
+
START_PROFILE(SMBcreate);
com = SVAL(inbuf,smb_com);
- createmode = SVAL(inbuf,smb_vwv0);
- srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
return ERROR_NT(status);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBcreate);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
- if (createmode & aVOLID)
+ if (fattr & aVOLID) {
DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
-
+ }
+
if(com == SMBmknew) {
/* We should fail if file exists. */
- ofun = FILE_CREATE_IF_NOT_EXIST;
+ create_disposition = FILE_CREATE;
} else {
- /* SMBcreate - Create if file doesn't exist, truncate if it does. */
- ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
- }
-
- /* Open file in dos compatibility share mode. */
- fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- ofun, (uint32)createmode, oplock_request, NULL, NULL);
+ /* Create if file doesn't exist, truncate if it does. */
+ create_disposition = FILE_OVERWRITE_IF;
+ }
+
+ /* Open file using ntcreate. */
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ access_mask,
+ share_mode,
+ create_disposition,
+ create_options,
+ fattr,
+ oplock_request,
+ NULL);
if (!fsp) {
END_PROFILE(SMBcreate);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- DEBUG( 2, ( "new file %s\n", fname ) );
- DEBUG( 3, ( "mknew %s fd=%d dmode=%d\n", fname, fsp->fd, createmode ) );
+ DEBUG( 2, ( "reply_mknew: file %s\n", fname ) );
+ DEBUG( 3, ( "reply_mknew %s fd=%d dmode=0x%x\n", fname, fsp->fh->fd, (unsigned int)fattr ) );
END_PROFILE(SMBcreate);
return(outsize);
{
pstring fname;
int outsize = 0;
- int createattr;
+ uint32 fattr = SVAL(inbuf,smb_vwv0);
BOOL bad_path = False;
files_struct *fsp;
int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
START_PROFILE(SMBctemp);
- createattr = SVAL(inbuf,smb_vwv0);
- srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
return ERROR_NT(status);
RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
unix_convert(fname,conn,0,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBctemp);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
tmpfd = smb_mkstemp(fname);
if (tmpfd == -1) {
SMB_VFS_STAT(conn,fname,&sbuf);
- /* Open file in dos compatibility share mode. */
/* We should fail if file does not exist. */
- fsp = open_file_shared(conn,fname,&sbuf,
- SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
- FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
- (uint32)createattr, oplock_request, NULL, NULL);
+ fsp = open_file_ntcreate(conn,fname,&sbuf,
+ FILE_GENERIC_READ | FILE_GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ fattr,
+ oplock_request,
+ NULL);
/* close fd from smb_mkstemp() */
close(tmpfd);
if (!fsp) {
END_PROFILE(SMBctemp);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
}
/* the returned filename is relative to the directory */
s = strrchr_m(fname, '/');
- if (!s)
+ if (!s) {
s = fname;
- else
+ } else {
s++;
+ }
p = smb_buf(outbuf);
#if 0
p += namelen;
outsize = set_message_end(outbuf, p);
- if (oplock_request && lp_fake_oplocks(SNUM(conn)))
+ if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
+ if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
+ }
- DEBUG( 2, ( "created temp file %s\n", fname ) );
- DEBUG( 3, ( "ctemp %s fd=%d umode=%o\n",
- fname, fsp->fd, sbuf.st_mode ) );
+ 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 ) );
END_PROFILE(SMBctemp);
return(outsize);
Check if a user is allowed to rename a file.
********************************************************************/
-static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst)
{
- int smb_action;
- int access_mode;
files_struct *fsp;
+ uint32 fmode;
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
-
- if (S_ISDIR(pst->st_mode))
+ }
+
+ fmode = dos_mode(conn,fname,pst);
+ if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
+ return NT_STATUS_NO_SUCH_FILE;
+ }
+
+ if (S_ISDIR(pst->st_mode)) {
return NT_STATUS_OK;
+ }
/* We need a better way to return NT status codes from open... */
- unix_ERR_class = 0;
- unix_ERR_code = 0;
+ set_saved_ntstatus(NT_STATUS_OK);
- fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
+ fsp = open_file_ntcreate(conn, fname, pst,
+ DELETE_ACCESS,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ NULL);
if (!fsp) {
- NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
- if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- ret = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- return ret;
+ NTSTATUS ret = get_saved_ntstatus();
+ if (!NT_STATUS_IS_OK(ret)) {
+ set_saved_ntstatus(NT_STATUS_OK);
+ return ret;
+ }
+ set_saved_ntstatus(NT_STATUS_OK);
+ return NT_STATUS_ACCESS_DENIED;
}
close_file(fsp,False);
return NT_STATUS_OK;
Check if a user is allowed to delete a file.
********************************************************************/
-static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype, BOOL bad_path)
+NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL bad_path, BOOL check_is_at_open)
{
SMB_STRUCT_STAT sbuf;
- int fmode;
- int smb_action;
- int access_mode;
+ uint32 fattr;
files_struct *fsp;
- DEBUG(10,("can_delete: %s, dirtype = %d\n",
- fname, dirtype ));
+ DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
- if (!CAN_WRITE(conn))
+ if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ }
if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) {
if(errno == ENOENT) {
- if (bad_path)
+ if (bad_path) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- else
+ } else {
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
}
return map_nt_error_from_unix(errno);
}
- fmode = dos_mode(conn,fname,&sbuf);
+ fattr = dos_mode(conn,fname,&sbuf);
/* Can't delete a directory. */
- if (fmode & aDIR)
+ if (fattr & aDIR) {
return NT_STATUS_FILE_IS_A_DIRECTORY;
+ }
+
#if 0 /* JRATEST */
else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
return NT_STATUS_OBJECT_NAME_INVALID;
#endif /* JRATEST */
if (!lp_delete_readonly(SNUM(conn))) {
- if (fmode & aRONLY)
+ if (fattr & aRONLY) {
return NT_STATUS_CANNOT_DELETE;
+ }
}
- if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
+ if ((fattr & ~dirtype) & (aHIDDEN | aSYSTEM)) {
return NT_STATUS_NO_SUCH_FILE;
+ }
- /* We need a better way to return NT status codes from open... */
- unix_ERR_class = 0;
- unix_ERR_code = 0;
-
- fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action);
-
- if (!fsp) {
- NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
- if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
- ret = unix_ERR_ntstatus;
- else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
- ret = NT_STATUS_SHARING_VIOLATION;
- unix_ERR_class = 0;
- unix_ERR_code = 0;
- unix_ERR_ntstatus = NT_STATUS_OK;
- return ret;
+ if (check_is_at_open) {
+ if (!can_delete_file_in_directory(conn, fname)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ } else {
+ /* On open checks the open itself will check the share mode, so
+ don't do it here as we'll get it wrong. */
+
+ /* We need a better way to return NT status codes from open... */
+ set_saved_ntstatus(NT_STATUS_OK);
+
+ fsp = open_file_ntcreate(conn, fname, &sbuf,
+ DELETE_ACCESS,
+ FILE_SHARE_NONE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ NULL);
+
+ if (!fsp) {
+ NTSTATUS ret = get_saved_ntstatus();
+ if (!NT_STATUS_IS_OK(ret)) {
+ set_saved_ntstatus(NT_STATUS_OK);
+ return ret;
+ }
+ set_saved_ntstatus(NT_STATUS_OK);
+ return NT_STATUS_ACCESS_DENIED;
+ }
+ close_file(fsp,False);
}
- close_file(fsp,False);
return NT_STATUS_OK;
}
code.
****************************************************************************/
-NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype, char *name)
{
pstring directory;
pstring mask;
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask))
- mangle_check_cache( mask );
+ if (!rc && mangle_is_mangled(mask,SNUM(conn)))
+ mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
if (!has_wild) {
pstrcat(directory,"/");
pstrcat(directory,mask);
- error = can_delete(directory,conn,dirtype,bad_path);
+ error = can_delete(conn,directory,dirtype,bad_path,False);
if (!NT_STATUS_IS_OK(error))
return error;
count++;
}
} else {
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
+ if (strequal(mask,"????????.???"))
+ pstrcpy(mask,"*");
+
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory, mask, dirtype);
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name, otherwise the short name
We don't implement this yet XXXX
*/
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = NT_STATUS_NO_SUCH_FILE;
-
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
+ SMB_STRUCT_STAT st;
pstring fname;
BOOL sys_direntry = False;
pstrcpy(fname,dname);
+ if (!is_visible_file(conn, directory, dname, &st, True)) {
+ continue;
+ }
+
/* Quick check for "." and ".." */
if (fname[0] == '.') {
if (!fname[1] || (fname[1] == '.' && !fname[2])) {
- if ((dirtype & aDIR)) {
+ if ((dirtype & FILE_ATTRIBUTE_DIRECTORY) && (dirtype & FILE_ATTRIBUTE_SYSTEM)) {
sys_direntry = True;
} else {
continue;
}
}
- if(!mask_match(fname, mask, case_sensitive))
+ if(!mask_match(fname, mask, conn->case_sensitive))
continue;
if (sys_direntry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
+ DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
+ fname, mask));
break;
}
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
- error = can_delete(fname,conn,dirtype,bad_path);
+ error = can_delete(conn,fname,dirtype,bad_path,False);
if (!NT_STATUS_IS_OK(error)) {
continue;
}
count++;
DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
}
{
int outsize = 0;
pstring name;
- int dirtype;
+ uint32 dirtype;
NTSTATUS status;
START_PROFILE(SMBunlink);
dirtype = SVAL(inbuf,smb_vwv0);
- srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBunlink);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
DEBUG(3,("reply_unlink : %s\n",name));
status = unlink_internals(conn, dirtype, name);
- if (!NT_STATUS_IS_OK(status))
+ if (!NT_STATUS_IS_OK(status)) {
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return ERROR_NT(status);
+ }
/*
* Win2k needs a changenotify request response before it will
Fail for readbraw.
****************************************************************************/
-void fail_readraw(void)
+static void fail_readraw(void)
{
pstring errstr;
slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
exit_server(errstr);
}
+#if defined(WITH_SENDFILE)
+/****************************************************************************
+ Fake (read/write) sendfile. Returns -1 on read or write fail.
+****************************************************************************/
+
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
+{
+ ssize_t ret=0;
+
+ /* Paranioa check... */
+ if (nread > bufsize) {
+ fail_readraw();
+ }
+
+ if (nread > 0) {
+ ret = read_file(fsp,buf,startpos,nread);
+ if (ret == -1) {
+ return -1;
+ }
+ }
+
+ /* If we had a short read, fill with zeros. */
+ if (ret < nread) {
+ memset(buf, '\0', nread - ret);
+ }
+
+ if (write_data(smbd_server_fd(),buf,nread) != nread) {
+ return -1;
+ }
+
+ return (ssize_t)nread;
+}
+#endif
+
/****************************************************************************
Use sendfile in readbraw.
****************************************************************************/
void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
- ssize_t mincount, char *outbuf)
+ ssize_t mincount, char *outbuf, int out_buffsize)
{
ssize_t ret=0;
#if defined(WITH_SENDFILE)
/*
- * We can only use sendfile on a non-chained packet and on a file
- * that is exclusively oplocked. reply_readbraw has already checked the length.
+ * We can only use sendfile on a non-chained packet
+ * but we can use on a non-oplocked file. tridge proved this
+ * on a train in Germany :-). JRA.
+ * reply_readbraw has already checked the length.
*/
- if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
- EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
+ if (chain_size ==0 && (nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) && lp_use_sendfile(SNUM(conn)) ) {
DATA_BLOB header;
_smb_setlen(outbuf,nread);
header.length = 4;
header.free = NULL;
- if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
+ if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, nread) == -1) {
+ /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
+ if (errno == ENOSYS) {
+ goto normal_readbraw;
+ }
+
/*
- * Special hack for broken Linux with no 64 bit clean sendfile. If we
- * return ENOSYS then pretend we just got a normal read.
+ * Special hack for broken Linux with no working sendfile. If we
+ * return EINTR we sent the header but not the rest of the data.
+ * Fake this up by doing read/write calls.
*/
- if (errno == ENOSYS)
- goto normal_read;
+ if (errno == EINTR) {
+ /* Ensure we don't do this again. */
+ set_use_sendfile(SNUM(conn), False);
+ DEBUG(0,("send_file_readbraw: sendfile not available. Faking..\n"));
+
+ if (fake_sendfile(fsp, startpos, nread, outbuf + 4, out_buffsize - 4) == -1) {
+ DEBUG(0,("send_file_readbraw: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server("send_file_readbraw fake_sendfile failed");
+ }
+ return;
+ }
DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
}
- normal_read:
+ normal_readbraw:
+
#endif
if (nread > 0) {
Reply to a readbraw (core+ protocol).
****************************************************************************/
-int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
+int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int out_buffsize)
{
- extern struct current_user current_user;
ssize_t maxcount,mincount;
size_t nread = 0;
SMB_OFF_T startpos;
* return a zero length response here.
*/
- if(global_oplock_break) {
- _smb_setlen(header,0);
- if (write_data(smbd_server_fd(),header,4) != 4)
- fail_readraw();
- DEBUG(5,("readbraw - oplock break finished\n"));
- END_PROFILE(SMBreadbraw);
- return -1;
- }
-
fsp = file_fsp(inbuf,smb_vwv0);
if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
/* ensure we don't overrun the packet size */
maxcount = MIN(65535,maxcount);
- if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
- SMB_OFF_T size = fsp->size;
- SMB_OFF_T sizeneeded = startpos + maxcount;
+ if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
+ SMB_STRUCT_STAT st;
+ SMB_OFF_T size = 0;
- if (size < sizeneeded) {
- SMB_STRUCT_STAT st;
- if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
- size = st.st_size;
- if (!fsp->can_write)
- fsp->size = size;
+ if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&st) == 0) {
+ size = st.st_size;
}
- if (startpos >= size)
+ if (startpos >= size) {
nread = 0;
- else
+ } else {
nread = MIN(maxcount,(size - startpos));
+ }
}
#if 0 /* mincount appears to be ignored in a W2K server. JRA. */
nread = 0;
#endif
- DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
- (int)maxcount, (int)mincount, (int)nread ) );
+ DEBUG( 3, ( "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, outbuf);
+ send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
DEBUG(5,("readbraw finished\n"));
END_PROFILE(SMBreadbraw);
return -1;
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
/****************************************************************************
Reply to a lockread (core+ protocol).
****************************************************************************/
START_PROFILE(SMBlockread);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
release_level_2_oplocks_on_change(fsp);
return(outsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
/****************************************************************************
Reply to a read.
****************************************************************************/
START_PROFILE(SMBread);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
data = smb_buf(outbuf) + 3;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBread);
return ERROR_DOS(ERRDOS,ERRlock);
}
Reply to a read and X - possibly using sendfile.
****************************************************************************/
-int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
+int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
{
+ int outsize = 0;
ssize_t nread = -1;
char *data = smb_buf(outbuf);
#if defined(WITH_SENDFILE)
/*
- * We can only use sendfile on a non-chained packet and on a file
- * that is exclusively oplocked.
+ * We can only use sendfile on a non-chained packet
+ * but we can use on a non-oplocked file. tridge proved this
+ * on a train in Germany :-). JRA.
*/
- if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
- lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
+ if (chain_size ==0 && (CVAL(inbuf,smb_vwv0) == 0xFF) && lp_use_sendfile(SNUM(conn)) &&
+ (lp_write_cache_size(SNUM(conn)) == 0) ) {
SMB_STRUCT_STAT sbuf;
DATA_BLOB header;
- if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
return(UNIXERROR(ERRDOS,ERRnoaccess));
if (startpos > sbuf.st_size)
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
SSVAL(outbuf,smb_vwv5,smb_maxcnt);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
SCVAL(outbuf,smb_vwv0,0xFF);
set_message(outbuf,12,smb_maxcnt,False);
header.length = data - outbuf;
header.free = NULL;
- if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
+ if ((nread = SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fh->fd, &header, startpos, smb_maxcnt)) == -1) {
+ /* Returning ENOSYS means no data at all was sent. Do this as a normal read. */
+ if (errno == ENOSYS) {
+ goto normal_read;
+ }
+
/*
- * Special hack for broken Linux with no 64 bit clean sendfile. If we
- * return ENOSYS then pretend we just got a normal read.
+ * Special hack for broken Linux with no working sendfile. If we
+ * return EINTR we sent the header but not the rest of the data.
+ * Fake this up by doing read/write calls.
*/
- if (errno == ENOSYS)
- goto normal_read;
+
+ if (errno == EINTR) {
+ /* Ensure we don't do this again. */
+ set_use_sendfile(SNUM(conn), False);
+ DEBUG(0,("send_file_readX: sendfile not available. Faking..\n"));
+
+ if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
+ len_outbuf - (data-outbuf))) == -1) {
+ DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
+ fsp->fsp_name, strerror(errno) ));
+ exit_server("send_file_readX: fake_sendfile failed");
+ }
+ DEBUG( 3, ( "send_file_readX: fake_sendfile fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ /* Returning -1 here means successful sendfile. */
+ return -1;
+ }
DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
fsp->fsp_name, strerror(errno) ));
DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ /* Returning -1 here means successful sendfile. */
return -1;
}
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
+ outsize = set_message(outbuf,12,nread,False);
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
SSVAL(smb_buf(outbuf),-2,nread);
DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
fsp->fnum, (int)smb_maxcnt, (int)nread ) );
- return nread;
+ /* Returning the number of bytes we want to send back - including header. */
+ return outsize;
}
/****************************************************************************
}
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
set_message(outbuf,12,0,True);
+ if (global_client_caps & CAP_LARGE_READX) {
+ if (SVAL(inbuf,smb_vwv7) == 1) {
+ smb_maxcnt |= (1<<16);
+ }
+ if (smb_maxcnt > BUFFER_SIZE) {
+ DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
+ (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
+ END_PROFILE(SMBreadX);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+ }
+
if(CVAL(inbuf,smb_wct) == 12) {
#ifdef LARGE_SMB_OFF_T
/*
}
- if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadX);
return ERROR_DOS(ERRDOS,ERRlock);
}
- nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
+ if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+ END_PROFILE(SMBreadX);
+ return -1;
+ }
+
+ nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt);
if (nread != -1)
nread = chain_reply(inbuf,outbuf,length,bufsize);
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
tcount = IVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
SCVAL(inbuf,smb_com,SMBwritec);
SCVAL(outbuf,smb_com,SMBwritec);
- if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwritebraw);
return(ERROR_DOS(ERRDOS,ERRlock));
}
SCVAL(outbuf,smb_com,SMBwritebraw);
SSVALS(outbuf,smb_vwv0,-1);
outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+ show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_writebraw: send_smb failed.");
/* Set up outbuf to return the correct return */
outsize = set_message(outbuf,1,0,True);
SCVAL(outbuf,smb_com,SMBwritec);
- SSVAL(outbuf,smb_vwv0,total_written);
if (numtowrite != 0) {
total_written += nwritten;
}
- if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
- sync_file(conn,fsp);
+ SSVAL(outbuf,smb_vwv0,total_written);
+
+ sync_file(conn, fsp, write_through);
DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
return(outsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
/****************************************************************************
Reply to a writeunlock (core+).
****************************************************************************/
START_PROFILE(SMBwriteunlock);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
data = smb_buf(inbuf) + 3;
- if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
- WRITE_LOCK,False)) {
+ if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteunlock);
return ERROR_DOS(ERRDOS,ERRlock);
}
/* The special X/Open SMB protocol handling of
zero length writes is *NOT* done for
this call */
- if(numtowrite == 0)
+ if(numtowrite == 0) {
nwritten = 0;
- else
+ } else {
nwritten = write_file(fsp,data,startpos,numtowrite);
+ }
- if (lp_syncalways(SNUM(conn)))
- sync_file(conn,fsp);
+ sync_file(conn, fsp, False /* write through */);
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
END_PROFILE(SMBwriteunlock);
return outsize;
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
/****************************************************************************
Reply to a write.
****************************************************************************/
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
data = smb_buf(inbuf) + 3;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwrite);
return ERROR_DOS(ERRDOS,ERRlock);
}
} else
nwritten = write_file(fsp,data,startpos,numtowrite);
- if (lp_syncalways(SNUM(conn)))
- sync_file(conn,fsp);
+ sync_file(conn, fsp, False);
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
END_PROFILE(SMBwrite);
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
+ set_message(outbuf,6,0,True);
+
/* Deal with possible LARGE_WRITEX */
- if (large_writeX)
+ if (large_writeX) {
numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
+ }
if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
END_PROFILE(SMBwriteX);
#endif /* LARGE_SMB_OFF_T */
}
- if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteX);
return ERROR_DOS(ERRDOS,ERRlock);
}
done, just a write of zero. To truncate a file,
use SMBwrite. */
- if(numtowrite == 0)
+ if(numtowrite == 0) {
nwritten = 0;
- else
+ } else {
+
+ if (schedule_aio_write_and_X(conn, inbuf, outbuf, length, bufsize,
+ fsp,data,startpos,numtowrite)) {
+ END_PROFILE(SMBwriteX);
+ return -1;
+ }
+
nwritten = write_file(fsp,data,startpos,numtowrite);
+ }
if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
END_PROFILE(SMBwriteX);
return(UNIXERROR(ERRHRD,ERRdiskfull));
}
- set_message(outbuf,6,0,True);
-
SSVAL(outbuf,smb_vwv2,nwritten);
if (large_writeX)
SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
fsp->fnum, (int)numtowrite, (int)nwritten));
- if (lp_syncalways(SNUM(conn)) || write_through)
- sync_file(conn,fsp);
+ sync_file(conn, fsp, write_through);
END_PROFILE(SMBwriteX);
return chain_reply(inbuf,outbuf,length,bufsize);
break;
case 1:
umode = SEEK_CUR;
- res = fsp->pos + startpos;
+ res = fsp->fh->pos + startpos;
break;
case 2:
umode = SEEK_END;
}
if (umode == SEEK_END) {
- if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
+ if((res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,startpos,umode)) == -1) {
if(errno == EINVAL) {
SMB_OFF_T current_pos = startpos;
SMB_STRUCT_STAT sbuf;
- if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
END_PROFILE(SMBlseek);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
current_pos += sbuf.st_size;
if(current_pos < 0)
- res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
+ res = SMB_VFS_LSEEK(fsp,fsp->fh->fd,0,SEEK_SET);
}
}
}
}
- fsp->pos = res;
+ fsp->fh->pos = res;
outsize = set_message(outbuf,2,0,True);
SIVAL(outbuf,smb_vwv0,res);
if (!fsp) {
file_sync_all(conn);
} else {
- sync_file(conn,fsp);
+ sync_file(conn,fsp, True);
}
DEBUG(3,("flush\n"));
int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
- extern struct current_user current_user;
int outsize = 0;
time_t mtime;
int32 eclass = 0, err = 0;
pstrcpy( file_name, fsp->fsp_name);
DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
- fsp->fd, fsp->fnum,
+ fsp->fh->fd, fsp->fnum,
conn->num_files_open));
+ /*
+ * Take care of any time sent in the close.
+ */
+
+ mtime = make_unix_date3(inbuf+smb_vwv1);
+ fsp_set_pending_modtime(fsp, mtime);
+
/*
* close_file() returns the unix errno if an error
* was detected on close - normally this is due to
END_PROFILE(SMBclose);
return (UNIXERROR(ERRHRD,ERRgeneral));
}
-
- /*
- * Now take care of any time sent in the close.
- */
-
- mtime = make_unix_date3(inbuf+smb_vwv1);
-
- /* try and set the date */
- set_filetime(conn, file_name, mtime);
-
}
/* We have a cached error */
START_PROFILE(SMBwriteclose);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
mtime = make_unix_date3(inbuf+smb_vwv4);
data = smb_buf(inbuf) + 1;
- if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
+ if (numtowrite && is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK)) {
END_PROFILE(SMBwriteclose);
return ERROR_DOS(ERRDOS,ERRlock);
}
return(outsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
/****************************************************************************
Reply to a lock.
****************************************************************************/
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count));
+ fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
if (NT_STATUS_V(status)) {
}
DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
- fsp->fd, fsp->fnum, (double)offset, (double)count ) );
+ fsp->fh->fd, fsp->fnum, (double)offset, (double)count ) );
END_PROFILE(SMBunlock);
return(outsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
/****************************************************************************
Reply to a tdis.
****************************************************************************/
smb_setlen(outbuf,outsize - 4);
+ show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_echo: send_smb failed.");
}
SSVAL(outbuf,smb_vwv0,fsp->fnum);
DEBUG(3,("openprint fd=%d fnum=%d\n",
- fsp->fd, fsp->fnum));
+ fsp->fh->fd, fsp->fnum));
END_PROFILE(SMBsplopen);
return(outsize);
}
DEBUG(3,("printclose fd=%d fnum=%d\n",
- fsp->fd,fsp->fnum));
+ fsp->fh->fd,fsp->fnum));
close_err = close_file(fsp,True);
}
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
numtowrite = SVAL(smb_buf(inbuf),1);
data = smb_buf(inbuf) + 3;
code.
****************************************************************************/
-NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
+NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path)
{
- BOOL bad_path = False;
- SMB_STRUCT_STAT sbuf;
int ret= -1;
- unix_convert(directory,conn,0,&bad_path,&sbuf);
+ if(!CAN_WRITE(conn)) {
+ DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn))));
+ errno = EACCES;
+ return map_nt_error_from_unix(errno);
+ }
- if( strchr_m(directory, ':')) {
- return NT_STATUS_NOT_A_DIRECTORY;
+ if (bad_path) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- if (ms_has_wild(directory)) {
- return NT_STATUS_OBJECT_NAME_INVALID;
+ if (!check_name(directory, conn)) {
+ if(errno == ENOENT) {
+ if (bad_path) {
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ } else {
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ }
+ return map_nt_error_from_unix(errno);
}
- if (check_name(directory, conn))
- ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
-
+ ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
if (ret == -1) {
if(errno == ENOENT) {
- if (bad_path)
- return NT_STATUS_OBJECT_PATH_NOT_FOUND;
- else
- return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
return map_nt_error_from_unix(errno);
}
pstring directory;
int outsize;
NTSTATUS status;
+ BOOL bad_path = False;
+ SMB_STRUCT_STAT sbuf;
+
START_PROFILE(SMBmkdir);
- srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
return ERROR_NT(status);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
- status = mkdir_internal(conn, directory);
+ unix_convert(directory,conn,0,&bad_path,&sbuf);
+
+ if( is_ntfs_stream_name(directory)) {
+ DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
+ END_PROFILE(SMBmkdir);
+ return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
+ }
+
+ status = mkdir_internal(conn, directory,bad_path);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
return ERROR_NT(status);
}
+ if (lp_inherit_owner(SNUM(conn))) {
+ /* Ensure we're checking for a symlink here.... */
+ /* We don't want to get caught by a symlink racer. */
+
+ if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) {
+ END_PROFILE(SMBmkdir);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ if(!S_ISDIR(sbuf.st_mode)) {
+ DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory ));
+ END_PROFILE(SMBmkdir);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ change_owner_to_parent(conn, NULL, directory, &sbuf);
+ }
+
outsize = set_message(outbuf,0,0,True);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
{
const char *dname = NULL;
BOOL ret = False;
- void *dirptr = OpenDir(conn, directory, False);
+ long offset = 0;
+ struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
- if(dirptr == NULL)
+ if(dir_hnd == NULL)
return True;
- while((dname = ReadDirName(dirptr))) {
+ while((dname = ReadDirName(dir_hnd, &offset))) {
pstring fullname;
SMB_STRUCT_STAT st;
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
+
/* Construct the full name. */
if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
errno = ENOMEM;
break;
}
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
return ret;
}
BOOL rmdir_internals(connection_struct *conn, char *directory)
{
BOOL ok;
+ SMB_STRUCT_STAT st;
ok = (SMB_VFS_RMDIR(conn,directory) == 0);
if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
*/
BOOL all_veto_files = True;
const char *dname;
- void *dirptr = OpenDir(conn, directory, False);
+ struct smb_Dir *dir_hnd = OpenDir(conn, directory, NULL, 0);
- if(dirptr != NULL) {
- int dirpos = TellDir(dirptr);
- while ((dname = ReadDirName(dirptr))) {
+ if(dir_hnd != NULL) {
+ long dirpos = 0;
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
if(!IS_VETO_PATH(conn, dname)) {
all_veto_files = False;
break;
}
if(all_veto_files) {
- SeekDir(dirptr,dirpos);
- while ((dname = ReadDirName(dirptr))) {
+ RewindDir(dir_hnd,&dirpos);
+ while ((dname = ReadDirName(dir_hnd,&dirpos))) {
pstring fullname;
- SMB_STRUCT_STAT st;
if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
continue;
+ if (!is_visible_file(conn, directory, dname, &st, False))
+ continue;
/* Construct the full name. */
if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
} else if(SMB_VFS_UNLINK(conn,fullname) != 0)
break;
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
/* Retry the rmdir */
ok = (SMB_VFS_RMDIR(conn,directory) == 0);
} else {
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
} else {
errno = ENOTEMPTY;
NTSTATUS status;
START_PROFILE(SMBrmdir);
- srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
return ERROR_NT(status);
RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
unix_convert(directory,conn, NULL,&bad_path,&sbuf);
+ if (bad_path) {
+ END_PROFILE(SMBrmdir);
+ return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ }
if (check_name(directory,conn)) {
dptr_closepath(directory,SVAL(inbuf,smb_pid));
if (*p2 == '?') {
*p2 = *p;
p2++;
+ } else if (*p2 == '*') {
+ pstrcpy(p2, p);
+ break;
} else {
p2++;
}
if (*p2 == '?') {
*p2 = *p;
p2++;
+ } else if (*p2 == '*') {
+ pstrcpy(p2, p);
+ break;
} else {
p2++;
}
(unsigned int)dev, (double)inode, newname ));
}
+/****************************************************************************
+ We need to check if the source path is a parent directory of the destination
+ (ie. a rename of /foo/bar/baz -> /foo/bar/baz/bibble/bobble. If so we must
+ refuse the rename with a sharing violation. Under UNIX the above call can
+ *succeed* if /foo/bar/baz is a symlink to another area in the share. We
+ probably need to check that the client is a Windows one before disallowing
+ this as a UNIX client (one with UNIX extensions) can know the source is a
+ symlink and make this decision intelligently. Found by an excellent bug
+ report from <AndyLiebman@aol.com>.
+****************************************************************************/
+
+static BOOL rename_path_prefix_equal(const char *src, const char *dest)
+{
+ const char *psrc = src;
+ const char *pdst = dest;
+ size_t slen;
+
+ if (psrc[0] == '.' && psrc[1] == '/') {
+ psrc += 2;
+ }
+ if (pdst[0] == '.' && pdst[1] == '/') {
+ pdst += 2;
+ }
+ if ((slen = strlen(psrc)) > strlen(pdst)) {
+ return False;
+ }
+ return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
+}
+
/****************************************************************************
Rename an open file - given an fsp.
****************************************************************************/
-NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
+NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, uint32 attrs, BOOL replace_if_exists)
{
SMB_STRUCT_STAT sbuf;
BOOL bad_path = False;
* filename).
*/
- if((case_sensitive == False) && (case_preserve == True) &&
+ if((conn->case_sensitive == False) && (conn->case_preserve == True) &&
strequal(newname, fsp->fsp_name)) {
char *p;
pstring newname_modified_last_component;
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- error = can_rename(newname,conn,&sbuf);
+ error = can_rename(conn,newname,attrs,&sbuf);
if (dest_exists && !NT_STATUS_IS_OK(error)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
return error;
}
+ if (rename_path_prefix_equal(fsp->fsp_name, newname)) {
+ return NT_STATUS_ACCESS_DENIED;
+ }
+
if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint16 attrs, BOOL replace_if_exists)
+NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, uint32 attrs, BOOL replace_if_exists)
{
pstring directory;
pstring mask;
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask))
- mangle_check_cache( mask );
+ if (!rc && mangle_is_mangled(mask,SNUM(conn)))
+ mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
has_wild = ms_has_wild(mask);
/*
* No wildcards - just process the one file.
*/
- BOOL is_short_name = mangle_is_8_3(name, True);
+ BOOL is_short_name = mangle_is_8_3(name, True, SNUM(conn));
/* Add a terminating '/' to the directory name. */
pstrcat(directory,"/");
DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
directory = %s, newname = %s, last_component_dest = %s, is_8_3 = %d\n",
- case_sensitive, case_preserve, short_case_preserve, directory,
+ conn->case_sensitive, conn->case_preserve, conn->short_case_preserve, directory,
newname, last_component_dest, is_short_name));
/*
* the rename (user is trying to change the case of the
* filename).
*/
- if((case_sensitive == False) &&
- (((case_preserve == True) &&
+ if((conn->case_sensitive == False) &&
+ (((conn->case_preserve == True) &&
(is_short_name == False)) ||
- ((short_case_preserve == True) &&
+ ((conn->short_case_preserve == True) &&
(is_short_name == True))) &&
strcsequal(directory, newname)) {
pstring modified_last_component;
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
- error = can_rename(directory,conn,&sbuf1);
+ error = can_rename(conn,directory,attrs,&sbuf1);
if (!NT_STATUS_IS_OK(error)) {
DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
return NT_STATUS_OBJECT_NAME_COLLISION;
}
+ if (rename_path_prefix_equal(directory, newname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+
if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
directory,newname));
/*
* Wildcards - process each file that matches.
*/
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
pstring destname;
+ if (strequal(mask,"????????.???"))
+ pstrcpy(mask,"*");
+
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory, mask, attrs);
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = NT_STATUS_NO_SUCH_FILE;
/* Was error = NT_STATUS_OBJECT_NAME_NOT_FOUND; - gentest fix. JRA */
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
-
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
pstring fname;
BOOL sysdir_entry = False;
}
}
- if(!mask_match(fname, mask, case_sensitive))
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+ continue;
+
+ if(!mask_match(fname, mask, conn->case_sensitive))
continue;
if (sysdir_entry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
- continue;
+ break;
}
error = NT_STATUS_ACCESS_DENIED;
DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
continue;
}
- error = can_rename(fname,conn,&sbuf1);
+ error = can_rename(conn,fname,attrs,&sbuf1);
if (!NT_STATUS_IS_OK(error)) {
DEBUG(6,("rename %s refused\n", fname));
continue;
continue;
}
+ if (rename_path_prefix_equal(fname, destname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
+
if (!SMB_VFS_RENAME(conn,fname,destname)) {
rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
count++;
}
DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
if (!NT_STATUS_EQUAL(error,NT_STATUS_NO_SUCH_FILE)) {
pstring name;
pstring newname;
char *p;
- uint16 attrs = SVAL(inbuf,smb_vwv0);
+ uint32 attrs = SVAL(inbuf,smb_vwv0);
NTSTATUS status;
START_PROFILE(SMBmv);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
p++;
- p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
status = rename_internals(conn, name, newname, attrs, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
return ERROR_NT(status);
}
Copy a file as part of a reply_copy.
******************************************************************/
-static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
+BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
int count,BOOL target_is_directory, int *err_ret)
{
- int Access,action;
SMB_STRUCT_STAT src_sbuf, sbuf2;
SMB_OFF_T ret=-1;
files_struct *fsp1,*fsp2;
pstring dest;
uint32 dosattrs;
+ uint32 new_create_disposition;
*err_ret = 0;
pstrcpy(dest,dest1);
if (target_is_directory) {
char *p = strrchr_m(src,'/');
- if (p)
+ if (p) {
p++;
- else
+ } else {
p = src;
+ }
pstrcat(dest,"/");
pstrcat(dest,p);
}
- if (!vfs_file_exist(conn,src,&src_sbuf))
+ if (!vfs_file_exist(conn,src,&src_sbuf)) {
return(False);
+ }
- fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
- (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),FILE_ATTRIBUTE_NORMAL,0,&Access,&action);
+ if (!target_is_directory && count) {
+ new_create_disposition = FILE_OPEN;
+ } else {
+ if (!map_open_params_to_ntcreate(dest1,0,ofun,
+ NULL, NULL, &new_create_disposition, NULL)) {
+ return(False);
+ }
+ }
- if (!fsp1)
- return(False);
+ fsp1 = open_file_ntcreate(conn,src,&src_sbuf,
+ FILE_GENERIC_READ,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ INTERNAL_OPEN_ONLY,
+ NULL);
- if (!target_is_directory && count)
- ofun = FILE_EXISTS_OPEN;
+ if (!fsp1) {
+ return(False);
+ }
dosattrs = dos_mode(conn, src, &src_sbuf);
- if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
+ if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) {
ZERO_STRUCTP(&sbuf2);
+ }
- fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
- ofun,dosattrs,0,&Access,&action);
+ fsp2 = open_file_ntcreate(conn,dest,&sbuf2,
+ FILE_GENERIC_WRITE,
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ new_create_disposition,
+ 0,
+ dosattrs,
+ INTERNAL_OPEN_ONLY,
+ NULL);
if (!fsp2) {
close_file(fsp1,False);
}
if ((ofun&3) == 1) {
- if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
+ if(SMB_VFS_LSEEK(fsp2,fsp2->fh->fd,0,SEEK_END) == -1) {
DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
/*
* Stop the copy from occurring.
}
}
- if (src_sbuf.st_size)
+ if (src_sbuf.st_size) {
ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
+ }
close_file(fsp1,False);
/* Ensure the modtime is set correctly on the destination file. */
- fsp2->pending_modtime = src_sbuf.st_mtime;
+ fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
/*
* As we are opening fsp1 read-only we only expect
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
}
- p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, True);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
return ERROR_DOS(ERRSRV,ERRinvdevice);
}
- RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
- RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf);
+ RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf);
rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
unix_convert(newname,conn,0,&bad_path2,&sbuf2);
* Tine Smukavec <valentin.smukavec@hermes.si>.
*/
- if (!rc && mangle_is_mangled(mask))
- mangle_check_cache( mask );
+ if (!rc && mangle_is_mangled(mask, SNUM(conn)))
+ mangle_check_cache( mask, sizeof(pstring)-1, SNUM(conn));
has_wild = ms_has_wild(mask);
exists = vfs_file_exist(conn,directory,NULL);
}
} else {
- void *dirptr = NULL;
+ struct smb_Dir *dir_hnd = NULL;
const char *dname;
pstring destname;
+ if (strequal(mask,"????????.???"))
+ pstrcpy(mask,"*");
+
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dir_hnd = OpenDir(conn, directory, mask, 0);
- if (dirptr) {
+ if (dir_hnd) {
+ long offset = 0;
error = ERRbadfile;
- if (strequal(mask,"????????.???"))
- pstrcpy(mask,"*");
-
- while ((dname = ReadDirName(dirptr))) {
+ while ((dname = ReadDirName(dir_hnd, &offset))) {
pstring fname;
pstrcpy(fname,dname);
- if(!mask_match(fname, mask, case_sensitive))
+ if (!is_visible_file(conn, directory, dname, &sbuf1, False))
+ continue;
+
+ if(!mask_match(fname, mask, conn->case_sensitive))
continue;
error = ERRnoaccess;
count++;
DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
}
- CloseDir(dirptr);
+ CloseDir(dir_hnd);
}
}
return ERROR_DOS(ERRDOS,error);
} else {
if((errno == ENOENT) && (bad_path1 || bad_path2)) {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadpath;
+ set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK);
}
END_PROFILE(SMBcopy);
return(UNIXERROR(ERRDOS,error));
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status, False);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(pathworks_setdir);
return ERROR_NT(status);
}
+ RESOLVE_DFSPATH(newdir, conn, inbuf, outbuf);
+
if (strlen(newdir) == 0) {
ok = True;
} else {
return(outsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_LOCKING
+
/****************************************************************************
Get a lock pid, dealing with large count requests.
****************************************************************************/
Reply to a lockingX request.
****************************************************************************/
-int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
+ int length, int bufsize)
{
files_struct *fsp = file_fsp(inbuf,smb_vwv2);
unsigned char locktype = CVAL(inbuf,smb_vwv3);
int32 lock_timeout = IVAL(inbuf,smb_vwv4);
int i;
char *data;
- BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
+ BOOL large_file_format =
+ (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
BOOL err;
BOOL my_lock_ctx = False;
NTSTATUS status;
data = smb_buf(inbuf);
- if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
+ if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) {
/* we don't support these - and CANCEL_LOCK makes w2k
and XP reboot so I don't really want to be
compatible! (tridge) */
- return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+ return ERROR_DOS(ERRDOS, ERRnoatomiclocks);
+ }
+
+ if (locktype & LOCKING_ANDX_CANCEL_LOCK) {
+ /* Need to make this like a cancel.... JRA. */
+ return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
}
/* Check if this is an oplock break on a file
if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
/* Client can insist on breaking to none. */
BOOL break_to_none = (oplocklevel == 0);
-
- DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
- (unsigned int)oplocklevel, fsp->fnum ));
+ BOOL result;
+
+ DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
+ "for fnum = %d\n", (unsigned int)oplocklevel,
+ fsp->fnum ));
/*
- * Make sure we have granted an exclusive or batch oplock on this file.
+ * Make sure we have granted an exclusive or batch oplock on
+ * this file.
*/
- if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
-no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
-
- /* if this is a pure oplock break request then don't send a reply */
+ if (fsp->oplock_type == 0) {
+ DEBUG(0,("reply_lockingX: Error : oplock break from "
+ "client for fnum = %d (oplock=%d) and no "
+ "oplock granted on this file (%s).\n",
+ fsp->fnum, fsp->oplock_type, fsp->fsp_name));
+
+ /* if this is a pure oplock break request then don't
+ * send a reply */
if (num_locks == 0 && num_ulocks == 0) {
END_PROFILE(SMBlockingX);
return -1;
}
}
- if (remove_oplock(fsp, break_to_none) == False) {
- DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
- fsp->fsp_name ));
+ if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
+ (break_to_none)) {
+ result = remove_oplock(fsp);
+ } else {
+ result = downgrade_oplock(fsp);
}
- /* if this is a pure oplock break request then don't send a reply */
+ if (!result) {
+ DEBUG(0, ("reply_lockingX: error in removing "
+ "oplock on file %s\n", fsp->fsp_name));
+ /* Hmmm. Is this panic justified? */
+ smb_panic("internal tdb error");
+ }
+
+ reply_to_oplock_break_requests(fsp);
+
+ /* if this is a pure oplock break request then don't send a
+ * reply */
if (num_locks == 0 && num_ulocks == 0) {
/* Sanity check - ensure a pure oplock break is not a
chained request. */
if(CVAL(inbuf,smb_vwv0) != 0xff)
- DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
+ DEBUG(0,("reply_lockingX: Error : pure oplock "
+ "break is a chained %d request !\n",
(unsigned int)CVAL(inbuf,smb_vwv0) ));
END_PROFILE(SMBlockingX);
return -1;
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- 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 ));
+ 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(fsp,conn,lock_pid,count,offset);
if (NT_STATUS_V(status)) {
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- 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 ));
+ 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 ));
status = do_lock_spin(fsp,conn,lock_pid, count,offset,
- ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
+ ((locktype & 1) ? READ_LOCK:WRITE_LOCK),
+ &my_lock_ctx);
if (NT_STATUS_V(status)) {
/*
- * Interesting fact found by IFSTEST /t LockOverlappedTest...
- * Even if it's our own lock context, we need to wait here as
- * there may be an unlock on the way.
- * So I removed a "&& !my_lock_ctx" from the following
- * if statement. JRA.
+ * Interesting fact found by IFSTEST /t
+ * LockOverlappedTest... Even if it's our own lock
+ * context, we need to wait here as there may be an
+ * unlock on the way. So I removed a "&&
+ * !my_lock_ctx" from the following if statement. JRA.
*/
- if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+ if ((lock_timeout != 0) &&
+ lp_blocking_locks(SNUM(conn)) &&
+ ERROR_WAS_LOCK_DENIED(status)) {
/*
* A blocking lock was requested. Package up
* this smb into a queued request and push it
* onto the blocking lock queue.
*/
- if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
+ if(push_blocking_lock_request(inbuf, length,
+ lock_timeout, i,
+ lock_pid, offset,
+ count)) {
END_PROFILE(SMBlockingX);
return -1;
}
for(i--; i >= 0; 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);
+ offset = get_lock_offset( data, i, large_file_format,
+ &err);
/*
- * There is no error code marked "stupid client bug".... :-).
+ * There is no error code marked "stupid client
+ * bug".... :-).
*/
if(err) {
END_PROFILE(SMBlockingX);
set_message(outbuf,2,0,True);
- DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
+ 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);
return chain_reply(inbuf,outbuf,length,bufsize);
}
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_ALL
+
/****************************************************************************
Reply to a SMBreadbmpx (read block multiplex) request.
****************************************************************************/
outsize = set_message(outbuf,8,0,True);
CHECK_FSP(fsp,conn);
- CHECK_READ(fsp);
+ if (!CHECK_READ(fsp,inbuf)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
maxcount = SVAL(inbuf,smb_vwv3);
tcount = maxcount;
total_read = 0;
- if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK)) {
END_PROFILE(SMBreadBmpx);
return ERROR_DOS(ERRDOS,ERRlock);
}
if (nread < (ssize_t)N)
tcount = total_read + nread;
- set_message(outbuf,8,nread,False);
+ set_message(outbuf,8,nread+pad,False);
SIVAL(outbuf,smb_vwv0,startpos);
SSVAL(outbuf,smb_vwv2,tcount);
SSVAL(outbuf,smb_vwv6,nread);
SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
+ show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_readbmpx: send_smb failed.");
* Sometimes times are sent as zero - ignore them.
*/
- if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
+ if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
/* Ignore request */
if( DEBUGLVL( 3 ) ) {
dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
}
END_PROFILE(SMBsetattrE);
return(outsize);
- } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
- /* set modify time = to access time if modify time was 0 */
+ } else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
+ /* set modify time = to access time if modify time was unset */
unix_times.modtime = unix_times.actime;
}
/* Set the date on this file */
+ /* Should we set pending modtime here ? JRA */
if(file_utime(conn, fsp->fsp_name, &unix_times)) {
END_PROFILE(SMBsetattrE);
return ERROR_DOS(ERRDOS,ERRnoaccess);
START_PROFILE(SMBwriteBmpx);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
- CHECK_ERROR(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
+ if (HAS_CACHED_ERROR(fsp)) {
+ return(CACHED_ERROR(fsp));
+ }
tcount = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
not an SMBwritebmpx - set this up now so we don't forget */
SCVAL(outbuf,smb_com,SMBwritec);
- if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
+ if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK)) {
END_PROFILE(SMBwriteBmpx);
return(ERROR_DOS(ERRDOS,ERRlock));
}
nwritten = write_file(fsp,data,startpos,numtowrite);
- if(lp_syncalways(SNUM(conn)) || write_through)
- sync_file(conn,fsp);
+ sync_file(conn, fsp, write_through);
if(nwritten < (ssize_t)numtowrite) {
END_PROFILE(SMBwriteBmpx);
if(fsp->wbmpx_ptr != NULL)
wbms = fsp->wbmpx_ptr; /* Use an existing struct */
else
- wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
+ wbms = SMB_MALLOC_P(write_bmpx_struct);
if(!wbms) {
DEBUG(0,("Out of memory in reply_readmpx\n"));
END_PROFILE(SMBwriteBmpx);
if (write_through && tcount==nwritten) {
/* We need to send both a primary and a secondary response */
smb_setlen(outbuf,outsize - 4);
+ show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server("reply_writebmpx: send_smb failed.");
START_PROFILE(SMBwriteBs);
CHECK_FSP(fsp,conn);
- CHECK_WRITE(fsp);
+ if (!CHECK_WRITE(fsp)) {
+ return(ERROR_DOS(ERRDOS,ERRbadaccess));
+ }
tcount = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
nwritten = write_file(fsp,data,startpos,numtowrite);
- if(lp_syncalways(SNUM(conn)) || write_through)
- sync_file(conn,fsp);
+ sync_file(conn, fsp, write_through);
if (nwritten < (ssize_t)numtowrite) {
if(write_through) {
END_PROFILE(SMBwriteBs);
return(ERROR_DOS(ERRHRD,ERRdiskfull));
}
+ wbms->wr_errclass = ERRHRD;
+ wbms->wr_error = ERRdiskfull;
+ wbms->wr_status = NT_STATUS_DISK_FULL;
+ wbms->wr_discard = True;
END_PROFILE(SMBwriteBs);
- return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
+ return -1;
}
/* Increment the total written, if this matches tcount
put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
+ /* Should we check pending modtime here ? JRA */
put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
if (mode & aDIR) {
SIVAL(outbuf,smb_vwv6,0);
SIVAL(outbuf,smb_vwv8,0);
} else {
- uint32 allocation_size = get_allocation_size(fsp, &sbuf);
+ uint32 allocation_size = get_allocation_size(conn,fsp, &sbuf);
SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
SIVAL(outbuf,smb_vwv8,allocation_size);
}