mirror of
https://github.com/obarthel/amiga-smbfs.git
synced 2025-12-08 14:58:35 +00:00
Updated to version 1.158
Please keep in mind that this is still a development version and might surprise you (not necessarily in a good way). Do not let me discourage you to build and test this version, although there will be some risks involved such as data corruption or loss of data.
This commit is contained in:
@@ -2124,3 +2124,54 @@ smbfs 1.155 (24.6.2018)
|
||||
conversion. Fixed. Now I'm curious if this actually manages to
|
||||
make things worse because the SMB server may have reported
|
||||
its "local time" as UTC :-/
|
||||
|
||||
|
||||
smbfs 1.156 (24.6.2018)
|
||||
|
||||
- When processing the entries returned by directory scanning
|
||||
the names of entries would not be processed correctly if
|
||||
these were neither NUL-terminated nor NUL-padded. Thanks go
|
||||
to Tony Wyatt for reporting the problem.
|
||||
|
||||
- When preparing for reading from a file which was not yet
|
||||
ready to be accessed, accessing it could return an error
|
||||
code indicating that the access mode was not correct.
|
||||
Instead of retrying to access the file in read-only mode,
|
||||
the relevant function aborted the access attempt. This has
|
||||
been replaced by asking for read-only access and retrying.
|
||||
Thanks go to Tony Wyatt for reporting the problem.
|
||||
|
||||
- Slightly more robust handling of ExAll() due to the correct
|
||||
size of the the entry being known more early on.
|
||||
|
||||
- Printing the list of ExAll() entries to be returned crashed
|
||||
"reliably" if the number of entries was zero. Thanks go to
|
||||
Hubert Maier for reporting the problem.
|
||||
|
||||
|
||||
smbfs 1.157 (26.6.2018)
|
||||
|
||||
- The ACTION_SETDATE implementation now shows the date/time
|
||||
to be used before it is handed over to the respective SMB
|
||||
commands which change it for a file/directory. Because the
|
||||
different SMB commands (three of them) cannot but change
|
||||
three times (creation, modification, access) we now make
|
||||
sure that all three are initialized by reusing the current
|
||||
state of affairs.
|
||||
|
||||
|
||||
smbfs 1.158 (27.6.2018)
|
||||
|
||||
- Changing the attributes of a file/directory, as in "archived"
|
||||
or "deletable" did not work at all in protocol=core because
|
||||
the original code which handled this used the command
|
||||
SMB_COM_SET_INFORMATION2 in place of SMB_COM_SET_INFORMATION.
|
||||
The command SMB_COM_SET_INFORMATION2 can only change time
|
||||
information but not the attributes. I changed this to use
|
||||
SMB_COM_SET_INFORMATION when necessary.
|
||||
|
||||
- Changing the attributes and/or times of files/directories
|
||||
would have no effect if the server dropped out, the connection
|
||||
had to be reestablished and the file/directory in question had
|
||||
to be reopened because all the attribute and file information
|
||||
was overwritten. Fixed.
|
||||
|
||||
@@ -69,7 +69,7 @@ int smb_proc_mv(struct smb_server *server, const char *opath, const int olen, co
|
||||
int smb_proc_mkdir(struct smb_server *server, const char *path, const int len, int * error_ptr);
|
||||
int smb_proc_rmdir(struct smb_server *server, const char *path, const int len, int * error_ptr);
|
||||
int smb_proc_unlink(struct smb_server *server, const char *path, const int len, int * error_ptr);
|
||||
int smb_proc_trunc(struct smb_server *server, word fid, dword length, int * error_ptr);
|
||||
int smb_proc_trunc(struct smb_server *server, struct smb_dirent *entry, dword length, int * error_ptr);
|
||||
int smb_proc_readdir(struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr);
|
||||
int smb_proc_getattr_core(struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr);
|
||||
int smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry, int * error_ptr);
|
||||
|
||||
+105
-28
@@ -4836,10 +4836,6 @@ Action_SetProtect(
|
||||
|
||||
memset(&st,0,sizeof(st));
|
||||
|
||||
st.atime = -1;
|
||||
st.ctime = -1;
|
||||
st.mtime = -1;
|
||||
|
||||
if((mask & FIBF_DELETE) != 0)
|
||||
{
|
||||
SHOWMSG("write/delete protection enabled");
|
||||
@@ -5378,11 +5374,34 @@ Action_ExamineObject(
|
||||
SHOWVALUE(fib->fib_DirEntryType);
|
||||
SHOWVALUE(fib->fib_NumBlocks);
|
||||
SHOWVALUE(fib->fib_Size);
|
||||
SHOWVALUE(fib->fib_Date.ds_Days);
|
||||
SHOWVALUE(fib->fib_Date.ds_Minute);
|
||||
SHOWVALUE(fib->fib_Date.ds_Tick);
|
||||
SHOWVALUE(fib->fib_DiskKey);
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct DateTime dat;
|
||||
TEXT date[LEN_DATSTRING],time[LEN_DATSTRING];
|
||||
|
||||
memset(&dat,0,sizeof(dat));
|
||||
|
||||
memset(date,0,sizeof(date));
|
||||
memset(time,0,sizeof(time));
|
||||
|
||||
dat.dat_Stamp = fib->fib_Date;
|
||||
dat.dat_Format = FORMAT_DEF;
|
||||
dat.dat_StrDate = date;
|
||||
dat.dat_StrTime = time;
|
||||
|
||||
if(DateToStr(&dat))
|
||||
{
|
||||
D(("days=%ld/minutes=%ld/ticks=%ld: %s %s", fib->fib_Date.ds_Days, fib->fib_Date.ds_Minute, fib->fib_Date.ds_Tick, date, time));
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("could not convert days=%ld/minutes=%ld/ticks=%ld", fib->fib_Date.ds_Days, fib->fib_Date.ds_Minute, fib->fib_Date.ds_Tick));
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
out:
|
||||
|
||||
(*error_ptr) = error;
|
||||
@@ -5554,6 +5573,32 @@ dir_scan_callback_func_exnext(
|
||||
fib->fib_Date.ds_Minute = (seconds % (24 * 60 * 60)) / 60;
|
||||
fib->fib_Date.ds_Tick = (seconds % 60) * TICKS_PER_SECOND;
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct DateTime dat;
|
||||
TEXT date[LEN_DATSTRING],time[LEN_DATSTRING];
|
||||
|
||||
memset(&dat,0,sizeof(dat));
|
||||
|
||||
memset(date,0,sizeof(date));
|
||||
memset(time,0,sizeof(time));
|
||||
|
||||
dat.dat_Stamp = fib->fib_Date;
|
||||
dat.dat_Format = FORMAT_DEF;
|
||||
dat.dat_StrDate = date;
|
||||
dat.dat_StrTime = time;
|
||||
|
||||
if(DateToStr(&dat))
|
||||
{
|
||||
D((" days=%ld/minutes=%ld/ticks=%ld: %s %s", fib->fib_Date.ds_Days, fib->fib_Date.ds_Minute, fib->fib_Date.ds_Tick, date, time));
|
||||
}
|
||||
else
|
||||
{
|
||||
D((" could not convert days=%ld/minutes=%ld/ticks=%ld", fib->fib_Date.ds_Days, fib->fib_Date.ds_Minute, fib->fib_Date.ds_Tick));
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
result = 1;
|
||||
|
||||
out:
|
||||
@@ -5781,9 +5826,16 @@ dir_scan_callback_func_exall(
|
||||
*/
|
||||
ed_size = ec->ec_MinSize + name_len+1;
|
||||
|
||||
if(ec->ec_Next == NULL || ed_size > ec->ec_BytesLeft)
|
||||
/* All entries need to begin on a word-aligned address,
|
||||
* which means that we need to pad the entry size to
|
||||
* a multiple of 2.
|
||||
*/
|
||||
if((ed_size % 2) > 0)
|
||||
ed_size++;
|
||||
|
||||
if(ec->ec_Next == NULL || ec->ec_BytesLeft < ed_size)
|
||||
{
|
||||
D(("Not enough room to return this entry: size %ld > ec->ec_BytesLeft %ld",ed_size,ec->ec_BytesLeft));
|
||||
D(("Not enough room to return this entry: ec->ec_BytesLeft %ld < size %ld",ec->ec_BytesLeft,ed_size));
|
||||
|
||||
/* If this is the first directory entry,
|
||||
* stop the entire process before it has
|
||||
@@ -5814,7 +5866,7 @@ dir_scan_callback_func_exall(
|
||||
ed->ed_Next = NULL;
|
||||
|
||||
/* Copy the name, including the terminating NUL byte. */
|
||||
ed->ed_Name = (STRPTR)(((ULONG)ed) + ec->ec_MinSize);
|
||||
ed->ed_Name = (STRPTR)(&((BYTE *)ed)[ec->ec_MinSize]);
|
||||
memcpy(ed->ed_Name,name,name_len+1);
|
||||
|
||||
/* Fill in as many records as were requested. */
|
||||
@@ -5908,19 +5960,9 @@ dir_scan_callback_func_exall(
|
||||
if(ec->ec_Last != NULL)
|
||||
ec->ec_Last->ed_Next = ed;
|
||||
|
||||
/* All entries need to begin on a word-aligned address,
|
||||
* which means that we need to pad the entry size to
|
||||
* a multiple of 2.
|
||||
*/
|
||||
if((ed_size % 2) > 0)
|
||||
ed_size++;
|
||||
|
||||
/* Note: due to the padding byte the number of bytes
|
||||
* left may become negative.
|
||||
*/
|
||||
ec->ec_BytesLeft -= ed_size;
|
||||
|
||||
ec->ec_Next = ec->ec_BytesLeft > 0 ? (struct ExAllData *)(((ULONG)ed) + ed_size) : NULL;
|
||||
ec->ec_Next = ec->ec_BytesLeft > 0 ? (struct ExAllData *)(&((BYTE *)ed)[ed_size]) : NULL;
|
||||
ec->ec_Last = ed;
|
||||
|
||||
ec->ec_Control->eac_Entries++;
|
||||
@@ -6138,14 +6180,23 @@ Action_ExamineAll(
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
int num_entries_found = 0;
|
||||
|
||||
SHOWVALUE(eac->eac_Entries);
|
||||
|
||||
while(ed != NULL)
|
||||
if(eac->eac_Entries > 0)
|
||||
{
|
||||
SHOWSTRING(ed->ed_Name);
|
||||
do
|
||||
{
|
||||
SHOWSTRING(ed->ed_Name);
|
||||
num_entries_found++;
|
||||
|
||||
ed = ed->ed_Next;
|
||||
ed = ed->ed_Next;
|
||||
}
|
||||
while(ed != NULL);
|
||||
}
|
||||
|
||||
ASSERT( eac->eac_Entries == num_entries_found );
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
@@ -6817,14 +6868,40 @@ Action_SetDate(
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct DateTime dat;
|
||||
TEXT date[LEN_DATSTRING],time[LEN_DATSTRING];
|
||||
|
||||
memset(&dat,0,sizeof(dat));
|
||||
|
||||
memset(date,0,sizeof(date));
|
||||
memset(time,0,sizeof(time));
|
||||
|
||||
dat.dat_Stamp = (*ds);
|
||||
dat.dat_Format = FORMAT_DEF;
|
||||
dat.dat_StrDate = date;
|
||||
dat.dat_StrTime = time;
|
||||
|
||||
if(DateToStr(&dat))
|
||||
{
|
||||
D(("days=%ld/minutes=%ld/ticks=%ld: %s %s", ds->ds_Days, ds->ds_Minute, ds->ds_Tick, date, time));
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("could not convert days=%ld/minutes=%ld/ticks=%ld", ds->ds_Days, ds->ds_Minute, ds->ds_Tick));
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
seconds = (ds->ds_Days * 24 * 60 + ds->ds_Minute) * 60 + (ds->ds_Tick / TICKS_PER_SECOND);
|
||||
|
||||
memset(&st,0,sizeof(st));
|
||||
|
||||
st.atime = -1;
|
||||
st.ctime = -1;
|
||||
st.ctime = 0;
|
||||
st.atime = 0;
|
||||
st.mtime = seconds + UNIX_TIME_OFFSET + get_time_zone_delta();
|
||||
|
||||
D(("mtime = %lu",st.mtime));
|
||||
|
||||
if(smba_setattr(file,&st,NULL,&error) < 0)
|
||||
{
|
||||
error = map_errno_to_ioerr(error);
|
||||
|
||||
+179
-42
@@ -391,7 +391,7 @@ static size_t strnlen(const char * s,size_t max_size)
|
||||
|
||||
if(max_size > 0)
|
||||
{
|
||||
while((*s) != '\0' && --max_size > 0)
|
||||
while((*s) != '\0' && max_size-- > 0)
|
||||
s++;
|
||||
}
|
||||
|
||||
@@ -1368,10 +1368,16 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
|
||||
result = smb_request_ok(server, SMBntcreateX, 34, 0, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
int access_error;
|
||||
|
||||
SHOWMSG("that didn't work; retrying");
|
||||
|
||||
/* Try again in read-only mode? */
|
||||
if ((*error_ptr) == EACCES || ((*error_ptr) == error_check_smb_error && smb_errno(server->rcls,server->err) == EACCES))
|
||||
access_error = (*error_ptr);
|
||||
if(access_error == error_check_smb_error)
|
||||
access_error = smb_errno(server->rcls,server->err);
|
||||
|
||||
if (access_error == EACCES || access_error == EPERM)
|
||||
{
|
||||
if(retry_read_only)
|
||||
{
|
||||
@@ -1466,8 +1472,16 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
|
||||
result = smb_request_ok (server, SMBopen, 7, 0, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
int access_error;
|
||||
|
||||
SHOWMSG("that didn't work; retrying");
|
||||
|
||||
/* Try again in read-only mode? */
|
||||
if ((*error_ptr) == EACCES || ((*error_ptr) == error_check_smb_error && smb_errno(server->rcls,server->err) == EACCES))
|
||||
access_error = (*error_ptr);
|
||||
if(access_error == error_check_smb_error)
|
||||
access_error = smb_errno(server->rcls,server->err);
|
||||
|
||||
if (access_error == EACCES || access_error == EPERM)
|
||||
{
|
||||
if(retry_read_only)
|
||||
{
|
||||
@@ -1497,10 +1511,10 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
|
||||
|
||||
entry->attr = WVAL (buf, smb_vwv1);
|
||||
|
||||
/* This is actually just the mtime value, but we use it
|
||||
/* This is actually just the wtime value, but we use it
|
||||
* in all other places as well.
|
||||
*/
|
||||
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (DVAL (buf, smb_vwv2));
|
||||
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc(DVAL (buf, smb_vwv2)); /* Note: this is UTIME, and should be the server's local time. */
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
@@ -1546,18 +1560,18 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
|
||||
* the server
|
||||
*/
|
||||
int
|
||||
smb_proc_close (struct smb_server *server, word fileid, dword mtime, int * error_ptr)
|
||||
smb_proc_close (struct smb_server *server, word fileid, dword wtime, int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
|
||||
/* 0 and 0xffffffff mean: do not set mtime */
|
||||
if(mtime != 0 && mtime != (dword)0xffffffff)
|
||||
mtime = utc2local (mtime);
|
||||
/* Note: wtime is UTIME, and should be the server's local time. */
|
||||
if(wtime != 0 && wtime != (dword)-1)
|
||||
wtime = utc2local(wtime);
|
||||
|
||||
smb_setup_header (server, SMBclose, 3, 0);
|
||||
WSET (buf, smb_vwv0, fileid);
|
||||
DSET (buf, smb_vwv1, mtime);
|
||||
DSET (buf, smb_vwv1, wtime);
|
||||
|
||||
result = smb_request_ok (server, SMBclose, 0, 0, error_ptr);
|
||||
|
||||
@@ -2052,16 +2066,18 @@ smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const st
|
||||
int
|
||||
smb_proc_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr)
|
||||
{
|
||||
dword local_time = utc2local (entry->ctime);
|
||||
dword local_time;
|
||||
int result;
|
||||
char *p;
|
||||
char *buf = server->transmit_buffer;
|
||||
int path_size;
|
||||
|
||||
local_time = utc2local(entry->ctime); /* Note: this is UTIME, and should be the server's local time. */
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct tm tm_utc;
|
||||
struct tm tm_local;
|
||||
struct tm tm_utc;
|
||||
|
||||
seconds_to_tm(entry->ctime,&tm_utc);
|
||||
|
||||
@@ -2368,7 +2384,7 @@ smb_proc_unlink (struct smb_server *server, const char *path, const int len, int
|
||||
* writes "enough" data to the file.
|
||||
*/
|
||||
int
|
||||
smb_proc_trunc (struct smb_server *server, word fid, dword length, int * error_ptr)
|
||||
smb_proc_trunc (struct smb_server *server, struct smb_dirent *entry, dword length, int * error_ptr)
|
||||
{
|
||||
char *p;
|
||||
char *buf = server->transmit_buffer;
|
||||
@@ -2379,7 +2395,7 @@ smb_proc_trunc (struct smb_server *server, word fid, dword length, int * error_p
|
||||
retry:
|
||||
|
||||
p = smb_setup_header (server, SMBwrite, 5, 3);
|
||||
WSET (buf, smb_vwv0, fid);
|
||||
WSET (buf, smb_vwv0, entry->fileid);
|
||||
WSET (buf, smb_vwv1, 0);
|
||||
DSET (buf, smb_vwv2, length);
|
||||
WSET (buf, smb_vwv4, 0);
|
||||
@@ -2390,7 +2406,10 @@ smb_proc_trunc (struct smb_server *server, word fid, dword length, int * error_p
|
||||
if(result < 0)
|
||||
{
|
||||
if ((*error_ptr) != error_check_smb_error && smb_retry (server))
|
||||
goto retry;
|
||||
{
|
||||
if(reopen_entry(server,entry,NULL) == 0)
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2826,6 +2845,21 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s
|
||||
finfo->len = name_len;
|
||||
|
||||
D(("name = '%s', length=%ld, size=%ld",escape_name(finfo->complete_path),name_len,name_size));
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
seconds_to_tm(finfo->mtime,&tm);
|
||||
LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->ctime,&tm);
|
||||
LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->atime,&tm);
|
||||
LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->wtime,&tm);
|
||||
LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -2937,6 +2971,21 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s
|
||||
finfo->len = name_len;
|
||||
|
||||
D(("name = '%s', length=%ld, size=%ld",escape_name(finfo->complete_path),name_len,name_size));
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct tm tm;
|
||||
|
||||
seconds_to_tm(finfo->mtime,&tm);
|
||||
LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->ctime,&tm);
|
||||
LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->atime,&tm);
|
||||
LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(finfo->wtime,&tm);
|
||||
LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -3380,8 +3429,8 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str
|
||||
|
||||
entry->attr = WVAL (buf, smb_vwv0);
|
||||
|
||||
/* The server only tells us just the mtime */
|
||||
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (DVAL (buf, smb_vwv1));
|
||||
/* The server only tells us just the wtime */
|
||||
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc(DVAL (buf, smb_vwv1)); /* Note: this is UTIME, and should be the server's local time. */
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
@@ -3505,7 +3554,19 @@ smb_query_path_information(struct smb_server *server, const char *path, int len,
|
||||
if (result < 0)
|
||||
{
|
||||
if ((*error_ptr) != error_check_smb_error && smb_retry (server))
|
||||
goto retry;
|
||||
{
|
||||
/* We don't need the file id? */
|
||||
if (len > 0)
|
||||
{
|
||||
goto retry;
|
||||
}
|
||||
/* We do need the file id. */
|
||||
else if (reopen_entry(server,entry,NULL) == 0)
|
||||
{
|
||||
fid = entry->fileid;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
goto out;
|
||||
}
|
||||
@@ -3528,6 +3589,7 @@ smb_query_path_information(struct smb_server *server, const char *path, int len,
|
||||
entry->atime = convert_long_date_to_time_t(p);
|
||||
p += 2 * sizeof(dword); /* LastAccessTime */
|
||||
|
||||
entry->wtime = convert_long_date_to_time_t(p);
|
||||
p += 2 * sizeof(dword); /* LastWriteTime */
|
||||
|
||||
entry->mtime = convert_long_date_to_time_t(p);
|
||||
@@ -3577,8 +3639,13 @@ smb_query_path_information(struct smb_server *server, const char *path, int len,
|
||||
entry_size_quad.High = entry->size_high;
|
||||
|
||||
seconds_to_tm(entry->mtime,&tm);
|
||||
|
||||
LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(entry->ctime,&tm);
|
||||
LOG(("ctime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(entry->atime,&tm);
|
||||
LOG(("atime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
seconds_to_tm(entry->wtime,&tm);
|
||||
LOG(("wtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec));
|
||||
LOG(("size = %s (0x%08lx%08lx)\n",convert_quad_to_string(&entry_size_quad),entry->size_high,entry->size_low));
|
||||
LOG(("attr = 0x%08lx\n",entry->attr));
|
||||
LOG(("name = '%s' (length in bytes = %ld)\n",escape_name(name),file_name_length));
|
||||
@@ -3704,6 +3771,16 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co
|
||||
DSET(p, 8, 0);
|
||||
DSET(p, 12, 0);
|
||||
|
||||
/* Note that we update both mtime and wtime of the
|
||||
* directory and not just mtime because some Samba
|
||||
* versions will end up setting the mtime of the
|
||||
* directory entry to the time given as the wtime
|
||||
* value and ignore the mtime value. This happens
|
||||
* even if the wtime value is given as zero and the
|
||||
* mtime value is non-zero.
|
||||
*/
|
||||
LOG(("entry->mtime = %lu\n",entry->mtime));
|
||||
|
||||
convert_time_t_to_long_date(entry->mtime,&change_time_quad);
|
||||
|
||||
/* Last write time */
|
||||
@@ -3758,16 +3835,36 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co
|
||||
int
|
||||
smb_proc_setattr_core (struct smb_server *server, const char *path, int len, const struct smb_dirent *new_finfo, int * error_ptr)
|
||||
{
|
||||
dword local_time = utc2local (new_finfo->mtime);
|
||||
dword local_time;
|
||||
char *p;
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
int path_size;
|
||||
dword attr;
|
||||
|
||||
/* Don't do anything if mtime is unset. */
|
||||
if(new_finfo->mtime == 0 || new_finfo->mtime == (time_t)-1)
|
||||
return(0);
|
||||
|
||||
if(server->unicode_enabled)
|
||||
path_size = 1 + 2 * (len + 1 + 1);
|
||||
else
|
||||
path_size = 1 + len + 1 + 1;
|
||||
|
||||
ASSERT( smb_payload_size(server, 8, path_size) >= 0 );
|
||||
|
||||
/* We cache these because if the connection needs to be
|
||||
* reestablished, the direntry values will all get
|
||||
* overwritten.
|
||||
*/
|
||||
attr = new_finfo->attr;
|
||||
|
||||
local_time = utc2local(new_finfo->mtime); /* Note: this is UTIME, and should be the server's local time. */
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
struct tm tm_utc;
|
||||
struct tm tm_local;
|
||||
struct tm tm_utc;
|
||||
|
||||
seconds_to_tm(new_finfo->mtime,&tm_utc);
|
||||
|
||||
@@ -3791,17 +3888,10 @@ smb_proc_setattr_core (struct smb_server *server, const char *path, int len, con
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if(server->unicode_enabled)
|
||||
path_size = 1 + 2 * (len + 1 + 1);
|
||||
else
|
||||
path_size = 1 + len + 1 + 1;
|
||||
|
||||
ASSERT( smb_payload_size(server, 8, path_size) >= 0 );
|
||||
|
||||
retry:
|
||||
|
||||
p = smb_setup_header (server, SMBsetatr, 8, path_size);
|
||||
WSET (buf, smb_vwv0, new_finfo->attr);
|
||||
WSET (buf, smb_vwv0, attr);
|
||||
DSET (buf, smb_vwv1, local_time);
|
||||
|
||||
if(server->unicode_enabled)
|
||||
@@ -3826,44 +3916,91 @@ smb_proc_setattr_core (struct smb_server *server, const char *path, int len, con
|
||||
return result;
|
||||
}
|
||||
|
||||
/* smb_proc_setattrE: we do not retry here, because we rely on fid,
|
||||
* which would not be valid after a retry.
|
||||
*/
|
||||
int
|
||||
smb_proc_setattrE (struct smb_server *server, word fid, struct smb_dirent *new_entry, int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
word date, time_value;
|
||||
time_t ctime, atime, mtime;
|
||||
int num_changes;
|
||||
int result;
|
||||
|
||||
/* We cache these because if the connection needs to be
|
||||
* reestablished, the direntry values will all get
|
||||
* overwritten.
|
||||
*/
|
||||
ctime = new_entry->ctime;
|
||||
atime = new_entry->atime;
|
||||
mtime = new_entry->mtime;
|
||||
|
||||
retry:
|
||||
|
||||
smb_setup_header (server, SMBsetattrE, 7, 0);
|
||||
|
||||
WSET (buf, smb_vwv0, fid);
|
||||
|
||||
date_unix2dos (new_entry->ctime, &time_value, &date);
|
||||
num_changes = 0;
|
||||
|
||||
if(ctime != 0 && ctime != (time_t)-1)
|
||||
{
|
||||
date_unix2dos (ctime, &time_value, &date);
|
||||
num_changes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
date = time_value = 0;
|
||||
}
|
||||
|
||||
WSET (buf, smb_vwv1, date);
|
||||
WSET (buf, smb_vwv2, time_value);
|
||||
|
||||
date_unix2dos (new_entry->atime, &time_value, &date);
|
||||
if(atime != 0 && atime != (time_t)-1)
|
||||
{
|
||||
date_unix2dos (atime, &time_value, &date);
|
||||
num_changes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
date = time_value = 0;
|
||||
}
|
||||
|
||||
WSET (buf, smb_vwv3, date);
|
||||
WSET (buf, smb_vwv4, time_value);
|
||||
|
||||
date_unix2dos (new_entry->mtime, &time_value, &date);
|
||||
if(mtime != 0 && mtime != (time_t)-1)
|
||||
{
|
||||
date_unix2dos (mtime, &time_value, &date);
|
||||
num_changes++;
|
||||
}
|
||||
else
|
||||
{
|
||||
date = time_value = 0;
|
||||
}
|
||||
|
||||
WSET (buf, smb_vwv5, date);
|
||||
WSET (buf, smb_vwv6, time_value);
|
||||
|
||||
result = smb_request_ok (server, SMBsetattrE, 0, 0, error_ptr);
|
||||
if (result < 0)
|
||||
/* Do we actually have to change anything at all? */
|
||||
if(num_changes > 0)
|
||||
{
|
||||
if ((*error_ptr) != error_check_smb_error && smb_retry (server))
|
||||
result = smb_request_ok (server, SMBsetattrE, 0, 0, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
if(reopen_entry(server,new_entry,NULL) == 0)
|
||||
goto retry;
|
||||
}
|
||||
if ((*error_ptr) != error_check_smb_error && smb_retry (server))
|
||||
{
|
||||
if(reopen_entry(server,new_entry,NULL) == 0)
|
||||
{
|
||||
fid = new_entry->fileid;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
LOG(("that didn't work.\n"));
|
||||
LOG(("that didn't work.\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -423,36 +423,84 @@ write_attr (smba_file_t * f, int * error_ptr)
|
||||
|
||||
LOG (("file '%s'\n", escape_name(f->dirent.complete_path)));
|
||||
|
||||
LOG(("mtime = %lu\n",f->dirent.mtime));
|
||||
|
||||
if(!f->server->server.prefer_core_protocol && f->server->server.protocol >= PROTOCOL_LANMAN2)
|
||||
{
|
||||
/* Copy these, because make_open() may overwrite them. */
|
||||
time_t mtime = f->dirent.mtime;
|
||||
dword attr = f->dirent.attr;
|
||||
|
||||
LOG(("mtime = %lu\n",f->dirent.mtime));
|
||||
|
||||
result = make_open (f, open_need_fid, open_writable, open_dont_truncate, error_ptr);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
LOG(("mtime = %lu\n",f->dirent.mtime));
|
||||
|
||||
f->dirent.mtime = mtime;
|
||||
f->dirent.attr = attr;
|
||||
|
||||
result = smb_set_file_information (&f->server->server, &f->dirent, NULL, error_ptr);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
f->attr_dirty = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy these, because make_open() may overwrite them. */
|
||||
time_t mtime = f->dirent.mtime;
|
||||
dword attr = f->dirent.attr;
|
||||
|
||||
LOG(("mtime = %lu\n",f->dirent.mtime));
|
||||
|
||||
result = make_open (f, open_dont_need_fid, open_writable, open_dont_truncate, error_ptr);
|
||||
if (result < 0)
|
||||
goto out;
|
||||
|
||||
if (f->dirent.opened && f->server->supports_E)
|
||||
result = smb_proc_setattrE (&f->server->server, f->dirent.fileid, &f->dirent, error_ptr);
|
||||
else
|
||||
LOG(("mtime = %lu\n",f->dirent.mtime));
|
||||
|
||||
f->dirent.mtime = mtime;
|
||||
f->dirent.attr = attr;
|
||||
|
||||
/* If the attributes need to be updated, we cannot used smb_proc_setattrE(),
|
||||
* because that only updates the "time of last write access", but not the
|
||||
* attributes.
|
||||
*/
|
||||
if(f->attr_dirty)
|
||||
{
|
||||
/* Update the attributes and the "time of last write access". */
|
||||
result = smb_proc_setattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
|
||||
}
|
||||
if(result < 0)
|
||||
goto out;
|
||||
|
||||
if (result < 0)
|
||||
{
|
||||
f->attr_time = 0;
|
||||
goto out;
|
||||
}
|
||||
/* Now deal with the creation/access/modification times. */
|
||||
if (f->dirent.opened && f->server->supports_E)
|
||||
{
|
||||
result = smb_proc_setattrE (&f->server->server, f->dirent.fileid, &f->dirent, error_ptr);
|
||||
if(result < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
f->attr_dirty = FALSE;
|
||||
f->attr_dirty = FALSE;
|
||||
}
|
||||
/* Update the times. */
|
||||
else
|
||||
{
|
||||
if (f->dirent.opened && f->server->supports_E)
|
||||
result = smb_proc_setattrE (&f->server->server, f->dirent.fileid, &f->dirent, error_ptr);
|
||||
else
|
||||
result = smb_proc_setattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (result < 0)
|
||||
f->attr_time = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -993,6 +1041,8 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
|
||||
|
||||
if (!f->server->server.prefer_core_protocol && f->server->server.protocol >= PROTOCOL_LANMAN2)
|
||||
{
|
||||
LOG(("using smb_query_path_information\n"));
|
||||
|
||||
if (f->dirent.opened)
|
||||
result = smb_query_path_information (&f->server->server, NULL, 0, f->dirent.fileid, &f->dirent, error_ptr);
|
||||
else
|
||||
@@ -1001,9 +1051,17 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
|
||||
else
|
||||
{
|
||||
if (f->dirent.opened && f->server->supports_E)
|
||||
{
|
||||
LOG(("using smb_proc_getattrE\n"));
|
||||
|
||||
result = smb_proc_getattrE (&f->server->server, &f->dirent, error_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(("using smb_proc_getattr_core\n"));
|
||||
|
||||
result = smb_proc_getattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (result < 0)
|
||||
@@ -1035,40 +1093,46 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
smba_setattr (smba_file_t * f, const smba_stat_t * data, const QUAD * const size, int * error_ptr)
|
||||
smba_setattr (smba_file_t * f, const smba_stat_t * st, const QUAD * const size, int * error_ptr)
|
||||
{
|
||||
BOOL times_changed = FALSE;
|
||||
int result = 0;
|
||||
dword attrs;
|
||||
|
||||
if (data != NULL)
|
||||
if (st != NULL)
|
||||
{
|
||||
if (data->atime != (time_t)-1 && f->dirent.atime != data->atime)
|
||||
if (st->atime != 0 && st->atime != (time_t)-1 && f->dirent.atime != st->atime)
|
||||
{
|
||||
f->dirent.atime = data->atime;
|
||||
LOG(("atime changed to %lu\n",st->atime));
|
||||
|
||||
f->dirent.atime = st->atime;
|
||||
times_changed = TRUE;
|
||||
}
|
||||
|
||||
if (data->ctime != (time_t)-1 && f->dirent.ctime != data->ctime)
|
||||
if (st->ctime != 0 && st->ctime != (time_t)-1 && f->dirent.ctime != st->ctime)
|
||||
{
|
||||
f->dirent.ctime = data->ctime;
|
||||
LOG(("ctime changed to %lu\n",st->ctime));
|
||||
|
||||
f->dirent.ctime = st->ctime;
|
||||
times_changed = TRUE;
|
||||
}
|
||||
|
||||
if (data->mtime != (time_t)-1 && f->dirent.mtime != data->mtime)
|
||||
if (st->mtime != 0 && st->mtime != (time_t)-1 && f->dirent.mtime != st->mtime)
|
||||
{
|
||||
f->dirent.mtime = data->mtime;
|
||||
LOG(("mtime changed to %lu\n",st->mtime));
|
||||
|
||||
f->dirent.mtime = st->mtime;
|
||||
times_changed = TRUE;
|
||||
}
|
||||
|
||||
attrs = f->dirent.attr;
|
||||
|
||||
if (data->is_read_only)
|
||||
if (st->is_read_only)
|
||||
attrs |= SMB_FILE_ATTRIBUTE_READONLY;
|
||||
else
|
||||
attrs &= ~SMB_FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
if (data->is_changed_since_last_archive)
|
||||
if (st->is_changed_since_last_archive)
|
||||
attrs |= SMB_FILE_ATTRIBUTE_ARCHIVE;
|
||||
else
|
||||
attrs &= ~SMB_FILE_ATTRIBUTE_ARCHIVE;
|
||||
@@ -1096,7 +1160,7 @@ smba_setattr (smba_file_t * f, const smba_stat_t * data, const QUAD * const size
|
||||
if(!f->server->server.prefer_core_protocol && f->server->server.protocol >= PROTOCOL_LANMAN2)
|
||||
result = smb_set_file_information (&f->server->server, &f->dirent, size, error_ptr);
|
||||
else
|
||||
result = smb_proc_trunc (&f->server->server, f->dirent.fileid, size->Low, error_ptr);
|
||||
result = smb_proc_trunc (&f->server->server, &f->dirent, size->Low, error_ptr);
|
||||
|
||||
if(result < 0)
|
||||
goto out;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define VERSION 1
|
||||
#define REVISION 155
|
||||
#define DATE "24.6.2018"
|
||||
#define VERS "smbfs 1.155"
|
||||
#define VSTRING "smbfs 1.155 (24.6.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 1.155 (24.6.2018)"
|
||||
#define REVISION 158
|
||||
#define DATE "27.6.2018"
|
||||
#define VERS "smbfs 1.158"
|
||||
#define VSTRING "smbfs 1.158 (27.6.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 1.158 (27.6.2018)"
|
||||
|
||||
@@ -1 +1 @@
|
||||
155
|
||||
158
|
||||
|
||||
Reference in New Issue
Block a user