Commit 28a6a425 authored by Stewart Brodie's avatar Stewart Brodie
Browse files

Another intermediate checkin now that *FileInfo works. I believe this means...

Another intermediate checkin now that *FileInfo works.  I believe this means that nearly all the core functionality is in place for long filename support.

Detail:
  According to Microsoft's documentation, several of the file lookup type
    transactions return the file information in a common format buffer.
    However, what the docs fail to mention, is that in *some* of those
    commands, the time & date fields are reversed.  FindFirst2/FindNext2
    return "date, time, ...".  QPathInformation returns "time, date, ..."
    Grrr.
  There remains a problem with occasional "server error" results from
    some requests.  The reason for these is unknown ... the documentation is
    unhelpful, describing this as "non-specific error code".  Simply repeating
    the command often results in success, sometimes it has to be repeated a
    few times.
  Also fixed filename mapping which caused any 'x' characters at the remote
    server end to be mapped to 'c' at the RISC OS end(!)  This didn't affect
    it before because servers wouldn't return the old module any filenames
    which contained lower case letters (LanManFS used to make the characters
    lower-case itself if the appropriate name style mode was set).
Admin:
  Tested - still seems to work.  Filename completion from LineEditor works
    nicely.  I can open and close files, and read data from them (*Dump
    used to test this).  *Cat, *Ex and *FileInfo all work.  *Dir works.
  Filename character translations to and from RISC OS format need to be
    verified.  The translation table DOS->RISC OS has been ripped out of
    the NFS module so should be pretty accurate.  The reverse mapping has
    not.

Version 1.87, 1.1.1.1.2.3. Tagged as 'LanManFS-1_87-1_1_1_1_2_3'
parent b7d80d6c
......@@ -4,11 +4,11 @@
*
*/
#define Module_MajorVersion_CMHG 1.87
#define Module_MinorVersion_CMHG 1.1.1.1.2.2
#define Module_Date_CMHG 11 Dec 1998
#define Module_MinorVersion_CMHG 1.1.1.1.2.3
#define Module_Date_CMHG 14 Dec 1998
#define Module_MajorVersion "1.87"
#define Module_Version 187
#define Module_MinorVersion "1.1.1.1.2.2"
#define Module_Date "11 Dec 1998"
#define Module_MinorVersion "1.1.1.1.2.3"
#define Module_Date "14 Dec 1998"
......@@ -58,6 +58,8 @@
#include "lmvars.h"
#include "nbip.h"
#include "LanMan_MH.h"
#define EXPORT static
......@@ -1121,7 +1123,7 @@ static bool CallbackSet = false;
/* ---------------- */
int EventFn_handler ( _kernel_swi_regs *R, int pw )
int EventFn_handler ( _kernel_swi_regs *R, void *pw )
{
(void) pw;
......@@ -1131,13 +1133,12 @@ int EventFn_handler ( _kernel_swi_regs *R, int pw )
{
STAT(STA_IP_EVENTS);
CallbackSet = true;
_swi(OS_AddCallBack, _INR(0,1), (int)NBIP_CallbackFn, LM_pw);
_swi(OS_AddCallBack, _INR(0,1), NBIP_CallbackFn, LM_pw);
}
return 1; /* Don't claim, others may wish to know */
}
/* -------------------------------- */
int NBIP_CallbackFn_handler(void)
......@@ -1147,6 +1148,7 @@ int NBIP_CallbackFn_handler(void)
int len, flen;
struct sockaddr sa;
CallbackSet = false;
while (1) /* Do as many packets as we can */
......@@ -1173,6 +1175,14 @@ int NBIP_CallbackFn_handler(void)
return 1;
}
int NBIP_CallbackFn_handler_ctrl(_kernel_swi_regs *r, void *pw)
{
(void) r;
(void) pw;
return NBIP_CallbackFn_handler();
}
/* Exported routines: name service & general =========================== */
/* -------------------- */
......@@ -1497,7 +1507,7 @@ static NBIP_SESSION *ValidatehSession( hSESSION hSess )
/* ------------------- */
static bool ReadData ( int sid, BYTE *where, int len, uint timeout )
static bool ReadData ( int sid, BYTE *where, int len, uint timeout, int flags )
{
uint tstart;
fd_set read_set;
......@@ -1516,11 +1526,14 @@ static bool ReadData ( int sid, BYTE *where, int len, uint timeout )
FD_ZERO(&read_set);
FD_SET( sid, &read_set );
if ( select ( FD_SETSIZE, &read_set, NULL, NULL, &tv ) != 0 )
/* SNB: Changed first param to sid+1 - is more efficient as Internet module
* no longer has to search entire array for set bits */
if ( select ( sid + 1, &read_set, NULL, NULL, &tv ) != 0 )
{
rdlen = recv ( sid, where, len, 0 );
rdlen = recv ( sid, where, len, flags );
if ( rdlen > 0 )
{
if (flags & MSG_PEEK) break;
len -= rdlen;
where += rdlen;
tstart = NB_GetTime();
......@@ -1586,7 +1599,7 @@ static err_t ConnectAttempt ( NBIP_SESSION *pNS, NETNAME *pnnFarEnd )
/* Now get reply */
if ( !ReadData(pNS->sid, DatagramBuf, 4, RECV_TIMEOUT) )
if ( !ReadData(pNS->sid, DatagramBuf, 4, RECV_TIMEOUT, 0) )
return ETIMEOUT;
switch ( DatagramBuf[0] )
......@@ -1598,7 +1611,7 @@ static err_t ConnectAttempt ( NBIP_SESSION *pNS, NETNAME *pnnFarEnd )
return ECONNREJECT;
case NBIP_SESS_RETARGET:
if ( !ReadData( pNS->sid, DatagramBuf, 6, RECV_TIMEOUT) )
if ( !ReadData( pNS->sid, DatagramBuf, 6, RECV_TIMEOUT, 0) )
return EDATALEN;
pNS->rmt_addr.sin_addr = GetIPAddr( DatagramBuf );
pNS->rmt_addr.sin_port = htons(GetShort( DatagramBuf+4 ));
......@@ -1775,6 +1788,19 @@ EXPORT err_t _NB_SendBlockData ( hSESSION hS, BYTE *where, int datalen )
EXPORT err_t _NB_ClearRxQueue ( hSESSION hS )
{
#ifdef LONGNAMES
NBIP_SESSION *pNS;
BYTE buf[4];
pNS = ValidatehSession(hS);
if ( pNS == NULL )
return EBADPARAM;
if ( !ReadData(pNS->sid, buf, 4, 0, MSG_PEEK) )
{
return OK;
}
return ERXNOTREADY;
#endif
(void) hS;
/* ClearRxQueue - not needed? !! */
return OK;
......@@ -1798,7 +1824,7 @@ EXPORT err_t _NB_GetData ( hSESSION hS, BUFCHAIN *pOutData, int timeout )
/* Get header */
retry:
if ( !ReadData(pNS->sid, hdr, 4, timeout) )
if ( !ReadData(pNS->sid, hdr, 4, timeout, 0) )
{
pNS->LinkOK = false;
return ETIMEOUT;
......@@ -1820,7 +1846,7 @@ retry:
while ( GetBlockPointer(&GBP) )
{
if ( !ReadData(pNS->sid, GBP.pBlock, GBP.BlockLen, timeout) )
if ( !ReadData(pNS->sid, GBP.pBlock, GBP.BlockLen, timeout, 0) )
{
pNS->LinkOK = false;
FreeChain(Chain);
......@@ -1851,7 +1877,7 @@ EXPORT err_t _NB_GetBlockData ( hSESSION hS, BYTE *where, int *len_in_out,
/* Get header */
retry:
if ( !ReadData(pNS->sid, hdr, 4, timeout) )
if ( !ReadData(pNS->sid, hdr, 4, timeout, 0) )
{
pNS->LinkOK = false;
return ETIMEOUT;
......@@ -1865,7 +1891,7 @@ retry:
}
len &= 0x1FFFF; /* Max 128K of data */
if ( !ReadData(pNS->sid, where, len, timeout) )
if ( !ReadData(pNS->sid, where, len, timeout, 0) )
{
pNS->LinkOK = false;
return ETIMEOUT;
......
......@@ -29,6 +29,10 @@
* by LONGNAMES macro.
* 08-12-98 sbrodie: Added SMB_Transact2 with full support for setup
* words and the like (present only for LONGNAMES build)
* Several new functions added to support long filename
* compatible versions of some calls, These functions have
* the same name as the function they upgrade with an X2 suffix
* added.
*/
/* A word about 'drive letters':
......@@ -222,6 +226,7 @@ typedef struct
/* And now the sub-commands for SMBtrans2 */
#define TRANSACT2_FINDFIRST 0x01
#define TRANSACT2_FINDNEXT 0x02
#define TRANSACT2_QUERYPATHINFORMATION 0x05
#endif
......@@ -330,7 +335,7 @@ static int DOS_Errs[] =
18, ENOMOREFILES,
2, EFILENOTFOUND,
12, ENOTPRESENT, /* Returned by OS2-Connect from SetAttrib */
50, ENOTPRESENT, /* Returned by W4WG from SetAttrib call */
50, ENOTPRESENT, /* Return~ed by W4WG from SetAttrib call */
110, EFILENOTFOUND, /* Returned by OS2 servers for hidden files */
3, EPATHNOTFOUND,
1, EBADPARAM,
......@@ -474,9 +479,23 @@ static void DumpBuffer(void *ptr, int len)
SMB_RxByteCount.
*/
#ifdef LONGNAMES
//#define RETRYONERROR
//#define PINGFIRST
#endif
static err_t Do_SMB ( hSHARE hS, int cmd, int wct_in, BUFCHAIN pB_in,
BUFCHAIN *ppB_out )
{
#ifdef RETRYONERROR
static const int xmit_size = SMBWORKBUF_SIZE + SMBHDR_SIZE + MAX_WCT * 2;
static BYTE SMB_XmitMemory[SMBWORKBUF_SIZE + SMBHDR_SIZE + MAX_WCT * 2];
int len, retry;
#endif
#ifdef PINGFIRST
BUFCHAIN ping_in;
static SMBHDR ping_hdr;
#endif
err_t res;
int wct_rx;
BUFCHAIN pB_rx;
......@@ -528,9 +547,43 @@ if (cmd == SMBtrans2 && SMB_TxWords[14] == 2) {
}
#endif
/* Send data */
#ifdef RETRYONERROR
len = ChainLen(pB_in);
GetData ( pB_in, SMB_XmitMemory, xmit_size );
retry = 1; /* number of retries to attempt */
do_smb_retry:
pB_in = AddChain ( NULL, SMB_XmitMemory, len );
if ( pB_in == NULL )
return EOUTOFMEM;
#endif
#ifdef PINGFIRST
NB_ClearRxQueue ( hSess );
ping_hdr = SMB_TxHdr;
ping_hdr.command = SMBecho;
ping_hdr.wct = 1;
ping_hdr.tid = 0;
ping_hdr.mid = 2;
ping_in = AddChain ( NULL, "\x01\x00\x02\x00\xA8\x00", 6 );
if (ping_in) ping_in = AddChain( ping_in , &ping_hdr, SMBHDR_SIZE );
if (ping_in) {
res = NB_SendData ( hSess, ping_in );
if ( res != OK )
return res;
res = NB_GetData ( hSess, &pB_rx, REPLY_TIMEOUT );
if (res != OK)
return res;
GetData ( pB_rx, NULL, SMBHDR_SIZE + 6 );
FreeChain ( pB_rx );
}
#endif
/* Send data */
res = NB_ClearRxQueue ( hSess );
if (res != OK) {
debug0("****************** NB_ClearRxQueue says there was stuff pending!!!!!!!!\n");
}
res = NB_SendData ( hSess, pB_in );
if ( res != OK )
......@@ -542,7 +595,7 @@ if (cmd == SMBtrans2 && SMB_TxWords[14] == 2) {
return res;
/* Extract received data */
debug1("Do_SMB - NB_GetData returned %d bytes\n", ChainLen(pB_rx));
debug2("Do_SMB (cmd=0x%x) - NB_GetData returned %d bytes\n", cmd, ChainLen(pB_rx));
SMB_RxHdr.wct = 0;
SMB_RxByteCount = 0;
......@@ -557,6 +610,12 @@ if (cmd == SMBtrans2 && SMB_TxWords[14] == 2) {
{
debug1("Do_SMB: errclass was %d\n", SMB_RxHdr.errclass);
FreeChain(pB_rx);
#ifdef RETRYONERROR
if (SMB_RxHdr.errclass == ERRSRV && SMB_RxHdr.errlo == 1 && SMB_RxHdr.errhi == 0 && retry) {
--retry;
goto do_smb_retry;
}
#endif
return Err_Translate ( SMB_RxHdr.errclass,
SMB_RxHdr.errlo + (SMB_RxHdr.errhi << 8) );
}
......@@ -1097,7 +1156,7 @@ static void FreeShare ( hSHARE hS )
OK; it is acceptable to test either.
*/
static hSHARE GetShare ( char *filename, err_t *pRes )
static hSHARE GetShare ( const char *filename, err_t *pRes )
{
uint tmp;
hSHARE hS;
......@@ -1143,6 +1202,24 @@ static hSHARE GetShare ( char *filename, err_t *pRes )
return hS;
}
/* ---------------------------- */
/* SMB_IsLongNameFS() returns true if the path refers to a share which is using long
filenames. Xlate.c needs to know this in order to determine which set of file
mappings is to be used.
*/
bool SMB_IsLongNameFS( const char * path)
{
err_t e;
hSHARE hS;
hS = GetShare(path, &e);
if (e != OK) return false;
if (hS->use_t2) return true;
return false;
}
/* ---------------------------- */
/* GetShareNoConn() is used to validate a drive letter when
......@@ -1506,6 +1583,50 @@ err_t SMB_Rename ( char *oldpath, char *newpath )
/* --------------------------- */
#ifdef LONGNAMES
/* Microsoft servers not sending them in the documented order */
static void swap_time_date(BYTE *p)
{
BYTE swp;
swp = p[0];
p[0] = p[2];
p[2] = swp;
swp = p[1];
p[1] = p[3];
p[3] = swp;
}
static err_t SMB_GetAttribsX2 (hSHARE hS, char *filename, DOS_ATTRIBS *pAttr )
{
err_t res;
static struct TransactParms tp;
Transact_init(&tp, 1 * 2);
Transact_addsetupword(&tp, TRANSACT2_QUERYPATHINFORMATION);
Transact_addword(&tp, 1); /* information level */
Transact_addlong(&tp, 0L); /* Reserved */
Transact_addstring(&tp, filename+2);
res = SMB_Transact2(hS, &tp);
if (res != OK)
return res;
/*
* OK. Who decided that this call should return data in a different
* format than the FindFirst/FindNext calls. Need to reverse the times
* and dates of the file before calling Xlt to expand them ...
*/
swap_time_date(tp.data_out_buf);
swap_time_date(tp.data_out_buf+4);
swap_time_date(tp.data_out_buf+8);
/* end workaround */
return Xlt_ExpandSearchEntryX2 ( tp.data_out_buf, NULL, NULL, pAttr, NULL);
}
#endif /* LONGNAMES */
/* --------------------------- */
#if 0
err_t SMB_GetAttribs ( char *filename, DOS_ATTRIBS *pAttr )
{
......@@ -1549,6 +1670,11 @@ err_t SMB_GetAttribs ( char *filename, DOS_ATTRIBS *pAttr )
if ( hS == NULL )
return res;
#ifdef LONGNAMES
if (hS->use_t2)
return SMB_GetAttribsX2 (hS, filename, pAttr );
#endif
pB = MkDataBlock ( NULL, DATA_VARBLK, NULL, 0, false );
if ( pB != NULL )
pB = MkDataString ( pB, DATA_ASCII, filename+2 );
......@@ -1691,6 +1817,11 @@ static hSHARE SearchDrive;
#ifdef LONGNAMES
/* Note.
*
* Requesting close_if_done doesn't seem to work (at least on NT 4.0 SP3)
*
*/
enum {
ffirst_FORCE_CLOSE = 1,
ffirst_CLOSE_IF_DONE = 2,
......@@ -2452,7 +2583,8 @@ static err_t SMB_Transact2 ( hSHARE hS, struct TransactParms *pT )
int padbytes; /* Temp variable */
int sc;
debug1("SMB_Transact2: processing (Tid = %#04x)...\n", hS->Tid);
debug2("SMB_Transact2: processing (Tid = %#04x, sub-cmd=%#04x)...\n", hS->Tid,
pT->setup_in[0]);
SMB_TxWords[0] = pT->parms_in_len; /* Total length */
SMB_TxWords[1] = pT->data_in_len; /* Total length */
......@@ -2531,7 +2663,7 @@ static err_t SMB_Transact2 ( hSHARE hS, struct TransactParms *pT )
/* Parm bytes being returned */
pT->data_out_len = min(SMB_RxWords[6], pT->data_out_maxlen);
/* Data bytes being returned */
pT->setup_out_len = min(SMB_RxWords[9], pT->setup_out_maxlen);
pT->setup_out_len = min(SMB_RxWords[9] & 0xFF, pT->setup_out_maxlen);
if (pT->setup_out_len > 0 ) /* Get setup_out */
{
......@@ -2555,7 +2687,7 @@ static err_t SMB_Transact2 ( hSHARE hS, struct TransactParms *pT )
if ( padbytes > 0 )
pBres = GetData(pBres, NULL, padbytes);
pBres = GetData(pBres, pT->data_out_buf, pT->data_out_len);
//DumpBuffer(pT->data_out_buf, pT->data_out_len);
//if (pT->setup_in[0] == 5) DumpBuffer(pT->data_out_buf, pT->data_out_len);
}
if ( pBres == NULL ) { /* Oh no! Techo fear! */
......
......@@ -33,6 +33,7 @@
#include "attr.h"
#include "omni.h"
#include "lmvars.h"
#include "SMB.h"
/* stricmp(): ignore-case string compare ------------------------ */
/* returns 0 if they match, > 0 if s1 > s2, < 0 if s1 < s2 */
......@@ -120,6 +121,10 @@ static uint DMYtoUtime ( int dtime, int ddate )
min = (dtime >> 5) & 63;
hrs = (dtime >> 11) & 31;
debug2("%08x %08x => ", dtime, ddate);
debug3("HH:MM:SS => %02d:%02d:%02d ", hrs, min, sec);
debug3("DD:MM:YY => %02d:%02d:%04d \n", dd, mm, yy + 1980);
/* Calc. no. of days since 1-1-70 */
x = 3652 + (yy*365) + ((yy+3)/4);
x += daycount[mm] + (dd-1);
......@@ -535,6 +540,16 @@ static const char nfs_lookup_table[257]=
""
"";
static const char nfs_lookup_inverse_table[257]=
"________________________________"
"!\"_<__'()_+,-/.0123456789_;<=>?"
"_ABCDEFGHIJKLMNOPQRSTUVWXYZ[_]__"
"`abcdefghijklmnopqrstuvwxyz{|}~_"
""
""
""
"";
void Xlt_NameDOStoROX2 ( char *dst, char *src )
{
int i;
......@@ -549,19 +564,20 @@ void Xlt_NameDOStoROX2 ( char *dst, char *src )
*dst = 0;
}
//void Xlt_NameROtoDOSX2 ( char *dst, char *src )
//{
// int i, c;
//
// for ( i=0; i<255; i++ ) /* No limit on length, except 255 chars */
// {
// c = src[i] & 0xFF;
// if (c == 0) break;
// *dst++ = nfs_lookup_inverse_table[c];
// }
//
// *dst = 0;
//}
static err_t Xlt_NameROtoDOSX2 ( char *dst, char *src )
{
int i, c;
for ( i=0; i<(DOS_NAME_LEN-1); i++ )
{
c = src[i] & 0xFF;
if (c == 0) break;
*dst++ = nfs_lookup_inverse_table[c];
}
*dst = 0;
return OK;
}
#endif
/* --------------------------- */
......@@ -616,6 +632,11 @@ err_t Xlt_ConvertPath ( char *name_in, char *name_out )
}
else if ( name_in[1] == '.' )
{
#ifdef LONGNAMES
if (SMB_IsLongNameFS( name_out )) {
return ( Xlt_NameROtoDOSX2 ( name_out+2, name_in+1 ) );
}
#endif
return ( nameROtoDOS ( name_out+2, name_in+1 ) );
}
......@@ -720,8 +741,8 @@ err_t Xlt_ExpandSearchEntryX2 ( BYTE *entry, char *path_base,
if ( da_out != NULL || ra_out != NULL )
{
da.attr = entry[20];
da.utime = DMYtoUtime ( 0, //entry[8] + (entry[9] << 8),
entry[10] + (entry[11] << 8) );
da.utime = DMYtoUtime ( entry[10] + (entry[11] << 8),
entry[8] + (entry[9] << 8) );
da.length = entry[12] + (entry[13]<<8) +
(entry[14]<<16) + (entry[15]<<24);
......@@ -732,7 +753,6 @@ err_t Xlt_ExpandSearchEntryX2 ( BYTE *entry, char *path_base,
{
Xlt_CnvDOStoRO ( &da, ra_out, CNV_DATETIME+CNV_ATTRIBS );
Attr_GetInfo ( path_base, (char *)entry+23, ra_out );
}
}
......
......@@ -244,8 +244,12 @@ extern err_t SMB_Shutdown ( void );
#ifdef LONGNAMES
/* Need a much larger buffer */
#define SMBWORKBUF_SIZE 16384
extern BYTE SMB_WorkBuf[SMBWORKBUF_SIZE];
#define SMBXMITMEM_SIZE SMBWORKBUF_SIZE
#else
#define SMBWORKBUF_SIZE 1500
#endif
extern BYTE SMB_WorkBuf[SMBWORKBUF_SIZE];
#ifdef LONGNAMES
extern bool SMB_IsLongNameFS( const char * path);
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment