local.h: Removed ununsed SHARE_MODES_XXX defines. Upped SMBD_RELOAD_CHECK
[kai/samba.git] / source3 / smbd / trans2.c
index 38c7031b665b593c5d05a06f2e6ccbbbe6c7cadc..1b199f01ba920e42452eff986ae0b49189893255 100644 (file)
@@ -277,6 +277,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
                    strequal(Connections[cnum].dirpath,"/"));
   BOOL was_8_3;
   int nt_extmode; /* Used for NT connections instead of mode */
+  BOOL needslash = ( Connections[cnum].dirpath[strlen(Connections[cnum].dirpath) -1] != '/');
 
   *fname = 0;
   *out_of_space = False;
@@ -323,7 +324,8 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
            continue;
 
          strcpy(pathreal,Connections[cnum].dirpath);
-         strcat(pathreal,"/");
+          if(needslash)
+           strcat(pathreal,"/");
          strcat(pathreal,fname);
          if (sys_stat(pathreal,&sbuf) != 0) 
            {
@@ -780,7 +782,7 @@ static int call_trans2findnext(char *inbuf, char *outbuf, int length, int bufsiz
     return(ERROR(ERRDOS,ERRnomem));
 
   /* Check that the dptr is valid */
-  if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(params, dptr_num)))
+  if(!(Connections[cnum].dirptr = dptr_fetch_lanman2(SNUM(cnum), params, dptr_num)))
     return(ERROR(ERRDOS,ERRnofiles));
 
   string_set(&Connections[cnum].dirpath,dptr_path(dptr_num));
@@ -916,7 +918,7 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize
       put_dos_date2(pdata,l2_vol_fdateCreation,st.st_ctime);
       SCVAL(pdata,l2_vol_cch,volname_len);
       StrnCpy(pdata+l2_vol_szVolLabel,vname,volname_len);
-      DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime,volname_len,
+      DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",st.st_ctime, volname_len,
               pdata+l2_vol_szVolLabel));
       break;
     }
@@ -939,7 +941,6 @@ static int call_trans2qfsinfo(char *inbuf, char *outbuf, int length, int bufsize
       DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol = %s\n", strlen(vname),
               vname));
       break;
-      break;
     case SMB_QUERY_FS_SIZE_INFO:
       {
        int dfree,dsize,bsize;
@@ -1069,21 +1070,21 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
 
   switch (info_level) 
     {
-    case 1:
-    case 2:
+    case SMB_INFO_STANDARD:
+    case SMB_INFO_QUERY_EA_SIZE:
       data_size = (info_level==1?22:26);
-      put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime);
-      put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
-      put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime);
+      put_dos_date2(pdata,l1_fdateCreation,sbuf.st_ctime); /* create = inode mod */
+      put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime); /* access time */
+      put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
       SIVAL(pdata,l1_cbFile,size);
       SIVAL(pdata,l1_cbFileAlloc,ROUNDUP(size,1024));
       SSVAL(pdata,l1_attrFile,mode);
       SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */
       break;
 
-    case 3:
+    case SMB_INFO_QUERY_EAS_FROM_LIST:
       data_size = 24;
-      put_dos_date2(pdata,0,sbuf.st_ctime);
+      put_dos_date2(pdata,0,sbuf.st_ctime); /* create time = inode mod time */
       put_dos_date2(pdata,4,sbuf.st_atime);
       put_dos_date2(pdata,8,sbuf.st_mtime);
       SIVAL(pdata,12,size);
@@ -1091,7 +1092,7 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       SIVAL(pdata,20,mode);
       break;
 
-    case 4:
+    case SMB_INFO_QUERY_ALL_EAS:
       data_size = 4;
       SIVAL(pdata,0,data_size);
       break;
@@ -1100,12 +1101,20 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       return(ERROR(ERRDOS,ERRbadfunc)); /* os/2 needs this */      
 
     case SMB_QUERY_FILE_BASIC_INFO:
-      data_size = 36;
-      put_long_date(pdata,sbuf.st_ctime);
-      put_long_date(pdata+8,sbuf.st_atime);
-      put_long_date(pdata+16,sbuf.st_mtime);
-      put_long_date(pdata+24,sbuf.st_mtime);
+      data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
+      put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
+      put_long_date(pdata+8,sbuf.st_atime); /* access time */
+      put_long_date(pdata+16,sbuf.st_mtime); /* write time */
+      put_long_date(pdata+24,sbuf.st_mtime); /* change time */
       SIVAL(pdata,32,mode);
+
+      DEBUG(5,("SMB_QFBI - "));
+      DEBUG(5,("create: %s ", ctime(&sbuf.st_ctime)));
+      DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
+      DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
+      DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
+      DEBUG(5,("mode: %x\n", mode));
+
       break;
 
     case SMB_QUERY_FILE_STANDARD_INFO:
@@ -1134,10 +1143,10 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
       break;
 
     case SMB_QUERY_FILE_ALL_INFO:
-      put_long_date(pdata,sbuf.st_ctime);
-      put_long_date(pdata+8,sbuf.st_atime);
-      put_long_date(pdata+16,sbuf.st_mtime);
-      put_long_date(pdata+24,sbuf.st_mtime);
+      put_long_date(pdata,sbuf.st_ctime); /* create time = inode mod time */
+      put_long_date(pdata+8,sbuf.st_atime); /* access time */
+      put_long_date(pdata+16,sbuf.st_mtime); /* write time */
+      put_long_date(pdata+24,sbuf.st_mtime); /* change time */
       SIVAL(pdata,32,mode);
       pdata += 40;
       SIVAL(pdata,0,size);
@@ -1256,29 +1265,33 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
   }
 
   switch (info_level)
+  {
+    case SMB_INFO_STANDARD:
+    case SMB_INFO_QUERY_EA_SIZE:
     {
-    case 1:
+      /* access time */
       tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
-      tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
-      mode = SVAL(pdata,l1_attrFile);
-      size = IVAL(pdata,l1_cbFile);
-      break;
 
-    case 2:
-      tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess);
+      /* write time */
       tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite);
+
       mode = SVAL(pdata,l1_attrFile);
       size = IVAL(pdata,l1_cbFile);
       break;
+    }
 
-    case 3:
+    /* XXXX um, i don't think this is right.
+       it's also not in the cifs6.txt spec.
+     */
+    case SMB_INFO_QUERY_EAS_FROM_LIST:
       tvs.actime = make_unix_date2(pdata+8);
       tvs.modtime = make_unix_date2(pdata+12);
       size = IVAL(pdata,16);
       mode = IVAL(pdata,24);
       break;
 
-    case 4:
+    /* XXXX nor this.  not in cifs6.txt, either. */
+    case SMB_INFO_QUERY_ALL_EAS:
       tvs.actime = make_unix_date2(pdata+8);
       tvs.modtime = make_unix_date2(pdata+12);
       size = IVAL(pdata,16);
@@ -1286,48 +1299,79 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
       break;
 
     case SMB_SET_FILE_BASIC_INFO:
-      pdata += 8;              /* create time */
-      tvs.actime = interpret_long_date(pdata); pdata += 8;
-      tvs.modtime=MAX(interpret_long_date(pdata),interpret_long_date(pdata+8));
-      pdata += 16;
-      mode = IVAL(pdata,0);
+    {
+      /* Ignore create time at offset pdata. */
+
+      /* access time */
+      tvs.actime = interpret_long_date(pdata+8);
+
+      /* write time + changed time, combined. */
+      tvs.modtime=MAX(interpret_long_date(pdata+16),
+                      interpret_long_date(pdata+24));
+
+      /* attributes */
+      mode = IVAL(pdata,32);
       break;
+    }
 
     case SMB_SET_FILE_END_OF_FILE_INFO:
+    {
       if (IVAL(pdata,4) != 0)  /* more than 32 bits? */
-       return(ERROR(ERRDOS,ERRunknownlevel));
+         return(ERROR(ERRDOS,ERRunknownlevel));
       size = IVAL(pdata,0);
       break;
+    }
 
     case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */
     case SMB_SET_FILE_ALLOCATION_INFO: /* not supported yet */
     default:
+    {
       return(ERROR(ERRDOS,ERRunknownlevel));
     }
+  }
 
+  DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
+  DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
+  DEBUG(6,("size: %x "   , size));
+  DEBUG(6,("mode: %x\n"  , mode));
 
+  /* get some defaults (no modifications) if any info is zero. */
   if (!tvs.actime) tvs.actime = st.st_atime;
   if (!tvs.modtime) tvs.modtime = st.st_mtime;
   if (!size) size = st.st_size;
 
-  /* Try and set the times, size and mode of this file - if they are different 
-   from the current values */
-  if(st.st_mtime != tvs.modtime || st.st_atime != tvs.actime) {
+  /* Try and set the times, size and mode of this file -
+     if they are different from the current values
+   */
+  if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
+  {
     if(sys_utime(fname, &tvs)!=0)
+    {
       return(ERROR(ERRDOS,ERRnoaccess));
+    }
   }
-  if(mode != dos_mode(cnum,fname,&st) && dos_chmod(cnum,fname,mode,NULL)) {
+
+  /* check the mode isn't different, before changing it */
+  if (mode != dos_mode(cnum, fname, &st) && dos_chmod(cnum, fname, mode, NULL))
+  {
     DEBUG(2,("chmod of %s failed (%s)\n", fname, strerror(errno)));
     return(ERROR(ERRDOS,ERRnoaccess));
   }
-  if(size != st.st_size) {
-    if (fd == -1) {
+
+  if(size != st.st_size)
+  {
+    if (fd == -1)
+    {
       fd = sys_open(fname,O_RDWR,0);
       if (fd == -1)
-       return(ERROR(ERRDOS,ERRbadpath));
+      {
+        return(ERROR(ERRDOS,ERRbadpath));
+      }
       set_filelen(fd, size);
       close(fd);
-    } else {
+    }
+    else
+    {
       set_filelen(fd, size);
     }
   }