client.c: New print queue query code from Jeff C. Foster " <jfoste@wgc.woodward...
authorSamba Release Account <samba-bugs@samba.org>
Tue, 1 Jul 1997 01:19:13 +0000 (01:19 +0000)
committerSamba Release Account <samba-bugs@samba.org>
Tue, 1 Jul 1997 01:19:13 +0000 (01:19 +0000)
ipc.c: Added code for returning restricted lists of servers.
loadparm.c: Changed default for force create mode to 000.
Changed default maxmux to 50 to comply with NT.
locking.c: Fixed silly crash bug with slow share mode code.
nameannounce.c: Added code for returning restricted lists of servers.
namedbserver.c: Added code for returning restricted lists of servers.
nameelect.c: Added code for returning restricted lists of servers.
namework.c: Added code for returning restricted lists of servers.
nmbsync.c: Added code for returning restricted lists of servers.
server.c: Added quota fix Albrecht Gebhardt <albrecht.gebhardt@uni-klu.ac.at>
smb.h: Added define for COPYBUF_SIZE.
system.c: Rename across filesystems Patch from Warren Birnbaum
<warrenb@hpcvscdp.cv.hp.com>
util.c: Minor fix for warning.

13 files changed:
source/client/client.c
source/include/smb.h
source/lib/system.c
source/lib/util.c
source/locking/locking.c
source/nameannounce.c
source/namedbserver.c
source/nameelect.c
source/namework.c
source/nmbsync.c
source/param/loadparm.c
source/smbd/ipc.c
source/smbd/server.c

index 873c88e88c4705094bb8b6b916213e2faf18fb43..c7e00c4515028472e71f6ca389fe495619f737cd 100644 (file)
@@ -1651,7 +1651,7 @@ static void cmd_more(void)
 
   strcpy(rname,cur_dir);
   strcat(rname,"\\");
-  sprintf(tmpname,"%s/smbmore.%d",tmpdir(),getpid());
+  sprintf(tmpname,"%s/smbmore.%d",tmpdir(),(int)getpid());
   strcpy(lname,tmpname);
 
   if (!next_token(NULL,rname+strlen(rname),NULL)) {
@@ -2452,7 +2452,8 @@ static void cmd_print(char *inbuf,char *outbuf )
 }
 
 /****************************************************************************
-show a print queue
+show a print queue - this is deprecated as it uses the old smb that
+has limited support - the correct call is the cmd_p_queue_4() after this.
 ****************************************************************************/
 static void cmd_queue(char *inbuf,char *outbuf )
 {
@@ -2513,6 +2514,119 @@ static void cmd_queue(char *inbuf,char *outbuf )
 }
 
 
+/****************************************************************************
+show information about a print queue
+****************************************************************************/
+static void cmd_p_queue_4(char *inbuf,char *outbuf )
+{
+  char *rparam = NULL;
+  char *rdata = NULL;
+  char *p;
+  int rdrcnt, rprcnt;
+  pstring param;
+  int result_code=0;
+
+  if (!connect_as_printer)
+    {
+      DEBUG(0,("WARNING: You didn't use the -P option to smbclient.\n"));
+      DEBUG(0,("Trying to print without -P may fail\n"));
+    }
+  
+  bzero(param,sizeof(param));
+
+  p = param;
+  SSVAL(p,0,76);                        /* API function number 76 (DosPrintJobEnum) */
+  p += 2;
+  strcpy(p,"zWrLeh");                   /* parameter description? */
+  p = skip_string(p,1);
+  strcpy(p,"WWzWWDDzz");                /* returned data format */
+  p = skip_string(p,1);
+  strcpy(p,strrchr(service,'\\')+1);    /* name of queue */
+  p = skip_string(p,1);
+  SSVAL(p,0,2);                 /* API function level 2, PRJINFO_2 data structure */
+  SSVAL(p,2,1000);                      /* size of bytes of returned data buffer */
+  p += 4;
+  strcpy(p,"");                         /* subformat */
+  p = skip_string(p,1);
+
+  DEBUG(1,("Calling DosPrintJobEnum()...\n"));
+  if( call_api(PTR_DIFF(p,param), 0,
+               10, 4096,
+               &rprcnt, &rdrcnt,
+               param, NULL,
+               &rparam, &rdata) )
+    {
+      int converter;
+      result_code = SVAL(rparam,0);
+      converter = SVAL(rparam,2);             /* conversion factor */
+
+      DEBUG(2,("returned %d bytes of parameters, %d bytes of data, %d records\n", rprcnt, rdrcnt, SVAL(rparam,4) ));
+
+      if (result_code == 0)                   /* if no error, */
+        {
+          int i;
+          uint16 JobId;
+          uint16 Priority;
+          uint32 Size;
+          char *UserName;
+          char *JobName;
+          char *JobTimeStr;
+          time_t JobTime;
+          char PrinterName[20];
+             
+          strcpy(PrinterName,strrchr(service,'\\')+1);       /* name of queue */
+          strlower(PrinterName);                             /* in lower case */
+
+          p = rdata;                          /* received data */
+          for( i = 0; i < SVAL(rparam,4); ++i)
+            {
+              JobId = SVAL(p,0);
+              Priority = SVAL(p,2);
+              UserName = fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt);
+              strlower(UserName);
+              Priority = SVAL(p,2);
+              JobTime = make_unix_date3( p + 12);
+              JobTimeStr = asctime(LocalTime( &JobTime));
+              Size = IVAL(p,16);
+              JobName = fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt);
+            
+
+              printf("%s-%u    %s    priority %u   %s    %s   %u bytes\n", 
+               PrinterName, JobId, UserName,
+                Priority, JobTimeStr, JobName, Size);
+   
+#if 0 /* DEBUG code */
+              printf("Job Id: \"%u\"\n", SVAL(p,0));
+              printf("Priority: \"%u\"\n", SVAL(p,2));
+            
+              printf("User Name: \"%s\"\n", fix_char_ptr(SVAL(p,4), converter, rdata, rdrcnt) );
+              printf("Position: \"%u\"\n", SVAL(p,8));
+              printf("Status: \"%u\"\n", SVAL(p,10));
+            
+              JobTime = make_unix_date3( p + 12);
+              printf("Submitted: \"%s\"\n", asctime(LocalTime(&JobTime)));
+              printf("date: \"%u\"\n", SVAL(p,12));
+
+              printf("Size: \"%u\"\n", SVAL(p,16));
+              printf("Comment: \"%s\"\n", fix_char_ptr(SVAL(p,20), converter, rdata, rdrcnt) );
+              printf("Document: \"%s\"\n", fix_char_ptr(SVAL(p,24), converter, rdata, rdrcnt) );
+#endif /* DEBUG CODE */ 
+              p += 28;
+            }
+        }
+    }
+  else                  /* call_api() failed */
+    {
+      printf("Failed, error = %d\n", result_code);
+    }
+
+  /* If any parameters or data were returned, free the storage. */
+  if(rparam) free(rparam);
+  if(rdata) free(rdata);
+
+  return;
+}
+
 /****************************************************************************
 show information about a print queue
 ****************************************************************************/
@@ -3870,6 +3984,7 @@ struct
   {"md",cmd_mkdir,"<directory> make a directory"},
   {"rmdir",cmd_rmdir,"<directory> remove a directory"},
   {"rd",cmd_rmdir,"<directory> remove a directory"},
+  {"pq",cmd_p_queue_4,"enumerate the print queue"},
   {"prompt",cmd_prompt,"toggle prompting for filenames for mget and mput"},  
   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput"},  
   {"translate",cmd_translate,"toggle text translation for printing"},  
index 2dc2624566fbfcab72192148a59d41069ac029a9..ddbd05792dfab7984ef9245b33da1c8ed2725b41 100644 (file)
@@ -912,4 +912,7 @@ enum case_handling {CASE_LOWER,CASE_UPPER};
 /* Default client code page - 850 - Western European */
 #define DEFAULT_CLIENT_CODE_PAGE 850
 
+/* Size of buffer to use when moving files across filesystems. */
+#define COPYBUF_SIZE (8*1024)
+
 /* _SMB_H */
index 521f5e304ce94155cb414c3d2dfcad25e31b3de3..ea86e9ccaabc239bc972a1f7f91d1838dfa01f11 100644 (file)
@@ -197,15 +197,130 @@ int sys_utime(char *fname,struct utimbuf *times)
   return(utime(dos_to_unix(fname,False),times));
 }
 
+/*********************************************************
+for rename across filesystems Patch from Warren Birnbaum 
+<warrenb@hpcvscdp.cv.hp.com>
+**********************************************************/
+
+static int
+copy_reg (const char *source, const char *dest)
+{
+  struct stat source_stats;
+  int ifd;
+  int full_write();
+  int safe_read();
+  int ofd;
+  char *buf;
+  int len;                      /* Number of bytes read into `buf'. */
+
+  lstat (source, &source_stats);
+  if (!S_ISREG (source_stats.st_mode))
+    {
+      return 1;
+    }
+
+  if (unlink (dest) && errno != ENOENT)
+    {
+      return 1;
+    }
+
+  if((ifd = open (source, O_RDONLY, 0)) < 0)
+    {
+      return 1;
+    }
+  if((ofd = open (dest, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0 )
+    {
+      close (ifd);
+      return 1;
+    }
+
+  if((buf = malloc( COPYBUF_SIZE )) == NULL)
+    {
+      close (ifd);  
+      close (ofd);  
+      unlink (dest);
+      return 1;
+    }
+
+  while ((len = read(ifd, buf, COPYBUF_SIZE)) > 0)
+    {
+      if (write_data(ofd, buf, len) < 0)
+        {
+          close (ifd);
+          close (ofd);
+          unlink (dest);
+          free(buf);
+          return 1;
+        }
+    }
+  free(buf);
+  if (len < 0)
+    {
+      close (ifd);
+      close (ofd);
+      unlink (dest);
+      return 1;
+    }
+
+  if (close (ifd) < 0)
+    {
+      close (ofd);
+      return 1;
+    }
+  if (close (ofd) < 0)
+    {
+      return 1;
+    }
+
+  /* chown turns off set[ug]id bits for non-root,
+     so do the chmod last.  */
+
+  /* Try to copy the old file's modtime and access time.  */
+  {
+    struct utimbuf tv;
+
+    tv.actime = source_stats.st_atime;
+    tv.modtime = source_stats.st_mtime;
+    if (utime (dest, &tv))
+      {
+        return 1;
+      }
+  }
+
+  /* Try to preserve ownership.  For non-root it might fail, but that's ok.
+     But root probably wants to know, e.g. if NFS disallows it.  */
+  if (chown (dest, source_stats.st_uid, source_stats.st_gid)
+      && (errno != EPERM))
+    {
+      return 1;
+    }
+
+  if (chmod (dest, source_stats.st_mode & 07777))
+    {
+      return 1;
+    }
+  unlink (source);
+  return 0;
+}
+
 /*******************************************************************
 for rename()
 ********************************************************************/
 int sys_rename(char *from, char *to)
 {
+    int rcode;  
     pstring zfrom, zto;
+
     strcpy (zfrom, dos_to_unix (from, False));
     strcpy (zto, dos_to_unix (to, False));
-    return rename (zfrom, zto);
+    rcode = rename (zfrom, zto);
+
+    if (errno == EXDEV) 
+      {
+        /* Rename across filesystems needed. */
+        rcode = copy_reg (zfrom, zto);        
+      }
+    return rcode;
 }
 
 /*******************************************************************
index def84bf5ae04fa6f95f947cb846eb7b787916585..9ebfdca88ea87c0c8bbbd27d995d0f2d336cf366 100644 (file)
@@ -3306,7 +3306,7 @@ BOOL process_exists(int pid)
     fstring s;
     if (!tested) {
       tested = True;
-      sprintf(s,"/proc/%05d",getpid());
+      sprintf(s,"/proc/%05d",(int)getpid());
       ok = file_exist(s,NULL);
     }
     if (ok) {
index 2c392e924d2e98eb5f946ad8855c1bb9ca0385c3..64dc207cb7dd2756bf146b3c6527dd4829491424 100644 (file)
@@ -893,7 +893,8 @@ it left a share mode entry with mode 0x%X in share file %s\n",
     DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
              fname));
     if(*old_shares)
-      free((char *)old_shares);
+      free((char *)*old_shares);
+    *old_shares = 0;
     if(buf)
       free(buf);
     delete_share_file(cnum, fname);
@@ -910,7 +911,8 @@ it left a share mode entry with mode 0x%X in share file %s\n",
       DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
 position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
       if(*old_shares)
-        free((char *)old_shares);
+        free((char *)*old_shares);
+      *old_shares = 0;
       if(buf)
         free(buf);
       return 0;
@@ -933,7 +935,8 @@ position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
       DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
 mode file %s (%s)\n", fname, strerror(errno)));
       if(*old_shares)
-        free((char *)old_shares);
+        free((char *)*old_shares);
+      *old_shares = 0;
       if(buf)
         free(buf);
       return 0;
@@ -944,7 +947,8 @@ mode file %s (%s)\n", fname, strerror(errno)));
       DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
 mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
       if(*old_shares)
-        free((char *)old_shares);
+        free((char *)*old_shares);
+      *old_shares = 0;
       if(buf)
         free(buf);
       return 0;
index 899fcd7e3b572c1240f17446c4e8ee17a2111d1d..6e7e445e4b194d63063f2b9c3c1972ac441f5985 100644 (file)
@@ -165,7 +165,7 @@ void do_announce_host(int command,
        CVAL(p,21) = MAJOR_VERSION; /* major version */
        CVAL(p,22) = MINOR_VERSION; /* minor version */
 
-       SIVAL(p,23,server_type);
+       SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
        /* browse version: got from NT/AS 4.00  - Value defined in smb.h (JHT)*/
        SSVAL(p,27,BROWSER_ELECTION_VERSION);
        SSVAL(p,29,BROWSER_CONSTANT); /* browse signature */
index 8cad8a3a1126d6c6de9e883402eb35199287156b..9223cb6ce6a4667a716becbd8a7ae3ac774103ae 100644 (file)
@@ -162,16 +162,6 @@ struct server_record *add_server_entry(struct subnet_record *d,
   }
   
   
-  if (strequal(myworkgroup,work->work_group))
-    {
-         if (servertype)
-        servertype |= SV_TYPE_LOCAL_LIST_ONLY;
-    }
-  else
-    {
-      servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
-    }
-  
   /* update the entry */
   StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
   StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
index cc1c2bc002ef9aaf3c3601942584e2498511fc76..2b4ebf091cc0398085f03302b4bf45d2bb5ffdca 100644 (file)
@@ -345,7 +345,8 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
 
       /* update our server status */
       work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
-      add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,lp_serverstring(),True);
 
       /* add special browser name */
       add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP,False);
@@ -360,7 +361,8 @@ void become_local_master(struct subnet_record *d, struct work_record *work)
       work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
 
       /* add server entry on successful registration of MSBROWSE */
-      add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
+      add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,myname,True);
 
       /* add master name */
       add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE,False);
@@ -384,7 +386,8 @@ on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip)));
       DEBUG(3,("become_local_master: updating our server %s to type %x\n", 
                 myname, work->ServerType));
 
-      add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                               0,lp_serverstring(),True);
 
       /* Count the number of servers we have on our list. If it's
          less than 10 (just a heuristic) request the servers
@@ -493,8 +496,8 @@ void become_domain_master(struct subnet_record *d, struct work_record *work)
  
       /* update our server status */
       work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
-      add_server_entry(d,work,myname,work->ServerType,0,
-                        lp_serverstring(),True);
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+                                       0, lp_serverstring(),True);
 
       DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n", 
                 work->work_group, inet_ntoa(d->bcast_ip)));
@@ -549,8 +552,8 @@ void become_logon_server(struct subnet_record *d, struct work_record *work)
  
       /* update our server status */
       work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
-      add_server_entry(d,work,myname,work->ServerType,0,
-                      lp_serverstring(),True);
+      add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY
+                                       ,0, lp_serverstring(),True);
 
       /* DON'T do anything else after calling add_my_name_entry() */
       break;
index 23d48d9ced7c45523be2f372907b945bdf733505..ff623e69dbf94a7cc42a5795c2c0f00117233a9c 100644 (file)
@@ -255,7 +255,7 @@ static void process_localnet_announce(struct packet_struct *p,uint16 command,cha
   ttl = GET_TTL(ttl);
   
   /* add them to our browse list, and update the browse.dat file */
-  add_server_entry(d,work,name,servertype,ttl,comment,True);
+  add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
   updatedlists = True;
 
 #if 0
index 7f5d608998a865b1e1e37efcb22ff20fb4694d6c..97e7e02b2b9271c6823252ed93feab48363515f0 100644 (file)
@@ -99,7 +99,7 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
          for (i = 0;i < count;i++, p += 26)
            {
              char *sname = p;
-             uint32 stype = IVAL(p,18);
+             uint32 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
              int comment_offset = IVAL(p,22) & 0xFFFF;
              char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
              
@@ -157,7 +157,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work,
   got_pass = True;
   
   DEBUG(0,("sync_browse_lists: Sync browse lists with %s for %s %s\n",
-           work->work_group, name, inet_ntoa(ip)));
+           name, work->work_group, inet_ntoa(ip)));
   
   strcpy(workgroup,work->work_group);
   strcpy(desthost,name);
index 8c2dd2776cc9c5170386e7c271fe33afc601cd6f..9d3850b2428c9fd12d1de19d9f7df1053e2dd90c 100644 (file)
@@ -298,7 +298,7 @@ static service sDefault =
   NULL,    /* volume */
   0,       /* iMinPrintSpace */
   0644,    /* iCreate_mode */
-  0700,    /* iCreate_force_mode */
+  0000,    /* iCreate_force_mode */
   0755,    /* iDir_mode */
   0000,    /* iDir_force_mode */
   0,       /* iMaxConnections */
@@ -598,7 +598,7 @@ static void init_globals(void)
   Globals.max_packet = 65535;
   Globals.mangled_stack = 50;
   Globals.max_xmit = 65535;
-  Globals.max_mux = 2;
+  Globals.max_mux = 50; /* This is *needed* for profile support. */
   Globals.lpqcachetime = 10;
   Globals.pwordlevel = 0;
   Globals.deadtime = 0;
index 6b3953e6c8658449e73f7c225214ea972129425d..7922e41623637586a26baeb0692c555f9d63c70c 100644 (file)
@@ -770,6 +770,7 @@ static int get_server_info(uint32 servertype,
   int count=0;
   int alloced=0;
   pstring line;
+  BOOL local_list_only;
 
   strcpy(fname,lp_lockdir());
   trim_string(fname,NULL,"/");
@@ -784,7 +785,10 @@ static int get_server_info(uint32 servertype,
   }
 
   /* request for everything is code for request all servers */
-  if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+  if (servertype == SV_TYPE_ALL) 
+       servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+
+  local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
 
   DEBUG(4,("Servertype search: %8x\n",servertype));
 
@@ -821,6 +825,14 @@ static int get_server_info(uint32 servertype,
       ok = False; 
     }
     
+       /* Filter the servers/domains we return based on what was asked for. */
+
+       /* Check to see if we are being asked for a local list only. */
+       if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+         DEBUG(4,("r: local list only"));
+         ok = False;
+       }
+
     /* doesn't match up: don't want it */
     if (!(servertype & s->type)) { 
       DEBUG(4,("r:serv type ")); 
@@ -839,6 +851,9 @@ static int get_server_info(uint32 servertype,
        ok = False;
       }
     
+       /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+       s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+
     if (ok)
       {
        DEBUG(4,("**SV** %20s %8x %25s %15s\n",
index 203bdb8da89850adc7df8eb91b0f29b6a6648b1c..8c40734ce42e264c260d63eceb48651defa70995 100644 (file)
@@ -603,6 +603,14 @@ static void disk_norm(int *bsize,int *dfree,int *dsize)
 int disk_free(char *path,int *bsize,int *dfree,int *dsize)
 {
   char *df_command = lp_dfree_command();
+  int dfree_retval;
+#ifdef QUOTAS
+  int dfreeq_retval;
+  int dfreeq = 0;
+  int bsizeq = *bsize;
+  int dsizeq = *dsize;
+#endif
+
 #ifndef NO_STATFS
 #ifdef USE_STATVFS
   struct statvfs fs;
@@ -615,15 +623,6 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize)
 #endif
 #endif
 
-#ifdef QUOTAS
-  if (disk_quotas(path, bsize, dfree, dsize))
-    {
-      disk_norm(bsize,dfree,dsize);
-      return(((*bsize)/1024)*(*dfree));
-    }
-#endif
-
-
   /* possibly use system() to get the result */
   if (df_command && *df_command)
     {
@@ -639,22 +638,42 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize)
       DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
          
       {
-       FILE *f = fopen(outfile,"r");   
-       *dsize = 0;
-       *dfree = 0;
-       *bsize = 1024;
-       if (f)
-         {
-           fscanf(f,"%d %d %d",dsize,dfree,bsize);
-           fclose(f);
-         }
-       else
-         DEBUG(0,("Can't open %s\n",outfile));
+        FILE *f = fopen(outfile,"r");  
+        *dsize = 0;
+        *dfree = 0;
+        *bsize = 1024;
+        if (f)
+          {
+            fscanf(f,"%d %d %d",dsize,dfree,bsize);
+            fclose(f);
+          }
+        else
+          DEBUG(0,("Can't open %s\n",outfile));
       }
          
       unlink(outfile);
       disk_norm(bsize,dfree,dsize);
-      return(((*bsize)/1024)*(*dfree));
+      dfree_retval = ((*bsize)/1024)*(*dfree);
+#ifdef QUOTAS
+      /* Ensure we return the min value between the users quota and
+         what's free on the disk. Thanks to Albrecht Gebhardt 
+         <albrecht.gebhardt@uni-klu.ac.at> for this fix.
+      */
+      if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
+        {
+          disk_norm(&bsizeq, &dfreeq, &dsizeq);
+          dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
+          dfree_retval =  ( dfree_retval < dfreeq_retval ) ? 
+                           dfree_retval : dfreeq_retval ;
+          /* maybe dfree and dfreeq are calculated using different bsizes 
+             so convert dfree from bsize into bsizeq */
+          *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+          *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ; 
+          *bsize = bsizeq;
+          *dsize = dsizeq;
+        }
+#endif
+      return(dfree_retval);
     }
 
 #ifdef NO_STATFS
@@ -724,7 +743,27 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
       *dsize = 20*1024*1024/(*bsize);
       *dfree = MAX(1,*dfree);
     }
-  return(((*bsize)/1024)*(*dfree));
+  dfree_retval = ((*bsize)/1024)*(*dfree);
+#ifdef QUOTAS
+  /* Ensure we return the min value between the users quota and
+     what's free on the disk. Thanks to Albrecht Gebhardt 
+     <albrecht.gebhardt@uni-klu.ac.at> for this fix.
+  */
+  if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
+    {
+      disk_norm(&bsizeq, &dfreeq, &dsizeq);
+      dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
+      dfree_retval = ( dfree_retval < dfreeq_retval ) ? 
+                       dfree_retval : dfreeq_retval ;
+      /* maybe dfree and dfreeq are calculated using different bsizes 
+         so convert dfree from bsize into bsizeq */
+      *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+      *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
+      *bsize = bsizeq;
+      *dsize = dsizeq;
+    }
+#endif
+  return(dfree_retval);
 #endif
 }