several clientgen mods to support smbwrapper. In particular added
authorAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 1998 12:36:18 +0000 (12:36 +0000)
committerAndrew Tridgell <tridge@samba.org>
Fri, 2 Oct 1998 12:36:18 +0000 (12:36 +0000)
cli_list() for directory listing and expended some other functions a
bit.
(This used to be commit 9bae21abaf3d69a204c6e617f06094303da4da48)

source3/libsmb/clientgen.c

index 0892714b393192b01a840c8d7faa3ebb5fa513eb..81842d920f4f6d2dd4665815fdb95ab888ad2bb5 100644 (file)
@@ -847,7 +847,6 @@ BOOL cli_unlink(struct cli_state *cli, char *fname)
        return True;
 }
 
-
 /****************************************************************************
 create a directory
 ****************************************************************************/
@@ -1259,7 +1258,8 @@ BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t)
 send a qpathinfo call
 ****************************************************************************/
 BOOL cli_qpathinfo(struct cli_state *cli, char *fname, 
-                  time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
+                  time_t *c_time, time_t *a_time, time_t *m_time, 
+                  uint32 *size, int *mode)
 {
        int data_len = 0;
        int param_len = 0;
@@ -1305,6 +1305,9 @@ BOOL cli_qpathinfo(struct cli_state *cli, char *fname,
        if (size) {
                *size = IVAL(rdata, 12);
        }
+       if (mode) {
+               *mode = SVAL(rdata,l1_attrFile);
+       }
 
        if (rdata) free(rdata);
        if (rparam) free(rparam);
@@ -1376,7 +1379,8 @@ BOOL cli_qpathinfo2(struct cli_state *cli, char *fname,
 send a qfileinfo call
 ****************************************************************************/
 BOOL cli_qfileinfo(struct cli_state *cli, int fnum, 
-                  time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
+                  time_t *c_time, time_t *a_time, time_t *m_time, 
+                  uint32 *size, int *mode)
 {
        int data_len = 0;
        int param_len = 0;
@@ -1422,12 +1426,277 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
        if (size) {
                *size = IVAL(rdata, 12);
        }
+       if (mode) {
+               *mode = SVAL(rdata,l1_attrFile);
+       }
 
        if (rdata) free(rdata);
        if (rparam) free(rparam);
        return True;
 }
 
+
+/****************************************************************************
+interpret a long filename structure - this is mostly guesses at the moment
+The length of the structure is returned
+The structure of a long filename depends on the info level. 260 is used
+by NT and 2 is used by OS/2
+****************************************************************************/
+static int interpret_long_filename(int level,char *p,file_info *finfo)
+{
+       extern file_info def_finfo;
+
+       if (finfo)
+               memcpy(finfo,&def_finfo,sizeof(*finfo));
+
+       switch (level)
+               {
+               case 1: /* OS/2 understands this */
+                       if (finfo) {
+                               /* these dates are converted to GMT by make_unix_date */
+                               finfo->ctime = make_unix_date2(p+4);
+                               finfo->atime = make_unix_date2(p+8);
+                               finfo->mtime = make_unix_date2(p+12);
+                               finfo->size = IVAL(p,16);
+                               finfo->mode = CVAL(p,24);
+                               pstrcpy(finfo->name,p+27);
+                       }
+                       return(28 + CVAL(p,26));
+
+               case 2: /* this is what OS/2 uses mostly */
+                       if (finfo) {
+                               /* these dates are converted to GMT by make_unix_date */
+                               finfo->ctime = make_unix_date2(p+4);
+                               finfo->atime = make_unix_date2(p+8);
+                               finfo->mtime = make_unix_date2(p+12);
+                               finfo->size = IVAL(p,16);
+                               finfo->mode = CVAL(p,24);
+                               pstrcpy(finfo->name,p+31);
+                       }
+                       return(32 + CVAL(p,30));
+
+                       /* levels 3 and 4 are untested */
+               case 3:
+                       if (finfo) {
+                               /* these dates are probably like the other ones */
+                               finfo->ctime = make_unix_date2(p+8);
+                               finfo->atime = make_unix_date2(p+12);
+                               finfo->mtime = make_unix_date2(p+16);
+                               finfo->size = IVAL(p,20);
+                               finfo->mode = CVAL(p,28);
+                               pstrcpy(finfo->name,p+33);
+                       }
+                       return(SVAL(p,4)+4);
+                       
+               case 4:
+                       if (finfo) {
+                               /* these dates are probably like the other ones */
+                               finfo->ctime = make_unix_date2(p+8);
+                               finfo->atime = make_unix_date2(p+12);
+                               finfo->mtime = make_unix_date2(p+16);
+                               finfo->size = IVAL(p,20);
+                               finfo->mode = CVAL(p,28);
+                               pstrcpy(finfo->name,p+37);
+                       }
+                       return(SVAL(p,4)+4);
+                       
+               case 260: /* NT uses this, but also accepts 2 */
+                       if (finfo) {
+                               int ret = SVAL(p,0);
+                               int namelen;
+                               p += 4; /* next entry offset */
+                               p += 4; /* fileindex */
+                               
+                               /* these dates appear to arrive in a
+                                  weird way. It seems to be localtime
+                                  plus the serverzone given in the
+                                  initial connect. This is GMT when
+                                  DST is not in effect and one hour
+                                  from GMT otherwise. Can this really
+                                  be right??
+
+                                  I suppose this could be called
+                                  kludge-GMT. Is is the GMT you get
+                                  by using the current DST setting on
+                                  a different localtime. It will be
+                                  cheap to calculate, I suppose, as
+                                  no DST tables will be needed */
+
+                               finfo->ctime = interpret_long_date(p); p += 8;
+                               finfo->atime = interpret_long_date(p); p += 8;
+                               finfo->mtime = interpret_long_date(p); p += 8; p += 8;
+                               finfo->size = IVAL(p,0); p += 8;
+                               p += 8; /* alloc size */
+                               finfo->mode = CVAL(p,0); p += 4;
+                               namelen = IVAL(p,0); p += 4;
+                               p += 4; /* EA size */
+                               p += 2; /* short name len? */
+                               p += 24; /* short name? */        
+                               StrnCpy(finfo->name,p,namelen);
+                               return(ret);
+                       }
+                       return(SVAL(p,0));
+               }
+       
+       DEBUG(1,("Unknown long filename format %d\n",level));
+       return(SVAL(p,0));
+}
+
+
+/****************************************************************************
+  do a directory listing, calling fn on each file found
+  ****************************************************************************/
+int cli_list(struct cli_state *cli,char *Mask,int attribute,void (*fn)(file_info *))
+{
+       int max_matches = 512;
+       /* NT uses 260, OS/2 uses 2. Both accept 1. */
+       int info_level = cli->protocol<PROTOCOL_NT1?1:260; 
+       char *p, *p2;
+       pstring mask;
+       file_info finfo;
+       int i;
+       char *dirlist = NULL;
+       int dirlist_len = 0;
+       int total_received = 0;
+       BOOL First = True;
+       int ff_resume_key = 0;
+       int ff_searchcount=0;
+       int ff_eos=0;
+       int ff_lastname=0;
+       int ff_dir_handle=0;
+       int loop_count = 0;
+       char *rparam=NULL, *rdata=NULL;
+       int param_len, data_len;
+       
+       uint16 setup;
+       pstring param;
+       
+       pstrcpy(mask,Mask);
+       
+       while (ff_eos == 0) {
+               loop_count++;
+               if (loop_count > 200) {
+                       DEBUG(0,("Error: Looping in FIND_NEXT??\n"));
+                       break;
+               }
+
+               param_len = 12+strlen(mask)+1;
+
+               if (First) {
+                       setup = TRANSACT2_FINDFIRST;
+                       SSVAL(param,0,attribute); /* attribute */
+                       SSVAL(param,2,max_matches); /* max count */
+                       SSVAL(param,4,8+4+2);   /* resume required + close on end + continue */
+                       SSVAL(param,6,info_level); 
+                       SIVAL(param,8,0);
+                       pstrcpy(param+12,mask);
+               } else {
+                       setup = TRANSACT2_FINDNEXT;
+                       SSVAL(param,0,ff_dir_handle);
+                       SSVAL(param,2,max_matches); /* max count */
+                       SSVAL(param,4,info_level); 
+                       SIVAL(param,6,ff_resume_key); /* ff_resume_key */
+                       SSVAL(param,10,8+4+2);  /* resume required + close on end + continue */
+                       pstrcpy(param+12,mask);
+
+                       DEBUG(5,("hand=0x%X resume=%d ff_lastname=%d mask=%s\n",
+                                ff_dir_handle,ff_resume_key,ff_lastname,mask));
+               }
+
+               if (!cli_send_trans(cli, SMBtrans2, 
+                                   NULL, 0,                /* Name, length */
+                                   -1, 0,                  /* fid, flags */
+                                   &setup, 1, 0,           /* setup, length, max */
+                                   param, param_len, 10,   /* param, length, max */
+                                   NULL, 0, 
+                                   cli->max_xmit /* data, length, max */
+                                   )) {
+                       return -1;
+               }
+
+               if (!cli_receive_trans(cli, SMBtrans2, 
+                                      &rparam, &param_len,
+                                      &rdata, &data_len)) {
+                       return -1;
+               }
+
+               /* parse out some important return info */
+               p = rparam;
+               if (First) {
+                       ff_dir_handle = SVAL(p,0);
+                       ff_searchcount = SVAL(p,2);
+                       ff_eos = SVAL(p,4);
+                       ff_lastname = SVAL(p,8);
+               } else {
+                       ff_searchcount = SVAL(p,0);
+                       ff_eos = SVAL(p,2);
+                       ff_lastname = SVAL(p,6);
+               }
+
+               if (ff_searchcount == 0) 
+                       break;
+
+               /* point to the data bytes */
+               p = rdata;
+
+               /* we might need the lastname for continuations */
+               if (ff_lastname > 0) {
+                       switch(info_level)
+                               {
+                               case 260:
+                                       ff_resume_key =0;
+                                       StrnCpy(mask,p+ff_lastname,
+                                               data_len-ff_lastname);
+                                       break;
+                               case 1:
+                                       pstrcpy(mask,p + ff_lastname + 1);
+                                       ff_resume_key = 0;
+                                       break;
+                               }
+               } else {
+                       pstrcpy(mask,"");
+               }
+  
+               /* and add them to the dirlist pool */
+               dirlist = Realloc(dirlist,dirlist_len + data_len);
+
+               if (!dirlist) {
+                       DEBUG(0,("Failed to expand dirlist\n"));
+                       break;
+               }
+
+               /* put in a length for the last entry, to ensure we can chain entries 
+                  into the next packet */
+               for (p2=p,i=0;i<(ff_searchcount-1);i++)
+                       p2 += interpret_long_filename(info_level,p2,NULL);
+               SSVAL(p2,0,data_len - PTR_DIFF(p2,p));
+
+               /* grab the data for later use */
+               memcpy(dirlist+dirlist_len,p,data_len);
+               dirlist_len += data_len;
+
+               total_received += ff_searchcount;
+
+               if (rdata) free(rdata); rdata = NULL;
+               if (rparam) free(rparam); rparam = NULL;
+               
+               DEBUG(3,("received %d entries (eos=%d resume=%d)\n",
+                        ff_searchcount,ff_eos,ff_resume_key));
+
+               First = False;
+       }
+
+       for (p=dirlist,i=0;i<total_received;i++) {
+               p += interpret_long_filename(info_level,p,&finfo);
+               fn(&finfo);
+       }
+
+       /* free up the dirlist buffer */
+       if (dirlist) free(dirlist);
+       return(total_received);
+}
+
+
 /****************************************************************************
 Send a SamOEMChangePassword command
 ****************************************************************************/