sync HEAD with recent changes in 3.0
authorGerald Carter <jerry@samba.org>
Tue, 13 Jan 2004 17:55:43 +0000 (17:55 +0000)
committerGerald Carter <jerry@samba.org>
Tue, 13 Jan 2004 17:55:43 +0000 (17:55 +0000)
(This used to be commit c98399e3c9d74e19b7c9d806ca8028b48866931e)

61 files changed:
source3/Makefile.in
source3/auth/auth_domain.c
source3/bin/.cvsignore
source3/client/mount.cifs.c
source3/configure.in
source3/include/printing.h
source3/include/samba_linux_quota.h [new file with mode: 0644]
source3/include/samba_xfs_quota.h [new file with mode: 0644]
source3/include/sysquotas.h
source3/intl/lang_tdb.c
source3/lib/charcnv.c
source3/lib/sysquotas.c
source3/lib/sysquotas_4A.c [new file with mode: 0644]
source3/lib/sysquotas_linux.c [new file with mode: 0644]
source3/lib/sysquotas_xfs.c [new file with mode: 0644]
source3/lib/talloctort.c
source3/lib/time.c
source3/lib/util_str.c
source3/libads/sasl.c
source3/libsmb/cliconnect.c
source3/libsmb/clikrb5.c
source3/libsmb/clispnego.c
source3/libsmb/namequery.c
source3/locking/locking.c
source3/nmbd/nmbd_processlogon.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbind_nss_freebsd.c [new file with mode: 0644]
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_misc.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_sid.c
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c
source3/nsswitch/wins.c
source3/param/loadparm.c
source3/passdb/secrets.c
source3/printing/notify.c
source3/printing/print_cups.c
source3/printing/print_generic.c
source3/printing/printing.c
source3/printing/printing_db.c
source3/rpc_client/cli_lsarpc.c
source3/rpc_server/srv_samr_nt.c
source3/rpcclient/cmd_lsarpc.c
source3/rpcclient/cmd_spoolss.c
source3/script/installswat.sh
source3/script/mkbuildoptions.awk
source3/smbd/chgpasswd.c
source3/smbd/quotas.c
source3/tdb/tdb.c
source3/tests/crack.c [new file with mode: 0644]
source3/utils/net_rpc.c
source3/utils/ntlm_auth.c
source3/utils/smbcontrol.c
source3/utils/smbget.c [new file with mode: 0644]

index 923f4dbd5b163353a6fd44577c92596e02e00fa1..68aead0fc2a491be61476aa52fd624b6a85c2756 100644 (file)
@@ -85,7 +85,6 @@ PRIVATEDIR = @privatedir@
 
 SMB_PASSWD_FILE = $(PRIVATEDIR)/smbpasswd
 PRIVATE_DIR = $(PRIVATEDIR)
-DATADIR = @datadir@
 
 # This is where SWAT images and help files go
 SWATDIR = @swatdir@
@@ -202,11 +201,11 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
 
 PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o param/modconf.o
 
-KRBCLIENT_OBJ = libads/kerberos.o
+KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o 
 
 LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
             libads/krb5_setpw.o libads/ldap_user.o \
-            libads/ads_struct.o libads/ads_status.o \
+            libads/ads_struct.o \
              libads/disp_sec.o libads/ads_utils.o libads/ldap_utils.o \
             libads/ads_ldap.o libads/authdata.o
 
@@ -362,8 +361,9 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
               smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
                smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
               smbd/process.o smbd/service.o smbd/error.o \
-              printing/printfsp.o \
-               lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \
+              printing/printfsp.o lib/sysquotas.o lib/sysquotas_linux.o \
+              lib/sysquotas_xfs.o lib/sysquotas_4A.o \
+              smbd/change_trust_pw.o smbd/fake_file.o \
               smbd/quotas.o smbd/ntquotas.o lib/afs.o \
               $(MANGLE_OBJ) @VFS_STATIC@
 
@@ -450,6 +450,8 @@ PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \
                $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \
                $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o
 
+SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ) $(SECRETS_OBJ)
+
 RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
                 rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \
                 rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \
@@ -730,6 +732,12 @@ MAKEDIR = || exec false; \
          -o $@ 
 @BROKEN_CC@    -mv `echo $@ | sed 's%^.*/%%g'` $@
 
+# this adds support for precompiled headers. To use it, install a snapshot
+# of gcc-3.4 and run 'make pch' before you do the main build. 
+pch:
+       rm -f $(srcdir)/include/includes.h.gch
+       $(CC) -I. -I$(srcdir) $(FLAGS) -c $(srcdir)/include/includes.h -o $(srcdir)/include/includes.h.gch
+
 # These dependencies are only approximately correct: we want to make
 # sure Samba's paths are updated if ./configure is re-run.  Really it
 # would be nice if "make prefix=/opt/samba all" also rebuilt things,
@@ -746,7 +754,7 @@ dynconfig.@PICSUFFIX@: dynconfig.c Makefile
        @echo Compiling $*.c with @PICFLAGS@
        @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAGS@ -c $< -o $*.@PICSUFFIX@
 @BROKEN_CC@    -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.@PICSUFFIX@$$%.o%'` $@
-@POBAD_CC@     @mv $*.@PICSUFFIX@.o $@
+@POBAD_CC@     -@mv $*.@PICSUFFIX@.o $@
 
 lib/version.o: lib/version.c include/version.h
        @echo Compiling $*.c
@@ -870,6 +878,10 @@ bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(LDAP_LIBS)
 
+bin/smbget@EXEEXT@: $(SMBGET_OBJ) @BUILD_POPT@ bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(SMBGET_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@  $(KRB5LIBS) $(LDAP_LIBS)
+
 bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(KRB5LIBS) $(LDAP_LIBS)
@@ -1034,7 +1046,7 @@ bin/librpc_epmapper.@SHLIBEXT@: $(RPC_EPMAPPER_OBJ)
 
 bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
        @echo "Linking $@"
-       @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) 
+       @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
 
 # Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind
 # libraries.  Add to the appropriate PICOBJ variable instead.
index 31ffd88083688c53dbe21cd25e61150a31afbdeb..0bf2031a374122f750a653f2f3abfa66e70f5bdc 100644 (file)
@@ -33,10 +33,10 @@ extern BOOL global_machine_password_needs_changing;
  * @param server either a machine name or text IP address to
  *               connect to.
  * @param setup_creds_as domain account to setup credentials as
- * @param sec_chan switch value to distinguish between domain
+ * @param sec_chan switch value to distinguish between domain
  *                 member and interdomain authentication
  * @param trust_passwd the trust password to establish the
- *                     credentials
+ *                     credentials with.
  *
  **/
 
index 013a5ba6c1d5a2990a450e61636ddcb5ce9ae702..aad6091960332a90b1168fe8a794c10ec64bc37d 100644 (file)
@@ -5,6 +5,7 @@ debug2html
 editreg
 locktest
 locktest2
+log2pcap
 make_printerdef
 make_smbcodepage
 make_unicodemap
@@ -28,6 +29,7 @@ smbcquotas
 smbd
 smbfilter
 smbgroupedit
+smbiconv
 smbmnt
 smbmount
 smbpasswd
@@ -37,7 +39,6 @@ smbstatus
 smbtorture
 smbtree
 smbumount
-smbiconv
 swat
 t_push_ucs2
 t_snprintf
@@ -45,11 +46,10 @@ t_strcmp
 t_stringoverflow
 talloctort
 tdbbackup
+tdbdump
 testparm
 testprns
 vfstest
-log2pcap
 wbinfo
 winbindd
 wrepld
-tdbdump
index 43b20e9d502cdbd00002065acfeb62a5c752ea1a..8c23cc2212312793d564c973805aeff4a7c0d37a 100755 (executable)
@@ -1,6 +1,27 @@
+/* 
+   Mount helper utility for Linux CIFS VFS (virtual filesystem) client
+   Copyright (C) 2003 Steve French  (sfrench@us.ibm.com)
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <unistd.h>
 #include <pwd.h>
 #include <sys/types.h>
 #include <netdb.h>
 #include <string.h>
 #include <mntent.h>
+#include <fcntl.h>
 
-#define MOUNT_CIFS_VERSION "1"
+#define MOUNT_CIFS_VERSION_MAJOR "1"
+#define MOUNT_CIFS_VERSION_MINOR "0"
 
-extern char *getusername(void);
+#ifndef MOUNT_CIFS_VENDOR_SUFFIX
+#define MOUNT_CIFS_VENDOR_SUFFIX ""
+#endif
 
 char * thisprogram;
 int verboseflag = 0;
@@ -41,17 +66,20 @@ char * mountpassword = NULL;
                 
 BB end finish BB */
 
-void mount_cifs_usage()
+static void mount_cifs_usage(void)
 {
-       printf("\nUsage:  %s remotetarget dir\n", thisprogram);
-       printf("\nMount the remotetarget, specified as either a UNC name or ");
-       printf(" CIFS URL, to the local directory, dir.\n");
-
+       printf("\nUsage:  %s <remotetarget> <dir> -o <options>\n", thisprogram);
+       printf("\nMount the remote target, specified as a UNC name,");
+       printf(" to a local directory.\n");
+       if(mountpassword) {
+               memset(mountpassword,0,64);
+               free(mountpassword);
+       }
        exit(1);
 }
 
 /* caller frees username if necessary */
-char * getusername() {
+static char * getusername(void) {
        char *username = NULL;
        struct passwd *password = getpwuid(getuid());
 
@@ -61,25 +89,185 @@ char * getusername() {
        return username;
 }
 
-char * parse_cifs_url(unc_name)
+char * parse_cifs_url(char * unc_name)
 {
        printf("\ncifs url %s\n",unc_name);
+       return NULL;
+}
+
+static int open_cred_file(char * file_name)
+{
+       char * line_buf;
+       char * temp_val;
+       FILE * fs;
+       int i, length;
+       fs = fopen(file_name,"r");
+       if(fs == NULL)
+               return errno;
+       line_buf = malloc(4096);
+       if(line_buf == NULL)
+               return -ENOMEM;
+
+       while(fgets(line_buf,4096,fs)) {
+               /* parse line from credential file */
+
+               /* eat leading white space */
+               for(i=0;i<4096;i++) {
+                       if(line_buf[i] == '\0')
+                               break;
+                       else if((line_buf[i] != ' ') && (line_buf[i] != '\t'))
+                               break;
+                       line_buf++;
+               }
+
+               if (strncasecmp("username",line_buf,8) == 0) {
+                       temp_val = strchr(line_buf + i,'=');
+                       if(temp_val) {
+                               /* go past equals sign */
+                               temp_val++;
+                               length = strlen(temp_val);
+                               if(length > 4086) {
+                                       printf("cifs.mount failed due to malformed username in credentials file");
+                                       memset(line_buf,0,4096);
+                                       if(mountpassword) {
+                                               memset(mountpassword,0,64);
+                                       }
+                                       exit(1);
+                               } else {
+                                       got_user = 1;
+                                       user_name = calloc(1 + length,1);
+                                       /* BB adding free of user_name string before exit,
+                                               not really necessary but would be cleaner */
+                                       strncpy(user_name,temp_val, length);
+                               }
+                       }
+               } else if (strncasecmp("password",line_buf,8) == 0) {
+                       temp_val = strchr(line_buf+i,'=');
+                       if(temp_val) {
+                               /* go past equals sign */
+                               temp_val++;
+                               length = strlen(temp_val);
+                               if(length > 64) {
+                                       printf("cifs.mount failed: password in credentials file too long\n");
+                                       memset(line_buf,0, 4096);
+                                       if(mountpassword) {
+                                               memset(mountpassword,0,64);
+                                       }
+                                       exit(1);
+                               } else {
+                                       if(mountpassword == NULL) {
+                                               mountpassword = calloc(65,1);
+                                       }
+                                       if(mountpassword) {
+                                               strncpy(mountpassword,temp_val,64);
+                                               got_password = 1;
+                                       }
+                               }
+                       }
+               }
+       }
+       fclose(fs);
+       if(line_buf) {
+               memset(line_buf,0,4096);
+               free(line_buf);
+       }
+       return 0;
 }
 
-int parse_options(char * options)
+static int get_password_from_file(int file_descript, char * filename)
+{
+       int rc = 0;
+       int i;
+       char c;
+
+       if(mountpassword == NULL)
+               mountpassword = calloc(65,1);
+       else 
+               memset(mountpassword, 0, 64);
+
+       if(filename != NULL) {
+               file_descript = open(filename, O_RDONLY);
+               if(file_descript < 0) {
+                       printf("cifs.mount failed. %s attempting to open password file %s\n",
+                                  strerror(errno),filename);
+                       exit(1);
+               }
+       }
+       /* else file already open and fd provided */
+
+       for(i=0;i<64;i++) {
+               rc = read(file_descript,&c,1);
+               if(rc < 0) {
+                       printf("cifs.mount failed. Error %s reading password file\n",strerror(errno));
+                       memset(mountpassword,0,64);
+                       if(filename != NULL)
+                               close(file_descript);
+                       exit(1);
+               } else if(rc == 0) {
+                       if(mountpassword[0] == 0) {
+                               if(verboseflag)
+                                       printf("\nWarning: null password used since cifs password file empty");
+                       }
+                       break;
+               } else /* read valid character */ {
+                       if((c == 0) || (c == '\n')) {
+                               break;
+                       } else 
+                               mountpassword[i] = c;
+               }
+       }
+       if((i == 64) && (verboseflag)) {
+               printf("\nWarning: password longer than 64 characters specified in cifs password file");
+       }
+       got_password = 1;
+       if(filename != NULL) {
+               close(file_descript);
+       }
+
+       return rc;
+}
+
+static int parse_options(char * options)
 {
        char * data;
+       char * percent_char = 0;
        char * value = 0;
+       char * next_keyword = 0;
+       int rc = 0;
 
        if (!options)
                return 1;
+       else
+               data = options;
+
+       if(verboseflag)
+               printf("\n parsing options: %s", options);
 
-       while ((data = strsep(&options, ",")) != NULL) {
-               if (!*data)
-                       continue;
+/* while ((data = strsep(&options, ",")) != NULL) { */
+       while(data != NULL) {
+               /*  check if ends with trailing comma */
+               if(*data == 0)
+                       break;
+
+               /* format is keyword=value,keyword2=value2,keyword3=value3 etc.) */
+               /* data  = next keyword */
+               /* value = next value ie stuff after equal sign */
+
+               next_keyword = strchr(data,',');
+       
+               /* temporarily null terminate end of keyword=value pair */
+               if(next_keyword)
+                       *next_keyword = 0;
+
+               /* if (!*data)
+                       continue; */
+               
+               /* temporarily null terminate keyword to make keyword and value distinct */
                if ((value = strchr(data, '=')) != NULL) {
-                       *value++ = '\0';
+                       *value = '\0';
+                       value++;
                }
+
                if (strncmp(data, "user", 4) == 0) {
                        if (!value || !*value) {
                                printf("invalid or missing username\n");
@@ -87,113 +275,142 @@ int parse_options(char * options)
                        }
                        if (strnlen(value, 260) < 260) {
                                got_user=1;
-                               /* BB add check for format user%pass */
-                               /* if(strchr(username%passw) got_password = 1) */
+                               percent_char = strchr(value,'%');
+                               if(percent_char) {
+                                       *percent_char = ',';
+                                       if(mountpassword == NULL)
+                                               mountpassword = calloc(65,1);
+                                       if(mountpassword) {
+                                               if(got_password)
+                                                       printf("\ncifs.mount warning - password specified twice\n");
+                                               got_password = 1;
+                                               percent_char++;
+                                               strncpy(mountpassword, percent_char,64);
+                                       /*  remove password from username */
+                                               while(*percent_char != 0) {
+                                                       *percent_char = ',';
+                                                       percent_char++;
+                                               }
+                                       }
+                               }
                        } else {
                                printf("username too long\n");
                                return 1;
                        }
-       } else if (strncmp(data, "pass", 4) == 0) {
-               if (!value || !*value) {
-                       if(got_password) {
-                               printf("password specified twice, ignoring second\n");
-                       } else
+               } else if (strncmp(data, "pass", 4) == 0) {
+                       if (!value || !*value) {
+                               if(got_password) {
+                                       printf("\npassword specified twice, ignoring second\n");
+                               } else
+                                       got_password = 1;
+                       } else if (strnlen(value, 17) < 17) {
+                               if(got_password)
+                                       printf("\ncifs.mount warning - password specified twice\n");
                                got_password = 1;
-               } else if (strnlen(value, 17) < 17) {
-                       got_password = 1;
-               } else {
-                       printf("password too long\n");
-                       return 1;
-               }
-       } else if (strncmp(data, "ip", 2) == 0) {
-               if (!value || !*value) {
-                       printf("target ip address argument missing");
-               } else if (strnlen(value, 35) < 35) {
-                       got_ip = 1;
-               } else {
-                       printf("ip address too long\n");
-                       return 1;
-               }
-       } else if ((strncmp(data, "unc", 3) == 0)
+                       } else {
+                               printf("password too long\n");
+                               return 1;
+                       }
+               } else if (strncmp(data, "ip", 2) == 0) {
+                       if (!value || !*value) {
+                               printf("target ip address argument missing");
+                       } else if (strnlen(value, 35) < 35) {
+                               got_ip = 1;
+                       } else {
+                               printf("ip address too long\n");
+                               return 1;
+                       }
+               } else if ((strncmp(data, "unc", 3) == 0)
                   || (strncmp(data, "target", 6) == 0)
                   || (strncmp(data, "path", 4) == 0)) {
-               if (!value || !*value) {
-                       printf("invalid path to network resource\n");
-                       return 1;  /* needs_arg; */
-               } else if(strnlen(value,5) < 5) {
-                       printf("UNC name too short");
-               }
+                       if (!value || !*value) {
+                               printf("invalid path to network resource\n");
+                               return 1;  /* needs_arg; */
+                       } else if(strnlen(value,5) < 5) {
+                               printf("UNC name too short");
+                       }
 
-               if (strnlen(value, 300) < 300) {
-                       got_unc = 1;
-                       if (strncmp(value, "//", 2) == 0) {
-                               if(got_unc)
-                                       printf("unc name specified twice, ignoring second\n");
-                               else
-                                       got_unc = 1;
-                       } else if (strncmp(value, "\\\\", 2) != 0) {                       
-                               printf("UNC Path does not begin with // or \\\\ \n");
+                       if (strnlen(value, 300) < 300) {
+                               got_unc = 1;
+                               if (strncmp(value, "//", 2) == 0) {
+                                       if(got_unc)
+                                               printf("unc name specified twice, ignoring second\n");
+                                       else
+                                               got_unc = 1;
+                               } else if (strncmp(value, "\\\\", 2) != 0) {                       
+                                       printf("UNC Path does not begin with // or \\\\ \n");
+                                       return 1;
+                               } else {
+                                       if(got_unc)
+                                               printf("unc name specified twice, ignoring second\n");
+                                       else
+                                               got_unc = 1;
+                               }
+                       } else {
+                               printf("CIFS: UNC name too long\n");
                                return 1;
+                       }
+               } else if ((strncmp(data, "domain", 3) == 0)
+                          || (strncmp(data, "workgroup", 5) == 0)) {
+                       if (!value || !*value) {
+                               printf("CIFS: invalid domain name\n");
+                               return 1;       /* needs_arg; */
+                       }
+                       if (strnlen(value, 65) < 65) {
+                               got_domain = 1;
                        } else {
-                               if(got_unc)
-                                       printf("unc name specified twice, ignoring second\n");
-                               else
-                                       got_unc = 1;
+                               printf("domain name too long\n");
+                               return 1;
+                       }
+               } else if (strncmp(data, "cred", 4) == 0) {
+                       if (value && *value) {
+                               rc = open_cred_file(value);
+                               if(rc) {
+                                       printf("error %d opening credential file %s",rc, value);
+                                       return 1;
+                               }
+                       } else {
+                               printf("invalid credential file name specified\n");
+                               return 1;
+                       }
+               } else if (strncmp(data, "uid", 3) == 0) {
+                       if (value && *value) {
+                               got_uid = 1;
+                       }
+               } else if (strncmp(data, "gid", 3) == 0) {
+                       if (value && *value) {
+                               got_gid = 1;
                        }
-               } else {
-                       printf("CIFS: UNC name too long\n");
-                       return 1;
-               }
-       } else if ((strncmp(data, "domain", 3) == 0)
-                  || (strncmp(data, "workgroup", 5) == 0)) {
-               if (!value || !*value) {
-                       printf("CIFS: invalid domain name\n");
-                       return 1;       /* needs_arg; */
-               }
-               if (strnlen(value, 65) < 65) {
-                       got_domain = 1;
-               } else {
-                       printf("domain name too long\n");
-                       return 1;
-               }
-       } else if (strncmp(data, "uid", 3) == 0) {
-               if (value && *value) {
-                       got_uid = 1;
-               }
-       } else if (strncmp(data, "gid", 3) == 0) {
-               if (value && *value) {
-                       got_gid = 1;
-               }
        /* fmask and dmask synonyms for people used to smbfs syntax */
-       } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
-               if (!value || !*value) {
-                       printf ("Option '%s' requires a numerical argument\n", data);
-                       return 1;
-               }
+               } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) {
+                       if (!value || !*value) {
+                               printf ("Option '%s' requires a numerical argument\n", data);
+                               return 1;
+                       }
 
-               if (value[0] != '0') {
-                       printf ("WARNING: '%s' not expressed in octal.\n", data);
-               }
+                       if (value[0] != '0') {
+                               printf ("WARNING: '%s' not expressed in octal.\n", data);
+                       }
+
+                       if (strcmp (data, "fmask") == 0) {
+                               printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
+                               data = "file_mode";
+                       }
+               } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
+                       if (!value || !*value) {
+                               printf ("Option '%s' requires a numerical argument\n", data);
+                               return 1;
+                       }
+
+                       if (value[0] != '0') {
+                               printf ("WARNING: '%s' not expressed in octal.\n", data);
+                       }
 
-               if (strcmp (data, "fmask") == 0) {
-                       printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n");
-                       data = "file_mode";
-                }
-        } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) {
-                if (!value || !*value) {
-                        printf ("Option '%s' requires a numerical argument\n", data);
-                        return 1;
-                }
-
-                if (value[0] != '0') {
-                        printf ("WARNING: '%s' not expressed in octal.\n", data);
-                }
-
-                if (strcmp (data, "dmask") == 0) {
-                        printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
-                        data = "dir_mode";
-                }
-       } /* else if (strnicmp(data, "port", 4) == 0) {
+                       if (strcmp (data, "dmask") == 0) {
+                               printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n");
+                               data = "dir_mode";
+                       }
+               } /* else if (strnicmp(data, "port", 4) == 0) {
                if (value && *value) {
                        vol->port =
                                simple_strtoul(value, &value, 0);
@@ -214,6 +431,22 @@ int parse_options(char * options)
                
        } else
                printf("CIFS: Unknown mount option %s\n",data); */
+
+               /* move to next option */
+               data = next_keyword+1;
+
+               /* put overwritten equals sign back */
+               if(value) {
+                       value--;
+                       *value = '=';
+               }
+               
+               /* put previous overwritten comma back */
+               if(next_keyword)
+                       *next_keyword = ',';
+               else
+                       data = 0;
+
        }
        return 0;
 }
@@ -226,8 +459,7 @@ char * parse_server(char * unc_name)
        char * ipaddress_string = NULL;
        struct hostent * host_entry;
        struct in_addr server_ipaddr;
-       int rc,j;
-       char temp[64];
+       int rc;
 
        if(length > 1023) {
                printf("mount error: UNC name too long");
@@ -244,7 +476,6 @@ char * parse_server(char * unc_name)
                printf("\nMounting the DFS root for domain not implemented yet");
                return 0;
        } else {
-               /* BB add support for \\\\ not just // */
                if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) {
                        printf("mount error: improperly formatted UNC name.");
                        printf(" %s does not begin with \\\\ or //\n",unc_name);
@@ -300,21 +531,19 @@ static struct option longopts[] = {
        { "rw", 0, 0, 'w' },
        { "options", 1, 0, 'o' },
        { "types", 1, 0, 't' },
-       { "replace", 0, 0, 129 },
-       { "after", 0, 0, 130 },
-       { "before", 0, 0, 131 },
-       { "over", 0, 0, 132 },
-       { "move", 0, 0, 133 },
-       { "rsize",1, 0, 136 },
-       { "wsize",1, 0, 137 },
-       { "uid", 1, 0, 138},
-       { "gid", 1, 0, 139},
+       { "rsize",1, 0, 'R' },
+       { "wsize",1, 0, 'W' },
+       { "uid", 1, 0, '1'},
+       { "gid", 1, 0, '2'},
        { "uuid",1,0,'U' },
-       { "user",1,0,140},
-       { "username",1,0,140},
-       { "dom",1,0,141},
-       { "domain",1,0,141},
-       { "password",1,0,142},
+       { "user",1,0,'u'},
+       { "username",1,0,'u'},
+       { "dom",1,0,'d'},
+       { "domain",1,0,'d'},
+       { "password",1,0,'p'},
+       { "pass",1,0,'p'},
+       { "credentials",1,0,'c'},
+       { "port",1,0,'P'},
        { NULL, 0, 0, 0 }
 };
 
@@ -330,13 +559,14 @@ int main(int argc, char ** argv)
        char * mountpoint;
        char * options;
        char * temp;
-       int rc,i;
+       int rc;
        int rsize = 0;
        int wsize = 0;
        int nomtab = 0;
        int uid = 0;
        int gid = 0;
        int optlen = 0;
+       int orgoptlen = 0;
        struct stat statbuf;
        struct utsname sysinfo;
        struct mntent mountent;
@@ -354,56 +584,40 @@ int main(int argc, char ** argv)
 
        uname(&sysinfo);
        /* BB add workstation name and domain and pass down */
-/*#ifdef _GNU_SOURCE
-       printf(" node: %s machine: %s\n", sysinfo.nodename,sysinfo.machine);
-#endif*/
-       if(argc < 3)
-               mount_cifs_usage();
+
+/* #ifdef _GNU_SOURCE
+       printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname);
+#endif */
+
        share_name = argv[1];
        mountpoint = argv[2];
+
        /* add sharename in opts string as unc= parm */
 
        while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:",
                         longopts, NULL)) != -1) {
                switch (c) {
-/*     case 'a':              
-               ++mount_all;
-               break;
-       case 'f':              
-               ++fake;
-               break;
-       case 'F':
-               ++optfork;
-               break; */
-               case 'h':        /* help */
-                       mount_cifs_usage ();
-                       break;
-/*     case 'i':
-               external_allowed = 0;
-               break;
-       case 'l':
+/* No code to do the following  options yet */
+/*     case 'l':
                list_with_volumelabel = 1;
                break;
        case 'L':
                volumelabel = optarg;
                break; */
-       case 'n':
-               ++nomtab;
-               break;
-       case 'o':
-               if (orgoptions) {
-                       orgoptions = strcat(orgoptions, ",");
-                       orgoptions = strcat(orgoptions,optarg);
-               } else
-                       orgoptions = strdup(optarg);
-               break;
+/*     case 'a':              
+               ++mount_all;
+               break; */
 
-/*     case 'O':
-               if (test_opts)
-                       test_opts = xstrconcat3(test_opts, ",", optarg);
-               else
-                       test_opts = xstrdup(optarg);
-               break;*/
+               case '?':
+               case 'h':        /* help */
+                       mount_cifs_usage ();
+                       exit(1);
+               case 'n':
+                   ++nomtab;
+                   break;
+               case 'o':
+                       orgoptions = strdup(optarg);
+                   break;
                case 'r':  /* mount readonly */
                        flags |= MS_RDONLY;
                        break;
@@ -413,68 +627,78 @@ int main(int argc, char ** argv)
                case 'v':
                        ++verboseflag;
                        break;
-/*     case 'V':          
-               printf ("mount: %s\n", version);
-               exit (0);*/
+               case 'V':          
+                       printf ("mount.cifs version: %s.%s%s\n",
+                       MOUNT_CIFS_VERSION_MAJOR,
+                       MOUNT_CIFS_VERSION_MINOR,
+                       MOUNT_CIFS_VENDOR_SUFFIX);
+                       if(mountpassword) {
+                               memset(mountpassword,0,64);
+                       }
+                       exit (0);
                case 'w':
                        flags &= ~MS_RDONLY;
                        break;
-/*     case 0:
-               break;
-
-       case 128: 
-               mounttype = MS_BIND;
-               break;
-       case 129: 
-               mounttype = MS_REPLACE;
-               break;
-       case 130: 
-               mounttype = MS_AFTER;
-               break;
-       case 131: 
-               mounttype = MS_BEFORE;
-               break;
-       case 132: 
-               mounttype = MS_OVER;
-               break;
-       case 133: 
-               mounttype = MS_MOVE;
-               break;
-       case 135:
-               mounttype = (MS_BIND | MS_REC);
-               break; */
-               case 136:
+               case 'R':
                        rsize = atoi(optarg) ;
                        break;
-               case 137:
+               case 'W':
                        wsize = atoi(optarg);
                        break;
-               case 138:
+               case '1':
                        uid = atoi(optarg);
                        break;
-               case 139:
+               case '2':
                        gid = atoi(optarg);
                        break;
-               case 140:
+               case 'u':
                        got_user = 1;
                        user_name = optarg;
                        break;
-               case 141:
+               case 'd':
                        domain_name = optarg;
                        break;
-               case 142:
-                       got_password = 1;
-                        mountpassword = optarg;
+               case 'p':
+                       if(mountpassword == NULL)
+                               mountpassword = calloc(65,1);
+                       if(mountpassword) {
+                               got_password = 1;
+                               strncpy(mountpassword,optarg,64);
+                       }
+                       break;
+               case 't':
                        break;
-               case '?':
                default:
-                       mount_cifs_usage ();
+                       printf("unknown mount option %c\n",c);
+                       mount_cifs_usage();
+                       exit(1);
                }
        }
 
-       /* canonicalize the path in argv[1]? */
+       if(argc < 3)
+               mount_cifs_usage();
+
+       if (getenv("PASSWD")) {
+               if(mountpassword == NULL)
+                       mountpassword = calloc(65,1);
+               if(mountpassword) {
+                       strncpy(mountpassword,getenv("PASSWD"),64);
+                       got_password = 1;
+               }
+       } else if (getenv("PASSWD_FD")) {
+               get_password_from_file(atoi(getenv("PASSWD_FD")),NULL);
+       } else if (getenv("PASSWD_FILE")) {
+               get_password_from_file(0, getenv("PASSWD_FILE"));
+       }
+
+       ipaddr = parse_server(share_name);
+       
+       if (orgoptions && parse_options(orgoptions))
+               return 1;
+
+       /* BB save off path and pop after mount returns? */
+       /* BB canonicalize the path in argv[1]? */
 
-       /* BB save off path and pop after mount returns */
        if(chdir(mountpoint)) {
                printf("mount error: can not change directory into mount target %s\n",mountpoint);
        }
@@ -490,44 +714,26 @@ int main(int argc, char ** argv)
        }
 
        if((getuid() != 0) && (geteuid() == 0)) {
-               if((statbuf.st_uid == getuid()) && (S_IRWXU == statbuf.st_mode & S_IRWXU)) {
+               if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) {
                        printf("setuid mount allowed\n");
                } else {
-                       printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n"); 
+                       printf("mount error: permission denied or not superuser and cifs.mount not installed SUID\n"); 
                        return -1;
                }
        }
 
-       ipaddr = parse_server(share_name);
-/*     if(share_name == NULL)
-               return 1; */
-       if (orgoptions && parse_options(strdup(orgoptions)))
-               return 1;
-
        if(got_user == 0)
                user_name = getusername();
        
-/*     check username for user%password format */
-
        if(got_password == 0) {
-               if (getenv("PASSWD")) {
-                       mountpassword = malloc(33);
-                       if(mountpassword) {
-                               strncpy(mountpassword,getenv("PASSWD"),32);
-                               got_password = 1;
-                       }
-/*             } else if (getenv("PASSWD_FD") || getenv("PASSWD_FILE")) {
-                       get_password_file();
-                       got_password = 1;*/ /* BB add missing function */
-               } else {
-                       mountpassword = getpass("Password: "); /* BB obsolete */
-                       got_password = 1;
-               }
+               mountpassword = getpass("Password: "); /* BB obsolete */
+               got_password = 1;
        }
        /* FIXME launch daemon (handles dfs name resolution and credential change) 
           remember to clear parms and overwrite password field before launching */
        if(orgoptions) {
                optlen = strlen(orgoptions);
+               orgoptlen = optlen;
        } else
                optlen = 0;
        if(share_name)
@@ -560,19 +766,20 @@ int main(int argc, char ** argv)
                strcat(options,mountpassword);
        }
        strncat(options,",ver=",5);
-       strcat(options,MOUNT_CIFS_VERSION);
+       strcat(options,MOUNT_CIFS_VERSION_MAJOR);
 
        if(orgoptions) {
                strcat(options,",");
                strcat(options,orgoptions);
        }
-       /* printf("\noptions %s \n",options);*/
+       if(verboseflag)
+               printf("\ncifs.mount kernel mount options %s \n",options);
        if(mount(share_name, mountpoint, "cifs", flags, options)) {
        /* remember to kill daemon on error */
                switch (errno) {
                case 0:
                        printf("mount failed but no error number set\n");
-                       return 0;
+                       break;
                case ENODEV:
                        printf("mount error: cifs filesystem not supported by the system\n");
                        break;
@@ -580,6 +787,9 @@ int main(int argc, char ** argv)
                        printf("mount error %d = %s\n",errno,strerror(errno));
                }
                printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n");
+               if(mountpassword) {
+                       memset(mountpassword,0,64);
+               }
                return -1;
        } else {
                pmntfile = setmntent(MOUNTED, "a+");
@@ -596,6 +806,20 @@ int main(int argc, char ** argv)
                    printf("could not update mount table\n");
                }
        }
+       if(mountpassword) {
+               memset(mountpassword,0,64);
+               free(mountpassword);
+       }
+
+       if(options) {
+               memset(options,0,optlen);
+               free(options);
+       }
+
+       if(orgoptions) {
+               memset(orgoptions,0,orgoptlen);
+               free(orgoptions);
+       }
        return 0;
 }
 
index 1121551efc98733f4f9e4fc7b8786e0f010ecd6f..821ab3a1eacfec214158a01e2b81b050509018ff 100644 (file)
@@ -187,7 +187,6 @@ AC_SUBST(CONFIG_LIBS)
 AC_ARG_ENABLE(debug, 
 [  --enable-debug          Turn on compiler debugging information (default=no)],
     [if eval "test x$enable_debug = xyes"; then
-        echo "DEBUGGING TURNED ON!!!!"
        CFLAGS="${CFLAGS} -g"
     fi])
 
@@ -1636,9 +1635,8 @@ for i in $LOOK_DIRS ; do
     save_CPPFLAGS=$CPPFLAGS
     CPPFLAGS="$CPPFLAGS -I$i/include"
 dnl This is here to handle -withval stuff for --with-libiconv
-    if test x"$ICONV_PATH_SPEC" = "xyes" ; then
-       LDFLAGS="-L$i/lib"
-    fi
+dnl Perhaps we should always add a -L
+    LDFLAGS="$LDFLAGS -L$i/lib"
     LIBS=
     export LDFLAGS LIBS CPPFLAGS
 dnl Try to find iconv(3)
@@ -1715,7 +1713,7 @@ dnl ])
         LIBS="$ic_save_LIBS"
         if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then
           CPPFLAGS=$save_CPPFLAGS
-          CFLAGS_ADD_DIR(CPPFLAGS, "$i/include")
+          LDFLAGS=$save_LDFLAGS
           LIBS=$save_LIBS
            if test x"$jm_cv_lib_iconv" != x; then
               LIBS="$LIBS -l$jm_cv_lib_iconv"
@@ -2640,6 +2638,7 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS) 
   AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS) 
   AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_data_contents, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS)
 
   LIBS="$LIBS $KRB5_LIBS"
@@ -3056,6 +3055,7 @@ samba_cv_TRY_QUOTAS=no
 samba_cv_RUN_QUOTA_TESTS=auto
 samba_cv_WITH_SYS_QUOTAS=auto
 samba_cv_TRY_SYS_QUOTAS=no
+samba_cv_SYSQUOTA_FOUND=no;
 
 AC_MSG_CHECKING(whether to try disk-quotas support)
 AC_ARG_WITH(quotas,
@@ -3125,6 +3125,11 @@ AC_MSG_CHECKING(whether to try the lib/sysquotas.c interface on ${host_os})
            AC_MSG_RESULT(yes)
             samba_cv_TRY_SYS_QUOTAS=yes
             samba_cv_RUN_QUOTA_TESTS=yes
+            samba_cv_SYSQUOTA_FOUND=yes
+            AC_DEFINE(HAVE_QUOTACTL_LINUX,1,[Whether Linux quota support is available])
+            samba_cv_sysquotas_file="lib/sysquotas_linux.c"
+            AC_DEFINE(HAVE_LINUX_XFS_QUOTAS,1,[Whether Linux xfs quota support is available])
+            samba_cv_found_xfs_header=yes
            ;;
        *)
            AC_MSG_RESULT(no)
@@ -3137,21 +3142,21 @@ fi
 # only check for quota stuff if --with-quotas
 if test x"$samba_cv_RUN_QUOTA_TESTS" != x"no"; then
 
+# some broken header files need this
+AC_CHECK_HEADER(asm/types.h,[
+           AC_DEFINE(HAVE_ASM_TYPES_H,1,[check for <asm/types.h>])
+           AC_ADD_INCLUDE(<asm/types.h>)
+           ])
+
 # For quotas on Veritas VxFS filesystems
 AC_CHECK_HEADERS(sys/fs/vx_quota.h)
 
 # For sys/quota.h and linux/quota.h
 AC_CHECK_HEADERS(sys/quota.h)
-AC_CHECK_HEADERS(asm/types.h linux/quota.h)
-
-# For quotas on Linux XFS filesystems
-AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
-AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)
-# For linux > 2.5.56 
-AC_CHECK_HEADERS(linux/dqblk_xfs.h)
 
-# if we have struct if_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct if_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_IF_DQBLK, [
+if test x"$samba_cv_found_xfs_header" != x"yes"; then
+# if we have xfs quota support <sys/quota.h> (IRIX) we should use it
+AC_CACHE_CHECK([for XFS QUOTA in <sys/quota.h>],samba_cv_HAVE_SYS_QUOTA_XFS, [
 AC_TRY_COMPILE([
 #include "confdefs.h"
 #ifdef HAVE_SYS_TYPES_H
@@ -3160,28 +3165,12 @@ AC_TRY_COMPILE([
 #ifdef HAVE_ASM_TYPES_H
 #include <asm/types.h>
 #endif
-#include <linux/quota.h>
-],[struct if_dqblk D;],
-samba_cv_HAVE_STRUCT_IF_DQBLK=yes,samba_cv_HAVE_STRUCT_IF_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_IF_DQBLK"x = "yes"x; then
-       AC_DEFINE(HAVE_STRUCT_IF_DQBLK,1,[struct if_dqblk])
+#include <sys/quota.h>
+],[int i = Q_XGETQUOTA;],
+samba_cv_HAVE_SYS_QUOTA_XFS=yes,samba_cv_HAVE_SYS_QUOTA_XFS=no)])
+if test "$samba_cv_HAVE_SYS_QUOTA_XFS"x = "yes"x; then
+       samba_cv_found_xfs_header=yes
 fi
-
-# if we have struct mem_dqblk in <linux/quota.h> we should use it
-AC_CACHE_CHECK([for struct mem_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_MEM_DQBLK, [
-AC_TRY_COMPILE([
-#include "confdefs.h"
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-#include <linux/quota.h>
-],[struct mem_dqblk D;],
-samba_cv_HAVE_STRUCT_MEM_DQBLK=yes,samba_cv_HAVE_STRUCT_MEM_DQBLK=no)])
-if test "$samba_cv_HAVE_STRUCT_MEM_DQBLK"x = "yes"x; then
-       AC_DEFINE(HAVE_STRUCT_MEM_DQBLK,1,[struct mem_dqblk])
 fi
 
 # if we have struct dqblk .dqb_fsoftlimit instead of .dqb_isoftlimit on IRIX 
@@ -3201,7 +3190,6 @@ fi
 
 ##################
 # look for a working quota system
-samba_cv_SYSQUOTA_FOUND=no;
 
 if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then
 AC_CACHE_CHECK([for long quotactl(int cmd, char *special, qid_t id, caddr_t addr)],samba_cv_HAVE_QUOTACTL_4A,[
@@ -3212,7 +3200,9 @@ AC_TRY_RUN_STRICT([
 #include "${srcdir-.}/tests/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS],
            samba_cv_HAVE_QUOTACTL_4A=yes,samba_cv_HAVE_QUOTACTL_4A=no,samba_cv_HAVE_QUOTACTL_4A=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_4A" = x"yes"; then
-    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available])
+    samba_cv_sysquotas_file="lib/sysquotas_4A.c"
 fi
 fi
 
@@ -3226,7 +3216,9 @@ AC_TRY_RUN_STRICT([
            samba_cv_HAVE_QUOTACTL_4B=yes,samba_cv_HAVE_QUOTACTL_4B=no,samba_cv_HAVE_QUOTACTL_4B=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_4B" = x"yes"; then
     echo "int quotactl(const char *path, int cmd, int id, char *addr) is not reworked for the new sys_quota api"
-#    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available])
+    samba_cv_sysquotas_file="lib/sysquotas_4B.c"
 fi
 fi
 
@@ -3240,7 +3232,9 @@ AC_TRY_RUN_STRICT([
            samba_cv_HAVE_QUOTACTL_3=yes,samba_cv_HAVE_QUOTACTL_3=no,samba_cv_HAVE_QUOTACTL_3=cross)])
 if test x"$samba_cv_HAVE_QUOTACTL_3" = x"yes"; then
     echo "CRAY int quotactl (char *spec, int request, char *arg) is NOT reworked for the sys_quota api"
-#    samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+    samba_cv_SYSQUOTA_FOUND=yes;
+    AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available])
+    samba_cv_sysquotas_file="lib/sysquotas_3.c"
 fi
 fi
 
@@ -3299,6 +3293,27 @@ AC_MSG_CHECKING(whether to use the new lib/sysquotas.c interface)
 fi
 fi
 
+if test x"$samba_cv_SYSQUOTA_FOUND" != x"no" -a x"$samba_cv_found_xfs_header" = x"yes"; then
+AC_CACHE_CHECK([whether the sys_quota interface works with XFS],samba_cv_SYSQUOTA_WORKS_XFS,[
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt  -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch"
+AC_TRY_COMPILE([
+#include "confdefs.h"
+#define NO_PROTO_H 1
+#define NO_CONFIG_H 1
+#define HAVE_SYS_QUOTAS 1
+#define HAVE_XFS_QUOTAS 1
+#include "${srcdir-.}/lib/sysquotas_xfs.c"
+],[],samba_cv_SYSQUOTA_WORKS_XFS=yes,samba_cv_SYSQUOTA_WORKS_XFS=no)
+CPPFLAGS="$SAVE_CPPFLAGS"
+])
+if test x"$samba_cv_SYSQUOTA_WORKS_XFS" = x"yes"; then
+    if test x"$samba_cv_WE_USE_SYS_QUOTAS" = x"yes"; then
+       AC_DEFINE(HAVE_XFS_QUOTAS,1,[Whether xfs quota support is available])
+    fi
+fi
+fi
+
 AC_CACHE_CHECK([whether the old quota support works],samba_cv_QUOTA_WORKS,[
 SAVE_CPPFLAGS="$CPPFLAGS"
 CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt  -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch"
@@ -4021,9 +4036,15 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT"
 WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS
 
 case "$host_os" in
-       *linux*|*freebsd*)
+       *linux*)
                WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o"
                ;;
+       *freebsd5*)
+               # FreeBSD winbind client is implemented as a wrapper around
+               # the Linux version.
+               WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_freebsd.o \
+                   nsswitch/winbind_nss_linux.o"
+               ;;
        *irix*)
                # IRIX has differently named shared libraries
                WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o"
index 1d658a07681e2330d70d1faf0d45ca72aaa8cf3b..bf7c61b251ee4b47b4510860d1e605b8690aff86 100644 (file)
@@ -21,8 +21,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "includes.h"
-
 /*
    This file defines the low-level printing system interfaces used by the
    SAMBA printing subsystem.
diff --git a/source3/include/samba_linux_quota.h b/source3/include/samba_linux_quota.h
new file mode 100644 (file)
index 0000000..02b3e51
--- /dev/null
@@ -0,0 +1,336 @@
+#ifndef _SAMBA_LINUX_QUOTA_H_
+#define _SAMBA_LINUX_QUOTA_H_
+/*
+   Unix SMB/CIFS implementation.
+   Copyright (C) Andrew Tridgell 1994-2002
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+       This file is needed because Quota support on Linux has
+       been broken since Linus kernel 2.4.x. It will only get
+       better (and this file be removed) when all the distributions
+       ship a glibc with a working quota.h file. This is very
+       bad. JRA.
+
+       Original file came from Christoph Hellwig <hch@infradead.org>.
+       Massaged into one nasty include file (to stop us having to
+       add multiple files into Samba just for Linux braindamage)
+       by JRA.
+*/
+
+#undef QUOTABLOCK_SIZE
+
+#ifndef _QUOTAIO_LINUX_V1
+#define _QUOTAIO_LINUX_V1
+
+/*
+ *     Headerfile for old quotafile format
+ */
+
+#include <sys/types.h>
+
+#define V1_DQBLK_SIZE_BITS 10
+#define V1_DQBLK_SIZE (1 << V1_DQBLK_SIZE_BITS)        /* Size of one quota block in bytes in old format */
+
+#define V1_DQOFF(__id) ((loff_t) ((__id) * sizeof(struct v1_disk_dqblk)))
+
+/* Structure of quota on disk */
+struct v1_disk_dqblk {
+       u_int32_t dqb_bhardlimit;       /* absolute limit on disk blks alloc */
+       u_int32_t dqb_bsoftlimit;       /* preferred limit on disk blks */
+       u_int32_t dqb_curblocks;        /* current block count */
+       u_int32_t dqb_ihardlimit;       /* maximum # allocated inodes */
+       u_int32_t dqb_isoftlimit;       /* preferred limit on inodes */
+       u_int32_t dqb_curinodes;        /* current # allocated inodes */
+       time_t dqb_btime;       /* time limit for excessive disk use */
+       time_t dqb_itime;       /* time limit for excessive files */
+} __attribute__ ((packed));
+
+/* Structure used for communication with kernel */
+struct v1_kern_dqblk {
+       u_int32_t dqb_bhardlimit;       /* absolute limit on disk blks alloc */
+       u_int32_t dqb_bsoftlimit;       /* preferred limit on disk blks */
+       u_int32_t dqb_curblocks;        /* current block count */
+       u_int32_t dqb_ihardlimit;       /* maximum # allocated inodes */
+       u_int32_t dqb_isoftlimit;       /* preferred inode limit */
+       u_int32_t dqb_curinodes;        /* current # allocated inodes */
+       time_t dqb_btime;       /* time limit for excessive disk use */
+       time_t dqb_itime;       /* time limit for excessive files */
+};
+
+struct v1_dqstats {
+       u_int32_t lookups;
+       u_int32_t drops;
+       u_int32_t reads;
+       u_int32_t writes;
+       u_int32_t cache_hits;
+       u_int32_t allocated_dquots;
+       u_int32_t free_dquots;
+       u_int32_t syncs;
+};                                                                               
+
+#ifndef Q_V1_GETQUOTA
+#define Q_V1_GETQUOTA  0x300
+#endif
+#ifndef Q_V1_SETQUOTA
+#define Q_V1_SETQUOTA  0x400
+#endif
+
+#endif /* _QUOTAIO_LINUX_V1 */
+
+/*
+ *
+ *     Header file for disk format of new quotafile format
+ *
+ */
+
+#ifndef _QUOTAIO_LINUX_V2
+#define _QUOTAIO_LINUX_V2
+
+#include <sys/types.h>
+
+#ifndef _QUOTA_LINUX
+#define _QUOTA_LINUX
+
+#include <sys/types.h>
+
+typedef u_int32_t qid_t;       /* Type in which we store ids in memory */
+typedef u_int64_t qsize_t;     /* Type in which we store size limitations */
+
+#define MAXQUOTAS 2
+#define USRQUOTA  0            /* element used for user quotas */
+#define GRPQUOTA  1            /* element used for group quotas */
+
+/*
+ * Definitions for the default names of the quotas files.
+ */
+#define INITQFNAMES { \
+       "user",    /* USRQUOTA */ \
+       "group",   /* GRPQUOTA */ \
+       "undefined", \
+}
+
+/*
+ * Definitions of magics and versions of current quota files
+ */
+#define INITQMAGICS {\
+       0xd9c01f11,     /* USRQUOTA */\
+       0xd9c01927      /* GRPQUOTA */\
+}
+
+/* Size of blocks in which are counted size limits in generic utility parts */
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+
+/* Conversion routines from and to quota blocks */
+#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
+#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
+#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
+
+/*
+ * Command definitions for the 'quotactl' system call.
+ * The commands are broken into a main command defined below
+ * and a subcommand that is used to convey the type of
+ * quota that is being manipulated (see above).
+ */
+#define SUBCMDMASK  0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_6_5_QUOTAON  0x0100  /* enable quotas */
+#define Q_6_5_QUOTAOFF 0x0200  /* disable quotas */
+#define Q_6_5_SYNC     0x0600  /* sync disk copy of a filesystems quotas */
+
+#define Q_SYNC     0x800001    /* sync disk copy of a filesystems quotas */
+#define Q_QUOTAON  0x800002    /* turn quotas on */
+#define Q_QUOTAOFF 0x800003    /* turn quotas off */
+#define Q_GETFMT   0x800004    /* get quota format used on given filesystem */
+#define Q_GETINFO  0x800005    /* get information about quota files */
+#define Q_SETINFO  0x800006    /* set information about quota files */
+#define Q_GETQUOTA 0x800007    /* get user quota structure */
+#define Q_SETQUOTA 0x800008    /* set user quota structure */
+
+/*
+ * Quota structure used for communication with userspace via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define QIF_BLIMITS    1
+#define QIF_SPACE      2
+#define QIF_ILIMITS    4
+#define QIF_INODES     8
+#define QIF_BTIME      16
+#define QIF_ITIME      32
+#define QIF_LIMITS     (QIF_BLIMITS | QIF_ILIMITS)
+#define QIF_USAGE      (QIF_SPACE | QIF_INODES)
+#define QIF_TIMES      (QIF_BTIME | QIF_ITIME)
+#define QIF_ALL                (QIF_LIMITS | QIF_USAGE | QIF_TIMES)
+
+struct if_dqblk {
+       u_int64_t dqb_bhardlimit;
+       u_int64_t dqb_bsoftlimit;
+       u_int64_t dqb_curspace;
+       u_int64_t dqb_ihardlimit;
+       u_int64_t dqb_isoftlimit;
+       u_int64_t dqb_curinodes;
+       u_int64_t dqb_btime;
+       u_int64_t dqb_itime;
+       u_int32_t dqb_valid;
+};
+
+/*
+ * Structure used for setting quota information about file via quotactl
+ * Following flags are used to specify which fields are valid
+ */
+#define IIF_BGRACE     1
+#define IIF_IGRACE     2
+#define IIF_FLAGS      4
+#define IIF_ALL                (IIF_BGRACE | IIF_IGRACE | IIF_FLAGS)
+
+struct if_dqinfo {
+       u_int64_t dqi_bgrace;
+       u_int64_t dqi_igrace;
+       u_int32_t dqi_flags;
+       u_int32_t dqi_valid;
+};
+
+/* Quota format identifiers */
+#define QFMT_VFS_OLD 1
+#define QFMT_VFS_V0  2
+
+/* Flags supported by kernel */
+#define V1_DQF_RSQUASH 1
+
+/* Ioctl for getting quota size */
+#include <sys/ioctl.h>
+#ifndef FIOQSIZE
+       #if defined(__alpha__) || defined(__powerpc__) || defined(__sh__) || defined(__sparc__) || defined(__sparc64__)
+               #define FIOQSIZE _IOR('f', 128, loff_t)
+       #elif defined(__arm__) || defined(__mc68000__) || defined(__s390__)
+               #define FIOQSIZE 0x545E
+        #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__ia64__) || defined(__parisc__) || defined(__cris__) || defined(__hppa__)
+               #define FIOQSIZE 0x5460
+       #elif defined(__mips__) || defined(__mips64__)
+               #define FIOQSIZE 0x6667
+       #endif
+#endif
+
+long quotactl __P((int, const char *, qid_t, caddr_t));
+
+#endif /* _QUOTA_LINUX */
+
+#define V2_DQINFOOFF   sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
+#define V2_DQBLKSIZE_BITS      10
+#define V2_DQBLKSIZE   (1 << V2_DQBLKSIZE_BITS)        /* Size of block with quota structures */
+#define V2_DQTREEOFF   1       /* Offset of tree in file in blOcks */
+#define V2_DQTREEDEPTH 4       /* Depth of quota tree */
+#define V2_DQSTRINBLK  ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk))     /* Number of entries in one blocks */
+#define V2_GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
+#define V2_GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)(buf)) + sizeof(struct v2_disk_dqdbheader)))
+#define INIT_V2_VERSIONS { 0, 0}
+
+struct v2_disk_dqheader {
+       u_int32_t dqh_magic;    /* Magic number identifying file */
+       u_int32_t dqh_version;  /* File version */
+} __attribute__ ((packed));
+
+/* Flags for version specific files */
+#define V2_DQF_MASK  0x0000    /* Mask for all valid ondisk flags */
+
+/* Header with type and version specific information */
+struct v2_disk_dqinfo {
+       u_int32_t dqi_bgrace;   /* Time before block soft limit becomes hard limit */
+       u_int32_t dqi_igrace;   /* Time before inode soft limit becomes hard limit */
+       u_int32_t dqi_flags;    /* Flags for quotafile (DQF_*) */
+       u_int32_t dqi_blocks;   /* Number of blocks in file */
+       u_int32_t dqi_free_blk; /* Number of first free block in the list */
+       u_int32_t dqi_free_entry;       /* Number of block with at least one free entry */
+} __attribute__ ((packed));
+
+/*
+ *  Structure of header of block with quota structures. It is padded to 16 bytes so
+ *  there will be space for exactly 18 quota-entries in a block
+ */
+struct v2_disk_dqdbheader {
+       u_int32_t dqdh_next_free;       /* Number of next block with free entry */
+       u_int32_t dqdh_prev_free;       /* Number of previous block with free entry */
+       u_int16_t dqdh_entries; /* Number of valid entries in block */
+       u_int16_t dqdh_pad1;
+       u_int32_t dqdh_pad2;
+} __attribute__ ((packed));
+
+/* Structure of quota for one user on disk */
+struct v2_disk_dqblk {
+       u_int32_t dqb_id;       /* id this quota applies to */
+       u_int32_t dqb_ihardlimit;       /* absolute limit on allocated inodes */
+       u_int32_t dqb_isoftlimit;       /* preferred inode limit */
+       u_int32_t dqb_curinodes;        /* current # allocated inodes */
+       u_int32_t dqb_bhardlimit;       /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+       u_int32_t dqb_bsoftlimit;       /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+       u_int64_t dqb_curspace; /* current space occupied (in bytes) */
+       u_int64_t dqb_btime;    /* time limit for excessive disk use */
+       u_int64_t dqb_itime;    /* time limit for excessive inode use */
+} __attribute__ ((packed));
+
+/* Structure of quota for communication with kernel */
+struct v2_kern_dqblk {
+       unsigned int dqb_ihardlimit;
+       unsigned int dqb_isoftlimit;
+       unsigned int dqb_curinodes;
+       unsigned int dqb_bhardlimit;
+       unsigned int dqb_bsoftlimit;
+       qsize_t dqb_curspace;
+       time_t dqb_btime;
+       time_t dqb_itime;
+};
+
+/* Structure of quotafile info for communication with kernel */
+struct v2_kern_dqinfo {
+       unsigned int dqi_bgrace;
+       unsigned int dqi_igrace;
+       unsigned int dqi_flags;
+       unsigned int dqi_blocks;
+       unsigned int dqi_free_blk;
+       unsigned int dqi_free_entry;
+};
+
+/* Structure with gathered statistics from kernel */
+struct v2_dqstats {
+       u_int32_t lookups;
+       u_int32_t drops;
+       u_int32_t reads;
+       u_int32_t writes;
+       u_int32_t cache_hits;
+       u_int32_t allocated_dquots;
+       u_int32_t free_dquots;
+       u_int32_t syncs;
+       u_int32_t version;
+};
+
+#ifndef Q_V2_GETQUOTA
+#define Q_V2_GETQUOTA  0x0D00
+#endif
+#ifndef Q_V2_SETQUOTA
+#define Q_V2_SETQUOTA  0x0E00
+#endif
+
+#endif /* _QUOTAIO_LINUX_V2 */
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE        1024
+#endif
+
+#endif /* _SAMBA_LINUX_QUOTA_H_ */
diff --git a/source3/include/samba_xfs_quota.h b/source3/include/samba_xfs_quota.h
new file mode 100644 (file)
index 0000000..1db4350
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef _SAMBA_LINUX_XFS_H_
+#define _SAMBA_LINUX_XFS_H_
+
+#ifndef _QUOTAIO_LINUX_XFS
+#define _QUOTAIO_LINUX_XFS
+
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc.  All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like.  Any license provided herein, whether implied or
+ * otherwise, applies only to this software file.  Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA  94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <linux/types.h>
+
+#define XQM_CMD(cmd)   ( ('X'<<8)+(cmd) )
+#define IS_XQM_CMD(cmd)        ( ((int)(cmd)>>8) == 'X' )
+
+/*
+ * Disk quota - quotactl(2) commands for XFS Quota Manager (XQM).
+ */
+#define Q_XQUOTAON   XQM_CMD(0x1)      /* enable quota accounting/enforcement */
+#define Q_XQUOTAOFF  XQM_CMD(0x2)      /* disable quota accounting/enforcement */
+#define Q_XGETQUOTA  XQM_CMD(0x3)      /* get disk limits & usage */
+#define Q_XSETQLIM   XQM_CMD(0x4)      /* set disk limits only */
+#define Q_XGETQSTAT  XQM_CMD(0x5)      /* returns fs_quota_stat_t struct */
+#define Q_XQUOTARM   XQM_CMD(0x6)      /* free quota files' space */
+
+/*
+ * fs_disk_quota structure:
+ *
+ * This contains the current quota information regarding a user/proj/group.
+ * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of
+ * 512 bytes.
+ */
+#define FS_DQUOT_VERSION       1       /* fs_disk_quota.d_version */
+typedef struct fs_disk_quota {
+       u_int8_t d_version;             /* version of this structure */
+       u_int8_t d_flags;               /* XFS_{USER,PROJ,GROUP}_QUOTA */
+       u_int16_t d_fieldmask;  /* field specifier */
+       u_int32_t d_id;         /* user, project, or group ID */
+       u_int64_t d_blk_hardlimit;      /* absolute limit on disk blks */
+       u_int64_t d_blk_softlimit;      /* preferred limit on disk blks */
+       u_int64_t d_ino_hardlimit;      /* maximum # allocated inodes */
+       u_int64_t d_ino_softlimit;      /* preferred inode limit */
+       u_int64_t d_bcount;             /* # disk blocks owned by the user */
+       u_int64_t d_icount;             /* # inodes owned by the user */
+       int32_t d_itimer;               /* zero if within inode limits */
+       /* if not, we refuse service */
+       int32_t d_btimer;               /* similar to above; for disk blocks */
+       u_int16_t d_iwarns;             /* # warnings issued wrt num inodes */
+       u_int16_t d_bwarns;             /* # warnings issued wrt disk blocks */
+       int32_t d_padding2;     /* padding2 - for future use */
+       u_int64_t d_rtb_hardlimit;      /* absolute limit on realtime blks */
+       u_int64_t d_rtb_softlimit;      /* preferred limit on RT disk blks */
+       u_int64_t d_rtbcount;   /* # realtime blocks owned */
+       int32_t d_rtbtimer;     /* similar to above; for RT disk blks */
+       u_int16_t d_rtbwarns;   /* # warnings issued wrt RT disk blks */
+       int16_t d_padding3;     /* padding3 - for future use */
+       char d_padding4[8];     /* yet more padding */
+} fs_disk_quota_t;
+
+/*
+ * These fields are sent to Q_XSETQLIM to specify fields that need to change.
+ */
+#define FS_DQ_ISOFT    (1<<0)
+#define FS_DQ_IHARD    (1<<1)
+#define FS_DQ_BSOFT    (1<<2)
+#define FS_DQ_BHARD    (1<<3)
+#define FS_DQ_RTBSOFT  (1<<4)
+#define FS_DQ_RTBHARD  (1<<5)
+#define FS_DQ_LIMIT_MASK       (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \
+                                FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD)
+/*
+ * These timers can only be set in super user's dquot. For others, timers are
+ * automatically started and stopped. Superusers timer values set the limits
+ * for the rest.  In case these values are zero, the DQ_{F,B}TIMELIMIT values
+ * defined below are used. 
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BTIMER   (1<<6)
+#define FS_DQ_ITIMER   (1<<7)
+#define FS_DQ_RTBTIMER         (1<<8)
+#define FS_DQ_TIMER_MASK       (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
+
+/*
+ * The following constants define the default amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure).  These may be modified by the quotactl(2)
+ * system call with the Q_XSETQLIM command.
+ */
+#define        DQ_FTIMELIMIT   (7 * 24*60*60)  /* 1 week */
+#define        DQ_BTIMELIMIT   (7 * 24*60*60)  /* 1 week */
+
+/*
+ * Various flags related to quotactl(2).  Only relevant to XFS filesystems.
+ */
+#define XFS_QUOTA_UDQ_ACCT     (1<<0)  /* user quota accounting */
+#define XFS_QUOTA_UDQ_ENFD     (1<<1)  /* user quota limits enforcement */
+#define XFS_QUOTA_GDQ_ACCT     (1<<2)  /* group quota accounting */
+#define XFS_QUOTA_GDQ_ENFD     (1<<3)  /* group quota limits enforcement */
+
+#define XFS_USER_QUOTA         (1<<0)  /* user quota type */
+#define XFS_PROJ_QUOTA         (1<<1)  /* (IRIX) project quota type */
+#define XFS_GROUP_QUOTA                (1<<2)  /* group quota type */
+
+/*
+ * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system.
+ * Provides a centralized way to get meta infomation about the quota subsystem.
+ * eg. space taken up for user and group quotas, number of dquots currently
+ * incore.
+ */
+#define FS_QSTAT_VERSION       1       /* fs_quota_stat.qs_version */
+
+/*
+ * Some basic infomation about 'quota files'.
+ */
+typedef struct fs_qfilestat {
+       u_int64_t qfs_ino;              /* inode number */
+       u_int64_t qfs_nblks;    /* number of BBs 512-byte-blks */
+       u_int32_t qfs_nextents; /* number of extents */
+} fs_qfilestat_t;
+
+typedef struct fs_quota_stat {
+       u_int8_t qs_version;    /* version number for future changes */
+       u_int16_t qs_flags;             /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
+       u_int8_t qs_pad;                /* unused */
+       fs_qfilestat_t qs_uquota;       /* user quota storage information */
+       fs_qfilestat_t qs_gquota;       /* group quota storage information */
+       u_int32_t qs_incoredqs; /* number of dquots incore */
+       int32_t qs_btimelimit;  /* limit for blks timer */
+       int32_t qs_itimelimit;  /* limit for inodes timer */
+       int32_t qs_rtbtimelimit;        /* limit for rt blks timer */
+       u_int16_t qs_bwarnlimit;        /* limit for num warnings */
+       u_int16_t qs_iwarnlimit;        /* limit for num warnings */
+} fs_quota_stat_t;
+
+#endif /* _QUOTAIO_LINUX_XFS */
+
+#endif /* _SAMBA_LINUX_XFS_H_ */
index b803e6277abbf0fba70f9430aedadeacc4308712..bfb9466b3928cb86c40a734da26704aad7a0341d 100644 (file)
  
 #ifdef HAVE_SYS_QUOTAS
 
-/* Sometimes we need this on linux for linux/quota.h */
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_ASM_TYPES_H
-#include <asm/types.h>
-#endif
-
-/*
- * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
- */
-#ifdef HAVE_LINUX_QUOTA_H
-#include <linux/quota.h>
-#elif defined(HAVE_SYS_QUOTA_H)
-#include <sys/quota.h>
-#endif
-
-#if defined(HAVE_STRUCT_IF_DQBLK)
-# define SYS_DQBLK if_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#elif defined(HAVE_STRUCT_MEM_DQBLK)
-# define SYS_DQBLK mem_dqblk
-# define dqb_curblocks dqb_curspace/bsize
-#else /* STRUCT_DQBLK */
-# define SYS_DQBLK dqblk
-#endif
-
-#ifndef Q_SETQLIM
-#define Q_SETQLIM Q_SETQUOTA
-#endif
-
-/*********************************************
- check for XFS QUOTA MANAGER 
- *********************************************/
-/* on linux */
-#ifdef HAVE_LINUX_XQM_H
-# include <linux/xqm.h>
-# define HAVE_XFS_QUOTA
-#else
-# ifdef HAVE_XFS_XQM_H
-#  include <xfs/xqm.h>
-#  define HAVE_XFS_QUOTA
-# else
-#  ifdef HAVE_LINUX_DQBLK_XFS_H
-#   include <linux/dqblk_xfs.h>
-#   define HAVE_XFS_QUOTA
-#  endif 
-# endif
-#endif
-/* on IRIX */
-#ifdef Q_XGETQUOTA
-# ifndef HAVE_XFS_QUOTA
-#  define HAVE_XFS_QUOTA
-#  ifndef Q_XQUOTAON
-#   define Q_XQUOTAON Q_QUOTAON
-#  endif /* Q_XQUOTAON */
-#  ifndef Q_XQUOTAOFF
-#   define Q_XQUOTAOFF Q_QUOTAOFF
-#  endif /* Q_XQUOTAOFF */
-#  ifndef Q_XGETQSTAT
-#   define Q_XGETQSTAT Q_GETQSTAT
-#  endif /* Q_XGETQSTAT */
-# endif /* HAVE_XFS_QUOTA */
-#endif /* Q_XGETQUOTA */
-
-#ifdef HAVE_XFS_QUOTA
-/* Linux has BBSIZE in <linux/xfs_fs.h>
- * or <xfs/xfs_fs.h>
- * IRIX has BBSIZE in <sys/param.h>
- */
-#ifdef HAVE_LINUX_XFS_FS_H
-#include <linux/xfs_fs.h>
-#elif defined(HAVE_XFS_XFS_FS_H)
-#include <xfs/xfs_fs.h>
-#endif /* *_XFS_FS_H */
-
-#ifndef BBSHIFT
-#define        BBSHIFT         9
-#endif /* BBSHIFT */
-#ifndef BBSIZE
-#define        BBSIZE          (1<<BBSHIFT)
-#endif /* BBSIZE */
-
-#endif /* HAVE_XFS_QUOTA */
-
-#ifdef LINUX
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE 1024
-# endif
-/* end LINUX */
-#elif defined(IRIX6)
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE BBSIZE
-# endif
-/* end IRIX6 */
-#else /* HPUP,... */
-# ifndef QUOTABLOCK_SIZE
-#  define QUOTABLOCK_SIZE DEV_BSIZE
-# endif
-#endif /* HPUP,... */
-
-#if !defined(QUOTAFILENAME) && defined(QFILENAME)
-#define QUOTAFILENAME QFILENAME
-#endif
-
-#ifdef INITQFNAMES
-#define USERQUOTAFILE_EXTENSION ".user"
-#else
-#define USERQUOTAFILE_EXTENSION ""
-#endif
-
-/* this check should be before the QCMD fake! */
-#if defined(QCMD)&&defined(GRPQUOTA)
-#define HAVE_GROUP_QUOTA
-#endif
-
-/* on some systems we have to fake this up ...*/
-#ifndef QCMD
-#define QCMD(cmd,type) (cmd)
-#endif /* QCMD */
-
-
-#ifdef HAVE_DQB_FSOFTLIMIT
-#define dqb_isoftlimit dqb_fsoftlimit
-#define dqb_ihardlimit dqb_fhardlimit
-#define dqb_curinodes  dqb_curfiles
-#endif
-
-/* maybe we can add a configure test for HAVE_CADDR_T,
- * but it's not needed
- */
-#ifdef HAVE_CADDR_T
-#define CADDR_T caddr_t
-#else /* CADDR_T */
-#define CADDR_T void*
-#endif /* CADDR_T */
-
 #if defined(HAVE_MNTENT_H)&&defined(HAVE_SETMNTENT)&&defined(HAVE_GETMNTENT)&&defined(HAVE_ENDMNTENT)
 #include <mntent.h>
 #define HAVE_MNTENT 1
 #endif /* HAVE_SYS_QUOTAS */
 
 
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE        1024
-#endif
-
 /**************************************************
  Some stuff for the sys_quota api.
  **************************************************/ 
@@ -217,4 +69,8 @@ typedef struct _SMB_DISK_QUOTA {
        uint32       qflags;
 } SMB_DISK_QUOTA;
 
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE 1024
+#endif
+
 #endif /*_SYSQUOTAS_H */
index b98e5734cbf82ac6ad0873aed84aaebad50b0831..fe2ad5b2fce48ab811600c2f282f6efd7f127607 100644 (file)
@@ -176,7 +176,8 @@ BOOL lang_tdb_init(const char *lang)
 const char *lang_msg(const char *msgid)
 {
        TDB_DATA key, data;
-       char *p, *q, *msgid_quoted;
+       const char *p;
+       char *q, *msgid_quoted;
        int count;
 
        lang_tdb_init(NULL);
index 7903dfd3f64bcfbb38b0b07b1aa8a92a0a54e42a..1c6058a43e395aaa82b5b11e669c0b68a1077400 100644 (file)
@@ -192,7 +192,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
 
        i_len=srclen;
        o_len=destlen;
-       retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
+       retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
        if(retval==(size_t)-1) {
                const char *reason="unknown error";
                switch(errno) {
@@ -426,7 +426,7 @@ convert:
        i_len = srclen;
        o_len = destlen;
        retval = smb_iconv(descriptor,
-                          &inbuf, &i_len,
+                          (char **)&inbuf, &i_len,
                           &outbuf, &o_len);
        if(retval == (size_t)-1)                {
                const char *reason="unknown error";
index 3223ecb580b06b76437aebf4726bb87351be4638..6883444e005d6d3b47d43508ba8126321ba131bb 100644 (file)
 #ifdef HAVE_SYS_QUOTAS
 
 #if defined(HAVE_QUOTACTL_4A) 
-/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
-/* this is used by: linux,HPUX,IRIX */
-
-/****************************************************************************
- Abstract out the old and new Linux quota get calls.
-****************************************************************************/
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-       uint32 qflags = 0;
-       struct SYS_DQBLK D;
-       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
-       if (!path||!bdev||!dp)
-               smb_panic("sys_get_vfs_quota: called with NULL pointer");
-
-       ZERO_STRUCT(D);
-       ZERO_STRUCT(*dp);
-       dp->qtype = qtype;
-
-       switch (qtype) {
-               case SMB_USER_QUOTA_TYPE:
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) {
-                               return ret;
-                       }
-
-                       if ((D.dqb_curblocks==0)&&
-                               (D.dqb_bsoftlimit==0)&&
-                               (D.dqb_bhardlimit==0)) {
-                               /* the upper layer functions don't want empty quota records...*/
-                               return -1;
-                       }
-
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_QUOTA_TYPE:
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) {
-                               return ret;
-                       }
-
-                       if ((D.dqb_curblocks==0)&&
-                               (D.dqb_bsoftlimit==0)&&
-                               (D.dqb_bhardlimit==0)) {
-                               /* the upper layer functions don't want empty quota records...*/
-                               return -1;
-                       }
-
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               case SMB_USER_FS_QUOTA_TYPE:
-                       id.uid = getuid();
-
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
-                               qflags |= QUOTAS_DENY_DISK;
-                       }
-
-                       ret = 0;
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_FS_QUOTA_TYPE:
-                       id.gid = getgid();
-
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
-                               qflags |= QUOTAS_DENY_DISK;
-                       }
-
-                       ret = 0;
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               default:
-                       errno = ENOSYS;
-                       return -1;
-       }
-
-       dp->bsize = bsize;
-       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
-       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
-       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
-       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
-       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-       dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-
-
-       dp->qflags = qflags;
-
-       return ret;
-}
-
-/****************************************************************************
- Abstract out the old and new Linux quota set calls.
-****************************************************************************/
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-       uint32 qflags = 0;
-       uint32 oldqflags = 0;
-       struct SYS_DQBLK D;
-       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-
-       if (!path||!bdev||!dp)
-               smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-       ZERO_STRUCT(D);
-
-       if (bsize == dp->bsize) {
-               D.dqb_bsoftlimit = dp->softlimit;
-               D.dqb_bhardlimit = dp->hardlimit;
-               D.dqb_ihardlimit = dp->ihardlimit;
-               D.dqb_isoftlimit = dp->isoftlimit;
-       } else {
-               D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
-               D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
-               D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-               D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
-       }
-
-       qflags = dp->qflags;
-
-       switch (qtype) {
-               case SMB_USER_QUOTA_TYPE:
-                       ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_QUOTA_TYPE:
-                       ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               case SMB_USER_FS_QUOTA_TYPE:
-                       /* this stuff didn't work as it should:
-                        * switching on/off quota via quotactl()
-                        * didn't work!
-                        * So we just return 0
-                        * --metze
-                        * 
-                        * On HPUX we didn't have the mount path,
-                        * we need to fix sys_path_to_bdev()
-                        *
-                        */
-#if 0
-                       id.uid = getuid();
-
-                       ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-
-                       if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
-                               if (ret == 0) {
-                                       char *quota_file = NULL;
-                                       
-                                       asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
-                                       if (quota_file == NULL) {
-                                               DEBUG(0,("asprintf() failed!\n"));
-                                               errno = ENOMEM;
-                                               return -1;
-                                       }
-                                       
-                                       ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file);
-                               } else {
-                                       ret = 0;        
-                               }
-                       } else {
-                               if (ret != 0) {
-                                       /* turn off */
-                                       ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0);        
-                               } else {
-                                       ret = 0;
-                               }               
-                       }
-
-                       DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
-                               ret,errno,strerror(errno),id.uid,bdev));
-#else
-                       id.uid = getuid();
-
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) {
-                               oldqflags |= QUOTAS_DENY_DISK;
-                       }
-
-                       if (oldqflags == qflags) {
-                               ret = 0;
-                       } else {
-                               ret = -1;
-                       }
-#endif
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_FS_QUOTA_TYPE:
-                       /* this stuff didn't work as it should:
-                        * switching on/off quota via quotactl()
-                        * didn't work!
-                        * So we just return 0
-                        * --metze
-                        * 
-                        * On HPUX we didn't have the mount path,
-                        * we need to fix sys_path_to_bdev()
-                        *
-                        */
-#if 0
-                       id.gid = getgid();
-
-                       ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D);
-
-                       if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
-                               if (ret == 0) {
-                                       char *quota_file = NULL;
-                                       
-                                       asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
-                                       if (quota_file == NULL) {
-                                               DEBUG(0,("asprintf() failed!\n"));
-                                               errno = ENOMEM;
-                                               return -1;
-                                       }
-                                       
-                                       ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file);
-                               } else {
-                                       ret = 0;        
-                               }
-                       } else {
-                               if (ret != 0) {
-                                       /* turn off */
-                                       ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0);        
-                               } else {
-                                       ret = 0;
-                               }               
-                       }
-
-                       DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
-                               ret,errno,strerror(errno),id.gid,bdev));
-#else
-                       id.gid = getgid();
-
-                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) {
-                               oldqflags |= QUOTAS_DENY_DISK;
-                       }
-
-                       if (oldqflags == qflags) {
-                               ret = 0;
-                       } else {
-                               ret = -1;
-                       }
-#endif
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               default:
-                       errno = ENOSYS;
-                       return -1;
-       }
-
-       return ret;
-}
 
 /*#endif HAVE_QUOTACTL_4A */
 #elif defined(HAVE_QUOTACTL_4B)
@@ -287,30 +38,6 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_
 /* #endif  HAVE_QUOTACTL_3 */
 #else /* NO_QUOTACTL_USED */
 
-static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-
-       if (!path||!bdev||!dp)
-               smb_panic("sys_get_vfs_quota: called with NULL pointer");
-               
-       errno = ENOSYS;
-
-       return ret;
-}
-
-static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-
-       if (!path||!bdev||!dp)
-               smb_panic("sys_set_vfs_quota: called with NULL pointer");
-
-       errno = ENOSYS;
-
-       return ret;
-}
-
 #endif /* NO_QUOTACTL_USED */
 
 #ifdef HAVE_MNTENT
@@ -434,262 +161,6 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char
 }
 #endif
 
-
-/*********************************************************
- if we have XFS QUOTAS we should use them
- *********************************************************/
-#ifdef HAVE_XFS_QUOTA
-/****************************************************************************
- Abstract out the XFS Quota Manager quota get call.
-****************************************************************************/
-static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-       uint32 qflags = 0;
-       SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
-       struct fs_disk_quota D;
-       struct fs_quota_stat F;
-       ZERO_STRUCT(D);
-       ZERO_STRUCT(F);
-
-       if (!bdev||!dp)
-               smb_panic("sys_get_xfs_quota: called with NULL pointer");
-               
-       ZERO_STRUCT(*dp);
-       dp->qtype = qtype;
-               
-       switch (qtype) {
-               case SMB_USER_QUOTA_TYPE:
-                       if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D)))
-                               return ret;
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_QUOTA_TYPE:
-                       if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D)))
-                               return ret;
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               case SMB_USER_FS_QUOTA_TYPE:    
-                       quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-
-                       if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
-                               qflags |= QUOTAS_DENY_DISK;
-                       }
-                       else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
-                               qflags |= QUOTAS_ENABLED;
-                       }
-
-                       ret = 0;
-
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_FS_QUOTA_TYPE:   
-                       quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-
-                       if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
-                               qflags |= QUOTAS_DENY_DISK;
-                       }
-                       else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
-                               qflags |= QUOTAS_ENABLED;
-                       }
-
-                       ret = 0;
-
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               default:
-                       errno = ENOSYS;
-                       return -1;
-       }
-
-       dp->bsize = bsize;
-       dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
-       dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
-       dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
-       dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
-       dp->curinodes = (SMB_BIG_UINT)D.d_icount;
-       dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-       dp->qflags = qflags;
-
-       return ret;
-}
-
-/****************************************************************************
- Abstract out the XFS Quota Manager quota set call.
-****************************************************************************/
-static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
-{
-       int ret = -1;
-       uint32 qflags = 0;
-       SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
-       struct fs_disk_quota D;
-       struct fs_quota_stat F;
-       int q_on = 0;
-       int q_off = 0;
-       ZERO_STRUCT(D);
-       ZERO_STRUCT(F);
-
-       if (!bdev||!dp)
-               smb_panic("sys_set_xfs_quota: called with NULL pointer");
-       
-       if (bsize == dp->bsize) {
-               D.d_blk_softlimit = dp->softlimit;
-               D.d_blk_hardlimit = dp->hardlimit;
-               D.d_ino_hardlimit = dp->ihardlimit;
-               D.d_ino_softlimit = dp->isoftlimit;
-       } else {
-               D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
-               D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
-               D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
-               D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;           
-       }
-
-       qflags = dp->qflags;
-
-       switch (qtype) {
-               case SMB_USER_QUOTA_TYPE:
-                       D.d_fieldmask |= FS_DQ_LIMIT_MASK;
-                       ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D);
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_QUOTA_TYPE:
-                       D.d_fieldmask |= FS_DQ_LIMIT_MASK;
-                       ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D);
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               case SMB_USER_FS_QUOTA_TYPE:
-                       quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F);
-                       
-                       if (qflags & QUOTAS_DENY_DISK) {
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
-                                       q_on |= XFS_QUOTA_UDQ_ENFD;
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-                                       q_on |= XFS_QUOTA_UDQ_ACCT;
-                               
-                               if (q_on != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
-                               } else {
-                                       ret = 0;
-                               }
-
-                       } else if (qflags & QUOTAS_ENABLED) {
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-                                       q_off |= XFS_QUOTA_UDQ_ENFD;
-
-                               if (q_off != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
-                               } else {
-                                       ret = 0;
-                               }
-
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-                                       q_on |= XFS_QUOTA_UDQ_ACCT;
-
-                               if (q_on != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on);
-                               } else {
-                                       ret = 0;
-                               }
-                       } else {
-#if 0
-                       /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
-                        * only swittching off XFS_QUOTA_UDQ_ACCT work
-                        */
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-                                       q_off |= XFS_QUOTA_UDQ_ENFD;
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
-                                       q_off |= XFS_QUOTA_UDQ_ACCT;
-
-                               if (q_off !=0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off);
-                               } else {
-                                       ret = 0;
-                               }
-#else
-                               ret = -1;
-#endif
-                       }
-
-                       break;
-#ifdef HAVE_GROUP_QUOTA
-               case SMB_GROUP_FS_QUOTA_TYPE:
-                       quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F);
-                       
-                       if (qflags & QUOTAS_DENY_DISK) {
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
-                                       q_on |= XFS_QUOTA_UDQ_ENFD;
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-                                       q_on |= XFS_QUOTA_UDQ_ACCT;
-                               
-                               if (q_on != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
-                               } else {
-                                       ret = 0;
-                               }
-
-                       } else if (qflags & QUOTAS_ENABLED) {
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-                                       q_off |= XFS_QUOTA_UDQ_ENFD;
-
-                               if (q_off != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
-                               } else {
-                                       ret = 0;
-                               }
-
-                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
-                                       q_on |= XFS_QUOTA_UDQ_ACCT;
-
-                               if (q_on != 0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on);
-                               } else {
-                                       ret = 0;
-                               }
-                       } else {
-#if 0
-                       /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
-                        * only swittching off XFS_QUOTA_UDQ_ACCT work
-                        */
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
-                                       q_off |= XFS_QUOTA_UDQ_ENFD;
-                               if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
-                                       q_off |= XFS_QUOTA_UDQ_ACCT;
-
-                               if (q_off !=0) {
-                                       ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off);
-                               } else {
-                                       ret = 0;
-                               }
-#else
-                               ret = -1;
-#endif
-                       }
-
-                       break;
-#endif /* HAVE_GROUP_QUOTA */
-               default:
-                       errno = ENOSYS;
-                       return -1;
-       }
-
-       return ret;
-}
-#endif /* HAVE_XFS_QUOTA */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 /*********************************************************************
  Now the list of all filesystem specific quota systems we have found
 **********************************************************************/
diff --git a/source3/lib/sysquotas_4A.c b/source3/lib/sysquotas_4A.c
new file mode 100644 (file)
index 0000000..66b367f
--- /dev/null
@@ -0,0 +1,318 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for QUOTACTL_4A
+   Copyright (C) Stefan (metze) Metzmacher     2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "includes.h"
+
+#ifdef HAVE_QUOTACTL_4A
+/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
+/* this is used by: HPUX,IRIX */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_ASM_TYPES_H
+#include <asm/types.h>
+#endif
+
+#ifdef HAVE_SYS_QUOTA_H
+#include <sys/quota.h>
+#endif
+
+#ifndef Q_SETQLIM
+#define Q_SETQLIM Q_SETQUOTA
+#endif
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+#ifdef GRPQUOTA
+#define HAVE_GROUP_QUOTA
+#endif
+
+#ifndef QUOTABLOCK_SIZE
+#define QUOTABLOCK_SIZE DEV_BSIZE
+#endif
+
+#ifdef HAVE_DQB_FSOFTLIMIT
+#define dqb_isoftlimit dqb_fsoftlimit
+#define dqb_ihardlimit dqb_fhardlimit
+#define dqb_curinodes  dqb_curfiles
+#endif
+
+#ifdef INITQFNAMES
+#define USERQUOTAFILE_EXTENSION ".user"
+#else
+#define USERQUOTAFILE_EXTENSION ""
+#endif
+
+#if !defined(QUOTAFILENAME) && defined(QFILENAME)
+#define QUOTAFILENAME QFILENAME
+#endif
+
+/****************************************************************************
+ Abstract out the quotactl_4A get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       struct dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+       ZERO_STRUCT(*dp);
+       dp->qtype = qtype;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       if ((D.dqb_curblocks==0)&&
+                               (D.dqb_bsoftlimit==0)&&
+                               (D.dqb_bhardlimit==0)) {
+                               /* the upper layer functions don't want empty quota records...*/
+                               return -1;
+                       }
+
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       if ((D.dqb_curblocks==0)&&
+                               (D.dqb_bsoftlimit==0)&&
+                               (D.dqb_bhardlimit==0)) {
+                               /* the upper layer functions don't want empty quota records...*/
+                               return -1;
+                       }
+
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               case SMB_USER_FS_QUOTA_TYPE:
+                       id.uid = getuid();
+
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       ret = 0;
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       id.gid = getgid();
+
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       ret = 0;
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       dp->bsize = bsize;
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+       dp->qflags = qflags;
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the quotactl_4A set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       uint32 oldqflags = 0;
+       struct dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       if (bsize == dp->bsize) {
+               D.dqb_bsoftlimit = dp->softlimit;
+               D.dqb_bhardlimit = dp->hardlimit;
+               D.dqb_ihardlimit = dp->ihardlimit;
+               D.dqb_isoftlimit = dp->isoftlimit;
+       } else {
+               D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+               D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+               D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+               D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+       }
+
+       qflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (void *)&D);
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (void *)&D);
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               case SMB_USER_FS_QUOTA_TYPE:
+                       /* this stuff didn't work as it should:
+                        * switching on/off quota via quotactl()
+                        * didn't work!
+                        * So we just return 0
+                        * --metze
+                        * 
+                        * On HPUX we didn't have the mount path,
+                        * we need to fix sys_path_to_bdev()
+                        *
+                        */
+#if 0
+                       id.uid = getuid();
+
+                       ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D);
+
+                       if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+                               if (ret == 0) {
+                                       char *quota_file = NULL;
+                                       
+                                       asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
+                                       if (quota_file == NULL) {
+                                               DEBUG(0,("asprintf() failed!\n"));
+                                               errno = ENOMEM;
+                                               return -1;
+                                       }
+                                       
+                                       ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(void *)quota_file);
+                               } else {
+                                       ret = 0;        
+                               }
+                       } else {
+                               if (ret != 0) {
+                                       /* turn off */
+                                       ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (void *)0); 
+                               } else {
+                                       ret = 0;
+                               }               
+                       }
+
+                       DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+                               ret,errno,strerror(errno),id.uid,bdev));
+#else
+                       id.uid = getuid();
+
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (void *)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       if (oldqflags == qflags) {
+                               ret = 0;
+                       } else {
+                               ret = -1;
+                       }
+#endif
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       /* this stuff didn't work as it should:
+                        * switching on/off quota via quotactl()
+                        * didn't work!
+                        * So we just return 0
+                        * --metze
+                        * 
+                        * On HPUX we didn't have the mount path,
+                        * we need to fix sys_path_to_bdev()
+                        *
+                        */
+#if 0
+                       id.gid = getgid();
+
+                       ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (void *)&D);
+
+                       if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
+                               if (ret == 0) {
+                                       char *quota_file = NULL;
+                                       
+                                       asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
+                                       if (quota_file == NULL) {
+                                               DEBUG(0,("asprintf() failed!\n"));
+                                               errno = ENOMEM;
+                                               return -1;
+                                       }
+                                       
+                                       ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(void *)quota_file);
+                               } else {
+                                       ret = 0;        
+                               }
+                       } else {
+                               if (ret != 0) {
+                                       /* turn off */
+                                       ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (void *)0); 
+                               } else {
+                                       ret = 0;
+                               }               
+                       }
+
+                       DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
+                               ret,errno,strerror(errno),id.gid,bdev));
+#else
+                       id.gid = getgid();
+
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (void *)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       if (oldqflags == qflags) {
+                               ret = 0;
+                       } else {
+                               ret = -1;
+                       }
+#endif
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+#else /* HAVE_QUOTACTL_4A */
+ void dummy_sysquotas_4A(void){}
+#endif /* HAVE_QUOTACTL_4A */
diff --git a/source3/lib/sysquotas_linux.c b/source3/lib/sysquotas_linux.c
new file mode 100644 (file)
index 0000000..be42fa2
--- /dev/null
@@ -0,0 +1,485 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for LINUX
+   Copyright (C) Stefan (metze) Metzmacher     2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "includes.h"
+
+#ifdef HAVE_QUOTACTL_LINUX 
+
+#include "samba_linux_quota.h"
+
+/****************************************************************************
+ Abstract out the v1 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       struct v1_kern_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       dp->bsize = bsize;
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+
+       dp->qflags = qflags;
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the v1 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v1_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       uint32 oldqflags = 0;
+       struct v1_kern_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       if (bsize == dp->bsize) {
+               D.dqb_bsoftlimit = dp->softlimit;
+               D.dqb_bhardlimit = dp->hardlimit;
+               D.dqb_ihardlimit = dp->ihardlimit;
+               D.dqb_isoftlimit = dp->isoftlimit;
+       } else {
+               D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+               D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+               D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+               D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+       }
+
+       qflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_V1_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_V1_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       struct v2_kern_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       dp->bsize = bsize;
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+       dp->qflags = qflags;
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the v2 Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_v2_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       uint32 oldqflags = 0;
+       struct v2_kern_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       if (bsize == dp->bsize) {
+               D.dqb_bsoftlimit = dp->softlimit;
+               D.dqb_bhardlimit = dp->hardlimit;
+               D.dqb_ihardlimit = dp->ihardlimit;
+               D.dqb_isoftlimit = dp->isoftlimit;
+       } else {
+               D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+               D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+               D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+               D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+       }
+
+       qflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_V2_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_V2_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the generic Linux quota get calls.
+****************************************************************************/
+static int sys_get_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       struct if_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))&&errno != EDQUOT) {
+                               return ret;
+                       }
+
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       dp->bsize = bsize;
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = (SMB_BIG_UINT)D.dqb_curspace/bsize;
+
+
+       dp->qflags = qflags;
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the gen Linux quota set calls.
+****************************************************************************/
+static int sys_set_linux_gen_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       uint32 oldqflags = 0;
+       struct if_dqblk D;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+
+       ZERO_STRUCT(D);
+
+       if (bsize == dp->bsize) {
+               D.dqb_bsoftlimit = dp->softlimit;
+               D.dqb_bhardlimit = dp->hardlimit;
+               D.dqb_ihardlimit = dp->ihardlimit;
+               D.dqb_isoftlimit = dp->isoftlimit;
+       } else {
+               D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
+               D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
+               D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+               D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
+       }
+
+       qflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
+                       break;
+               case SMB_GROUP_QUOTA_TYPE:
+                       ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))==0) {
+                               oldqflags |= QUOTAS_DENY_DISK;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota get calls.
+****************************************************************************/
+int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+
+       if (!path||!bdev||!dp)
+               smb_panic("sys_set_vfs_quota: called with NULL pointer");
+
+       ZERO_STRUCT(*dp);
+       dp->qtype = qtype;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                               if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                                       if ((ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                                               return ret;
+                                       }
+                               }
+                       }
+
+                       if ((dp->curblocks==0)&&
+                               (dp->softlimit==0)&&
+                               (dp->hardlimit==0)) {
+                               /* the upper layer functions don't want empty quota records...*/
+                               return -1;
+                       }
+
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       id.uid = getuid();
+
+                       if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                               if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                                       ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+                               }
+                       }
+
+                       ret = 0;
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       id.gid = getgid();
+
+                       if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                               if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))&&errno != EDQUOT) {
+                                       ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+                               }
+                       }
+
+                       ret = 0;
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the Linux quota set calls.
+****************************************************************************/
+int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 oldqflags = 0;
+
+       if (!path||!bdev||!dp)
+               smb_panic("sys_set_vfs_quota: called with NULL pointer");
+
+       oldqflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret=sys_set_linux_gen_quota(path, bdev, qtype, id, dp))) {
+                               if ((ret=sys_set_linux_v2_quota(path, bdev, qtype, id, dp))) {
+                                       if ((ret=sys_set_linux_v1_quota(path, bdev, qtype, id, dp))) {
+                                               return ret;
+                                       }
+                               }
+                       }
+                       break;
+               case SMB_USER_FS_QUOTA_TYPE:
+                       id.uid = getuid();
+
+                       if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+                               if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+                                       ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+                               }
+                       }
+
+                       if (oldqflags == dp->qflags) {
+                               ret = 0;
+                       } else {
+                               ret = -1;
+                       }
+                       break;
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       id.gid = getgid();
+
+                       if ((ret=sys_get_linux_gen_quota(path, bdev, qtype, id, dp))) {
+                               if ((ret=sys_get_linux_v2_quota(path, bdev, qtype, id, dp))) {
+                                       ret=sys_get_linux_v1_quota(path, bdev, qtype, id, dp);
+                               }
+                       }
+
+                       if (oldqflags == dp->qflags) {
+                               ret = 0;
+                       } else {
+                               ret = -1;
+                       }
+
+                       break;
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+#else /* HAVE_QUOTACTL_LINUX */
+ void dummy_sysquotas_linux(void){}
+#endif /* HAVE_QUOTACTL_LINUX */
diff --git a/source3/lib/sysquotas_xfs.c b/source3/lib/sysquotas_xfs.c
new file mode 100644 (file)
index 0000000..6d7d9f9
--- /dev/null
@@ -0,0 +1,306 @@
+/* 
+   Unix SMB/CIFS implementation.
+   System QUOTA function wrappers for XFS
+   Copyright (C) Stefan (metze) Metzmacher     2003
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+#include "includes.h"
+
+#ifndef HAVE_SYS_QUOTAS
+#ifdef HAVE_XFS_QUOTAS
+#undef HAVE_XFS_QUOTAS
+#endif
+#endif
+
+#ifdef HAVE_XFS_QUOTAS
+
+#ifdef HAVE_LINUX_XFS_QUOTAS
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
+#define HAVE_GROUP_QUOTA
+#else /* IRIX */
+#include <sys/quota.h> 
+#endif
+
+/* on IRIX */
+#ifndef Q_XQUOTAON
+#define Q_XQUOTAON Q_QUOTAON
+#endif /* Q_XQUOTAON */
+#ifndef Q_XQUOTAOFF
+#define Q_XQUOTAOFF Q_QUOTAOFF
+#endif /* Q_XQUOTAOFF */
+#ifndef Q_XGETQSTAT
+#define Q_XGETQSTAT Q_GETQSTAT
+#endif /* Q_XGETQSTAT */
+
+/* currently doesn't support Group and Project quotas on IRIX 
+ */
+
+#ifndef QCMD
+#define QCMD(x,y) x
+#endif
+
+/*
+ * IRIX has BBSIZE in <sys/param.h>
+ */
+#ifndef BBSHIFT
+#define        BBSHIFT         9
+#endif /* BBSHIFT */
+#ifndef BBSIZE
+#define        BBSIZE          (1<<BBSHIFT)
+#endif /* BBSIZE */
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota get call.
+****************************************************************************/
+int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+       struct fs_disk_quota D;
+       struct fs_quota_stat F;
+       ZERO_STRUCT(D);
+       ZERO_STRUCT(F);
+
+       if (!bdev||!dp)
+               smb_panic("sys_get_xfs_quota: called with NULL pointer");
+               
+       ZERO_STRUCT(*dp);
+       dp->qtype = qtype;
+               
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D)))
+                               return ret;
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_QUOTA_TYPE:
+                       if ((ret=quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D)))
+                               return ret;
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               case SMB_USER_FS_QUOTA_TYPE:    
+                       quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+
+                       if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+                       else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) {
+                               qflags |= QUOTAS_ENABLED;
+                       }
+
+                       ret = 0;
+
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_FS_QUOTA_TYPE:   
+                       quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+
+                       if (F.qs_flags & XFS_QUOTA_GDQ_ENFD) {
+                               qflags |= QUOTAS_DENY_DISK;
+                       }
+                       else if (F.qs_flags & XFS_QUOTA_GDQ_ACCT) {
+                               qflags |= QUOTAS_ENABLED;
+                       }
+
+                       ret = 0;
+
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       dp->bsize = bsize;
+       dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.d_icount;
+       dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
+       dp->qflags = qflags;
+
+       return ret;
+}
+
+/****************************************************************************
+ Abstract out the XFS Quota Manager quota set call.
+****************************************************************************/
+int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
+{
+       int ret = -1;
+       uint32 qflags = 0;
+       SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE;
+       struct fs_disk_quota D;
+       struct fs_quota_stat F;
+       int q_on = 0;
+       int q_off = 0;
+       ZERO_STRUCT(D);
+       ZERO_STRUCT(F);
+
+       if (!bdev||!dp)
+               smb_panic("sys_set_xfs_quota: called with NULL pointer");
+       
+       if (bsize == dp->bsize) {
+               D.d_blk_softlimit = dp->softlimit;
+               D.d_blk_hardlimit = dp->hardlimit;
+               D.d_ino_hardlimit = dp->ihardlimit;
+               D.d_ino_softlimit = dp->isoftlimit;
+       } else {
+               D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize;
+               D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize;
+               D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize;
+               D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize;           
+       }
+
+       qflags = dp->qflags;
+
+       switch (qtype) {
+               case SMB_USER_QUOTA_TYPE:
+                       D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+                       ret = quotactl(QCMD(Q_XSETQLIM,XFS_USER_QUOTA), bdev, id.uid, (caddr_t)&D);
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_QUOTA_TYPE:
+                       D.d_fieldmask |= FS_DQ_LIMIT_MASK;
+                       ret = quotactl(QCMD(Q_XSETQLIM,XFS_GROUP_QUOTA), bdev, id.gid, (caddr_t)&D);
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               case SMB_USER_FS_QUOTA_TYPE:
+                       quotactl(QCMD(Q_XGETQSTAT,XFS_USER_QUOTA), bdev, -1, (caddr_t)&F);
+                       
+                       if (qflags & QUOTAS_DENY_DISK) {
+                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD))
+                                       q_on |= XFS_QUOTA_UDQ_ENFD;
+                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+                                       q_on |= XFS_QUOTA_UDQ_ACCT;
+                               
+                               if (q_on != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+                               } else {
+                                       ret = 0;
+                               }
+
+                       } else if (qflags & QUOTAS_ENABLED) {
+                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+                                       q_off |= XFS_QUOTA_UDQ_ENFD;
+
+                               if (q_off != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+                               } else {
+                                       ret = 0;
+                               }
+
+                               if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT))
+                                       q_on |= XFS_QUOTA_UDQ_ACCT;
+
+                               if (q_on != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAON,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_on);
+                               } else {
+                                       ret = 0;
+                               }
+                       } else {
+#if 0
+                       /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+                        * only swittching off XFS_QUOTA_UDQ_ACCT work
+                        */
+                               if (F.qs_flags & XFS_QUOTA_UDQ_ENFD)
+                                       q_off |= XFS_QUOTA_UDQ_ENFD;
+                               if (F.qs_flags & XFS_QUOTA_UDQ_ACCT)
+                                       q_off |= XFS_QUOTA_UDQ_ACCT;
+
+                               if (q_off !=0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_USER_QUOTA),bdev, -1, (caddr_t)&q_off);
+                               } else {
+                                       ret = 0;
+                               }
+#else
+                               ret = -1;
+#endif
+                       }
+
+                       break;
+#ifdef HAVE_GROUP_QUOTA
+               case SMB_GROUP_FS_QUOTA_TYPE:
+                       quotactl(QCMD(Q_XGETQSTAT,XFS_GROUP_QUOTA), bdev, -1, (caddr_t)&F);
+                       
+                       if (qflags & QUOTAS_DENY_DISK) {
+                               if (!(F.qs_flags & XFS_QUOTA_GDQ_ENFD))
+                                       q_on |= XFS_QUOTA_GDQ_ENFD;
+                               if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT))
+                                       q_on |= XFS_QUOTA_GDQ_ACCT;
+                               
+                               if (q_on != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+                               } else {
+                                       ret = 0;
+                               }
+
+                       } else if (qflags & QUOTAS_ENABLED) {
+                               if (F.qs_flags & XFS_QUOTA_GDQ_ENFD)
+                                       q_off |= XFS_QUOTA_GDQ_ENFD;
+
+                               if (q_off != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+                               } else {
+                                       ret = 0;
+                               }
+
+                               if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT))
+                                       q_on |= XFS_QUOTA_GDQ_ACCT;
+
+                               if (q_on != 0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAON,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_on);
+                               } else {
+                                       ret = 0;
+                               }
+                       } else {
+#if 0
+                       /* Switch on XFS_QUOTA_UDQ_ACCT didn't work!
+                        * only swittching off XFS_QUOTA_UDQ_ACCT work
+                        */
+                               if (F.qs_flags & XFS_QUOTA_GDQ_ENFD)
+                                       q_off |= XFS_QUOTA_GDQ_ENFD;
+                               if (F.qs_flags & XFS_QUOTA_GDQ_ACCT)
+                                       q_off |= XFS_QUOTA_GDQ_ACCT;
+
+                               if (q_off !=0) {
+                                       ret = quotactl(QCMD(Q_XQUOTAOFF,XFS_GROUP_QUOTA),bdev, -1, (caddr_t)&q_off);
+                               } else {
+                                       ret = 0;
+                               }
+#else
+                               ret = -1;
+#endif
+                       }
+
+                       break;
+#endif /* HAVE_GROUP_QUOTA */
+               default:
+                       errno = ENOSYS;
+                       return -1;
+       }
+
+       return ret;
+}
+
+#else /* HAVE_XFS_QUOTAS */
+ void dummy_sysquotas_xfs(void){}
+#endif /* HAVE_XFS_QUOTAS */
index ad5de38581dbe1c4fdd5bf386aaa0f8c7214e628..0cdf693bb91c84a1ec7689c0f32ed5521a4b11d1 100644 (file)
@@ -51,9 +51,9 @@ int main(void)
        }
 
        for (i = 0; i < NCTX; i++) {
-               printf("talloc@%p %-40s %dkB\n", ctx[i],
+               printf("talloc@%p %-40s %ldkB\n", ctx[i],
                       talloc_pool_name(ctx[i]),
-                      talloc_pool_size(ctx[i]) >> 10);
+                      (unsigned long)talloc_pool_size(ctx[i]) >> 10);
        }
 
        printf("%s", talloc_describe_all(ctx[0]));
index 635ede9be2278d7bcdadef73e57ad09e778870fc..faca2cba879b78f62782bfd2fae3d2413350dc8e 100644 (file)
@@ -465,10 +465,9 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
        nt->low=~nt->low;
 }
 
-
 /****************************************************************************
-take an NTTIME structure, containing high / low time.  convert to unix time.
-lkclXXXX this may need 2 SIVALs not a memcpy.  we'll see...
+take a Unix time and convert to an NTTIME structure and place in buffer 
+pointed to by p.
 ****************************************************************************/
 void put_long_date(char *p,time_t t)
 {
index f552b38e67c0013daf8df0d35049f15ed68278db..d93f39696f4862234b1ff9a4313f40cf83310a56 100644 (file)
@@ -697,7 +697,7 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
 
        if (!dest) {
                DEBUG(0,("ERROR: NULL dest in StrnCpy, called from [%s][%d]\n", fn, line));
-               return NULL;
+               return(NULL);
        }
 
        if (!src) {
@@ -1196,7 +1196,7 @@ char *strchr_m(const char *src, char c)
 
        for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
                if (*s == c)
-                       return s;
+                       return (char *)s;
        }
 
        if (!*s)
@@ -1244,7 +1244,7 @@ char *strrchr_m(const char *s, char c)
                                        break;
                                }
                                /* No - we have a match ! */
-                               return cp;
+                               return (char *)cp;
                        }
                } while (cp-- != s);
                if (!got_mb)
index 51228035974b1036bb1c8486c6edf4ebff5ea1a5..1ab71c6ee514fbae1ddd25699ba09fe8b026cd33 100644 (file)
@@ -124,13 +124,13 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
 {
        DATA_BLOB blob;
        struct berval cred, *scred;
-       unsigned char sk[16];
+       DATA_BLOB session_key;
        int rc;
 
-       blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, sk);
+       rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key);
 
-       if (!blob.data) {
-               return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+       if (rc) {
+               return ADS_ERROR_KRB5(rc);
        }
 
        /* now send the auth packet and we should be done */
@@ -140,6 +140,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
        rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
 
        data_blob_free(&blob);
+       data_blob_free(&session_key);
 
        return ADS_ERROR(rc);
 }
@@ -166,6 +167,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
 
        blob = data_blob(scred->bv_val, scred->bv_len);
 
+       ber_bvfree(scred);
+
 #if 0
        file_save("sasl_spnego.dat", blob.data, blob.length);
 #endif
@@ -196,9 +199,13 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
                status = ads_sasl_spnego_krb5_bind(ads, principal);
                if (ADS_ERR_OK(status))
                        return status;
-               if (ads_kinit_password(ads) == 0) {
+
+               status = ADS_ERROR_KRB5(ads_kinit_password(ads)); 
+
+               if (ADS_ERR_OK(status)) {
                        status = ads_sasl_spnego_krb5_bind(ads, principal);
                }
+
                /* only fallback to NTLMSSP if allowed */
                if (ADS_ERR_OK(status) || 
                    !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
index 28de7fc9f3f40e354ea44967ffdb487245840aba..707a33881df810772d33fcc46226d8fb028b639c 100644 (file)
@@ -53,6 +53,13 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, const char *user,
        if (passlen > sizeof(pword)-1)
                return False;
 
+       /* LANMAN servers predate NT status codes and Unicode and ignore those 
+          smb flags so we must disable the corresponding default capabilities  
+          that would otherwise cause the Unicode and NT Status flags to be
+          set (and even returned by the server) */
+
+       cli->capabilities &= ~(CAP_UNICODE | CAP_STATUS32);
+
        /* if in share level security then don't send a password now */
        if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
                passlen = 0;
@@ -493,19 +500,22 @@ static void use_in_memory_ccache(void) {
  Do a spnego/kerberos encrypted session setup.
 ****************************************************************************/
 
-static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
+static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup)
 {
        DATA_BLOB blob2, negTokenTarg;
        DATA_BLOB session_key_krb5;
        DATA_BLOB null_blob = data_blob(NULL, 0);
-       
+       int rc;
+
        DEBUG(2,("Doing kerberos session setup\n"));
 
        /* generate the encapsulated kerberos5 ticket */
-       negTokenTarg = spnego_gen_negTokenTarg(principal, 0, &session_key_krb5);
+       rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
 
-       if (!negTokenTarg.data)
-               return NT_STATUS_UNSUCCESSFUL;
+       if (rc) {
+               DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
+               return ADS_ERROR_KRB5(rc);
+       }
 
 #if 0
        file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length);
@@ -524,10 +534,10 @@ static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *pr
 
        if (cli_is_error(cli)) {
                if (NT_STATUS_IS_OK(cli_nt_error(cli))) {
-                       return NT_STATUS_UNSUCCESSFUL;
+                       return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
                }
        } 
-       return NT_STATUS_OK;
+       return ADS_ERROR_NT(cli_nt_error(cli));
 }
 #endif /* HAVE_KRB5 */
 
@@ -537,7 +547,7 @@ static NTSTATUS cli_session_setup_kerberos(struct cli_state *cli, const char *pr
 ****************************************************************************/
 
 static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, 
-                                     const char *pass, const char *workgroup)
+                                         const char *pass, const char *domain)
 {
        struct ntlmssp_state *ntlmssp_state;
        NTSTATUS nt_status;
@@ -556,7 +566,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
                return nt_status;
        }
-       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, workgroup))) {
+       if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
                return nt_status;
        }
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_password(ntlmssp_state, pass))) {
@@ -654,8 +664,8 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
  Do a spnego encrypted session setup.
 ****************************************************************************/
 
-NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
-                             const char *pass, const char *workgroup)
+ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, 
+                             const char *pass, const char *domain)
 {
        char *principal;
        char *OIDs[ASN1_MAX_OIDS];
@@ -682,7 +692,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
           reply */
        if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
                data_blob_free(&blob);
-               return NT_STATUS_INVALID_PARAMETER;
+               return ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
        }
        data_blob_free(&blob);
 
@@ -712,11 +722,11 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                        
                        if (ret){
                                DEBUG(0, ("Kinit failed: %s\n", error_message(ret)));
-                               return NT_STATUS_LOGON_FAILURE;
+                               return ADS_ERROR_KRB5(ret);
                        }
                }
                
-               return cli_session_setup_kerberos(cli, principal, workgroup);
+               return cli_session_setup_kerberos(cli, principal, domain);
        }
 #endif
 
@@ -724,7 +734,7 @@ NTSTATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
 
 ntlmssp:
 
-       return cli_session_setup_ntlmssp(cli, user, pass, workgroup);
+       return ADS_ERROR_NT(cli_session_setup_ntlmssp(cli, user, pass, domain));
 }
 
 /****************************************************************************
@@ -805,9 +815,9 @@ BOOL cli_session_setup(struct cli_state *cli,
        /* if the server supports extended security then use SPNEGO */
 
        if (cli->capabilities & CAP_EXTENDED_SECURITY) {
-               NTSTATUS nt_status;
-               if (!NT_STATUS_IS_OK(nt_status = cli_session_setup_spnego(cli, user, pass, workgroup))) {
-                       DEBUG(3, ("SPENGO login failed: %s\n", get_friendly_nt_error_msg(nt_status)));
+               ADS_STATUS status = cli_session_setup_spnego(cli, user, pass, workgroup);
+               if (!ADS_ERR_OK(status)) {
+                       DEBUG(3, ("SPENGO login failed: %s\n", ads_errstr(status)));
                        return False;
                }
                return True;
index 5568b5e033253ec82aedce4ad353dd89f05cc5c9..15b244a83dc273ce6e72679e1801b5d6fd424546 100644 (file)
@@ -307,14 +307,14 @@ cleanup_princ:
 /*
   get a kerberos5 ticket for the given service 
 */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
+int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
 {
        krb5_error_code retval;
        krb5_data packet;
        krb5_ccache ccdef;
        krb5_context context;
        krb5_auth_context auth_context = NULL;
-       DATA_BLOB ret;
        krb5_enctype enc_types[] = {
 #ifdef ENCTYPE_ARCFOUR_HMAC
                ENCTYPE_ARCFOUR_HMAC,
@@ -356,17 +356,18 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BL
 
        get_krb5_smb_session_key(context, auth_context, session_key_krb5, False);
 
-       ret = data_blob(packet.data, packet.length);
+       *ticket = data_blob(packet.data, packet.length);
+
 /* Hmm, heimdal dooesn't have this - what's the correct call? */
-/*     krb5_free_data_contents(context, &packet); */
-       krb5_free_context(context);
-       return ret;
+#ifdef HAVE_KRB5_FREE_DATA_CONTENTS
+       krb5_free_data_contents(context, &packet); 
+#endif
 
 failed:
        if ( context )
                krb5_free_context(context);
                
-       return data_blob(NULL, 0);
+       return retval;
 }
 
  BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, BOOL remote)
@@ -410,10 +411,11 @@ failed:
 
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
-DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, DATA_BLOB *session_key_krb5)
- {
+int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5) 
+{
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
-        return data_blob(NULL, 0);
- }
+        return 1;
+}
 
 #endif
index 92543736ff258b767ee766c6a258965c055d8426..e6cadc466c17e501e18946913b8dc909511ef5da 100644 (file)
@@ -323,27 +323,30 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
    generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
    kerberos session setup 
 */
-DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, DATA_BLOB *session_key_krb5)
+int spnego_gen_negTokenTarg(const char *principal, int time_offset, 
+                           DATA_BLOB *targ, 
+                           DATA_BLOB *session_key_krb5)
 {
-       DATA_BLOB tkt, tkt_wrapped, targ;
+       int retval;
+       DATA_BLOB tkt, tkt_wrapped;
        const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
 
        /* get a kerberos ticket for the service and extract the session key */
-       tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5);
 
-       if (tkt.data == NULL)
-               return tkt;
+       if (retval)
+               return retval;
 
        /* wrap that up in a nice GSS-API wrapping */
        tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
 
        /* and wrap that in a shiny SPNEGO wrapper */
-       targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
+       *targ = gen_negTokenTarg(krb_mechs, tkt_wrapped);
 
        data_blob_free(&tkt_wrapped);
        data_blob_free(&tkt);
 
-       return targ;
+       return retval;
 }
 
 
index c7cc4848b7013b218df436a2d5424f0711717eae..83902971b0921bf221d6a771b715d5712f5fa998 100644 (file)
@@ -884,6 +884,40 @@ static BOOL resolve_hosts(const char *name, int name_type,
         */
        struct hostent *hp;
        
+       if ( name_type != 0x20 && name_type != 0x0) {
+               DEBUG(5, ("resolve_hosts: not appropriate for name type <0x%x>\n", name_type));
+               return False;
+       }
+
+       *return_iplist = NULL;
+       *return_count = 0;
+
+       DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x%x>\n", name, name_type));
+       
+       if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
+               struct in_addr return_ip;
+               putip((char *)&return_ip,(char *)hp->h_addr);
+               *return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service));
+               if(*return_iplist == NULL) {
+                       DEBUG(3,("resolve_hosts: malloc fail !\n"));
+                       return False;
+               }
+               (*return_iplist)->ip   = return_ip;
+               (*return_iplist)->port = PORT_NONE;
+               *return_count = 1;
+               return True;
+       }
+       return False;
+}
+
+/********************************************************
+ Resolve via "ADS" method.
+*********************************************************/
+
+static BOOL resolve_ads(const char *name, int name_type,
+                         struct ip_service **return_iplist, int *return_count)
+{
+       
 #ifdef HAVE_ADS
        if ( name_type == 0x1c ) {
                int                     count, i = 0;
@@ -935,28 +969,11 @@ static BOOL resolve_hosts(const char *name, int name_type,
                *return_count = i;
                                
                return True;
-       }
+       } else 
 #endif         /* HAVE_ADS */
-
-       *return_iplist = NULL;
-       *return_count = 0;
-
-       DEBUG(3,("resolve_hosts: Attempting host lookup for name %s<0x20>\n", name));
-       
-       if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) {
-               struct in_addr return_ip;
-               putip((char *)&return_ip,(char *)hp->h_addr);
-               *return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service));
-               if(*return_iplist == NULL) {
-                       DEBUG(3,("resolve_hosts: malloc fail !\n"));
-                       return False;
-               }
-               (*return_iplist)->ip   = return_ip;
-               (*return_iplist)->port = PORT_NONE;
-               *return_count = 1;
-               return True;
+       { 
+               return False;
        }
-       return False;
 }
 
 /*******************************************************************
@@ -1034,14 +1051,17 @@ static BOOL internal_resolve_name(const char *name, int name_type,
   
   while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) {
          if((strequal(tok, "host") || strequal(tok, "hosts"))) {
-                  /* deal with 0x20 & 0x1c names here.  The latter will result
-                    in a SRV record lookup for _ldap._tcp.<domain> if we are using 
-                    'security = ads' */
-                 if ( name_type==0x20 || name_type == 0x1c ) {
-                         if (resolve_hosts(name, name_type, return_iplist, return_count)) {
-                                 result = True;
-                                 goto done;
-                         }
+                 if (resolve_hosts(name, name_type, return_iplist, return_count)) {
+                         result = True;
+                         goto done;
+                 }
+         } else if(strequal( tok, "ads")) {
+                  /* deal with 0x1c names here.  This will result in a
+                    SRV record lookup for _ldap._tcp.<domain> if we
+                    are using 'security = ads' */
+                 if (resolve_ads(name, name_type, return_iplist, return_count)) {
+                   result = True;
+                   goto done;
                  }
          } else if(strequal( tok, "lmhosts")) {
                  if (resolve_lmhosts(name, name_type, return_iplist, return_count)) {
@@ -1207,14 +1227,14 @@ BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
 /*********************************************************************
  small wrapper function to get the DC list and sort it if neccessary 
 *********************************************************************/
-BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL dns_only )
+BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
 {
        BOOL ordered;
        
        DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
-               (dns_only ? "hosts" : lp_name_resolve_order())));
+               (ads_only ? "ads" : lp_name_resolve_order())));
        
-       if ( !get_dc_list(domain, ip_list, count, dns_only, &ordered) )
+       if ( !get_dc_list(domain, ip_list, count, ads_only, &ordered) )
                return False;
                
        /* only sort if we don't already have an ordered list */
@@ -1230,11 +1250,11 @@ BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *c
 *********************************************************/
 
 BOOL get_dc_list(const char *domain, struct ip_service **ip_list, 
-                 int *count, BOOL dns_only, int *ordered)
+                 int *count, BOOL ads_only, int *ordered)
 {
        /* defined the name resolve order to internal_name_resolve() 
           only used for looking up 0x1c names */
-       const char *resolve_oder = (dns_only ? "hosts" : lp_name_resolve_order());
+       const char *resolve_oder = (ads_only ? "ads" : lp_name_resolve_order());
        
        *ordered = False;
                
index d645a2fffb384c831755586c72b25f1e30369d74..c3abd6381825b84e3213b87d5fe085a8eb18455d 100644 (file)
@@ -361,7 +361,7 @@ void unlock_share_entry(connection_struct *conn,
 }
 
 /*******************************************************************
- Lock a hash bucket entry. Use an fsp for convenience.
+ Lock a hash bucket entry. use a fsp for convenience
 ******************************************************************/
 
 BOOL lock_share_entry_fsp(files_struct *fsp)
@@ -370,7 +370,7 @@ BOOL lock_share_entry_fsp(files_struct *fsp)
 }
 
 /*******************************************************************
- Unlock a hash bucket entry. Use an fsp for convenience.
+ Unlock a hash bucket entry.
 ******************************************************************/
 
 void unlock_share_entry_fsp(files_struct *fsp)
index fc66e0d6b49b584ef2335fcdff0051c3b79a91d1..728796ea21aa728559b862b67ad015dc3370e388 100644 (file)
@@ -255,7 +255,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
                                        q = ALIGN4(q, buf);
                                }
 
-                               DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
+                               DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %ld\n", len, (unsigned long)PTR_DIFF(q, buf) ));
 
                                if (len - PTR_DIFF(q, buf) > 8) {
                                        /* with NT5 clients we can sometimes
index 7d25524f8eee6fe8f0eed628f329c710c1ffd7e6..c7dc89d43f1f2837278df2f6bb86c9f275dcd570 100644 (file)
@@ -298,18 +298,20 @@ static BOOL wbinfo_domain_info(const char *domain_name)
 
        /* Display response */
 
-       d_printf("Name    : %s\n", response.data.domain_info.name);
-       d_printf("Alt_Name: %s\n", response.data.domain_info.alt_name);
+       d_printf("Name              : %s\n", response.data.domain_info.name);
+       d_printf("Alt_Name          : %s\n", response.data.domain_info.alt_name);
 
-       d_printf("SID     : %s\n", response.data.domain_info.sid);
+       d_printf("SID               : %s\n", response.data.domain_info.sid);
 
-       d_printf("Native  : %s\n",
+       d_printf("Active Directory  : %s\n",
+                response.data.domain_info.active_directory ? "Yes" : "No");
+       d_printf("Native            : %s\n",
                 response.data.domain_info.native_mode ? "Yes" : "No");
 
-       d_printf("Primary : %s\n",
+       d_printf("Primary           : %s\n",
                 response.data.domain_info.primary ? "Yes" : "No");
 
-       d_printf("Sequence: %d\n", response.data.domain_info.sequence_number);
+       d_printf("Sequence          : %d\n", response.data.domain_info.sequence_number);
 
        return True;
 }
@@ -909,14 +911,14 @@ static void wbinfo_get_auth_user(void)
        char *user, *domain, *password;
 
        /* Lift data from secrets file */
+       
+       secrets_fetch_ipc_userpass(&user, &domain, &password);
 
-       secrets_init();
-
-       user = secrets_fetch(SECRETS_AUTH_USER, NULL);
-       domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
-       password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+       if ((!user || !*user) && (!domain || !*domain ) && (!password || !*password)){
 
-       if (!user && !domain && !password) {
+               SAFE_FREE(user);
+               SAFE_FREE(domain);
+               SAFE_FREE(password);
                d_printf("No authorised user configured\n");
                return;
        }
diff --git a/source3/nsswitch/winbind_nss_freebsd.c b/source3/nsswitch/winbind_nss_freebsd.c
new file mode 100644 (file)
index 0000000..b73a4ce
--- /dev/null
@@ -0,0 +1,81 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   AIX loadable authentication module, providing identification 
+   routines against Samba winbind/Windows NT Domain
+
+   Copyright (C) Aaron Collins 2003
+   
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+   
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA  02111-1307, USA.   
+*/
+
+#include "winbind_client.h"
+
+/* Make sure that the module gets registered needed by freebsd 5.1 */
+
+extern enum nss_status _nss_winbind_getgrent_r(struct group *, char *, size_t,
+    int *);
+extern enum nss_status _nss_winbind_getgrnam_r(const char *, struct group *,
+    char *, size_t, int *);
+extern enum nss_status _nss_winbind_getgrgid_r(gid_t gid, struct group *, char *,
+    size_t, int *);
+extern enum nss_status _nss_winbind_setgrent(void);
+extern enum nss_status _nss_winbind_endgrent(void);
+
+extern enum nss_status _nss_winbind_getpwent_r(struct passwd *, char *, size_t,
+    int *);
+extern enum nss_status _nss_winbind_getpwnam_r(const char *, struct passwd *,
+    char *, size_t, int *);
+extern enum nss_status _nss_winbind_getpwuid_r(gid_t gid, struct passwd *, char *,
+    size_t, int *);
+extern enum nss_status _nss_winbind_setpwent(void);
+extern enum nss_status _nss_winbind_endpwent(void);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrgid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getgrent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setgrent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endgrent);
+
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwnam_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwuid_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_getpwent_r);
+NSS_METHOD_PROTOTYPE(__nss_compat_setpwent);
+NSS_METHOD_PROTOTYPE(__nss_compat_endpwent);
+
+static ns_mtab methods[] = {
+{ NSDB_GROUP, "getgrnam_r", __nss_compat_getgrnam_r, _nss_winbind_getgrnam_r },
+{ NSDB_GROUP, "getgrgid_r", __nss_compat_getgrgid_r, _nss_winbind_getgrgid_r },
+{ NSDB_GROUP, "getgrent_r", __nss_compat_getgrent_r, _nss_winbind_getgrent_r },
+{ NSDB_GROUP, "endgrent",   __nss_compat_setgrent,   _nss_winbind_setgrent },
+{ NSDB_GROUP, "setgrent",   __nss_compat_endgrent,   _nss_winbind_endgrent },
+
+{ NSDB_PASSWD, "getpwnam_r", __nss_compat_getpwnam_r, _nss_winbind_getpwnam_r },
+{ NSDB_PASSWD, "getpwuid_r", __nss_compat_getpwuid_r, _nss_winbind_getpwuid_r },
+{ NSDB_PASSWD, "getpwent_r", __nss_compat_getpwent_r, _nss_winbind_getpwent_r },
+{ NSDB_PASSWD, "endpwent",   __nss_compat_setpwent,   _nss_winbind_setpwent },
+{ NSDB_PASSWD, "setpwent",   __nss_compat_endpwent,   _nss_winbind_endpwent },
+
+};
+
+ns_mtab *
+nss_module_register(const char *source, unsigned int *mtabsize,
+    nss_module_unregister_fn *unreg)
+{
+        *mtabsize = sizeof(methods)/sizeof(methods[0]);
+        *unreg = NULL;
+        return (methods);
+}
index 4c03522461eb0faa22c237facded4c5f89bc05a6..3124ef6378245d333ac6926cef771ee1d33ed621 100644 (file)
@@ -935,6 +935,8 @@ int main(int argc, char **argv)
 
        netsamlogon_cache_init(); /* Non-critical */
        
+       init_domain_list();
+
        /* Loop waiting for requests */
 
        process_loop();
index 5dbe422bc148ca4563b7f07a245095216480c5b0..7c8e6256e15d51ad5e4603f724e498a12627d5d2 100644 (file)
@@ -95,7 +95,8 @@ struct winbindd_domain {
        fstring alt_name;                      /* alt Domain name (if any) */
        DOM_SID sid;                           /* SID for this domain */
        BOOL native_mode;                      /* is this a win2k domain in native mode ? */
-       BOOL primary;                           /* is this our primary domain ? */
+       BOOL active_directory;                 /* is this a win2k active directory ? */
+       BOOL primary;                          /* is this our primary domain ? */
 
        /* Lookup methods for this domain (LDAP or RPC) */
        struct winbindd_methods *methods;
index ec93d494d0e52d896ea18683137f795427e9c91d..e6b857f4061520c304cfcd6372a968766112f439 100644 (file)
@@ -112,7 +112,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
                goto done;
        }
 
-       rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
+       rc = ads_search_retry(ads, &res, "(objectClass=user)", attrs);
        if (!ADS_ERR_OK(rc) || !res) {
                DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
                goto done;
index a3c1706b75dbdd2a2a7b01f5580cd8419a8b7d9a..8dec89a6aa33ab3605aaf53befc565ae888107ec 100644 (file)
@@ -107,12 +107,14 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain)
                case SEC_ADS: {
                        extern struct winbindd_methods ads_methods;
                        /* always obey the lp_security parameter for our domain */
-                       if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) {
+                       if (domain->primary) {
                                domain->backend = &ads_methods;
                                break;
                        }
 
-                       if ( domain->native_mode ) {
+                       /* if it have either of the indications of ADS, 
+                          use ads_methods */
+                       if ( domain->active_directory || domain->native_mode ) {
                                domain->backend = &ads_methods;
                                break;
                        }
index 2b561be31db48bb3caf8daba1ab426e87754e80c..44fc06fe544da6d55212e2db6ffc090604bf1183 100644 (file)
@@ -174,16 +174,19 @@ static NTSTATUS cm_open_connection(const struct winbindd_domain *domain, const i
                        
                        if ((lp_security() == SEC_ADS) 
                                && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) {
+                               ADS_STATUS ads_status;
                                new_conn->cli->use_kerberos = True;
                                DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", 
                                          new_conn->controller, global_myname(), machine_krb5_principal));
 
-                               result = NT_STATUS_OK;
-
-                               if (!NT_STATUS_IS_OK(result = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
-                                                             machine_password, 
-                                                             lp_workgroup()))) {
-                                       DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result)));
+                               ads_status = cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, 
+                                                                     machine_password, 
+                                                                     lp_workgroup());
+                               if (!ADS_ERR_OK(ads_status)) {
+                                       DEBUG(4,("failed kerberos session setup with %s\n", ads_errstr(ads_status)));
+                                       result = ads_ntstatus(ads_status);
+                               } else {
+                                       result = NT_STATUS_OK;
                                }
                        }
                        new_conn->cli->use_kerberos = False;
@@ -405,46 +408,116 @@ static NTSTATUS get_connection_from_cache(struct winbindd_domain *domain, const
 }
 
 /**********************************************************************************
+ We can 'sense' certain things about the DC by it's replies to certain questions.
+
+ This tells us if this particular remote server is Active Directory, and if it is
+ native mode.
 **********************************************************************************/
 
-BOOL cm_check_for_native_mode_win2k( struct winbindd_domain *domain )
+void set_dc_type_and_flags( struct winbindd_domain *domain )
 {
        NTSTATUS                result;
        struct winbindd_cm_conn conn;
        DS_DOMINFO_CTR          ctr;
-       BOOL                    ret = False;
+       TALLOC_CTX              *mem_ctx = NULL;
        
        ZERO_STRUCT( conn );
        ZERO_STRUCT( ctr );
        
+       domain->native_mode = False;
+       domain->active_directory = False;
        
        if ( !NT_STATUS_IS_OK(result = cm_open_connection(domain, PI_LSARPC_DS, &conn)) ) {
-               DEBUG(5, ("cm_check_for_native_mode_win2k: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 
+               DEBUG(5, ("set_dc_type_and_flags: Could not open a connection to %s for PIPE_LSARPC (%s)\n", 
                          domain->name, nt_errstr(result)));
-               return False;
+               return;
        }
        
        if ( conn.cli ) {
                if ( !NT_STATUS_IS_OK(cli_ds_getprimarydominfo( conn.cli, 
                                conn.cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr)) ) {
-                       ret = False;
                        goto done;
                }
        }
                                
        if ( (ctr.basic->flags & DSROLE_PRIMARY_DS_RUNNING) 
                        && !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
-               ret = True;
+               domain->native_mode = True;
 
-done:
+       /* Cheat - shut down the DS pipe, and open LSA */
+
+       cli_nt_session_close(conn.cli);
+
+       if ( cli_nt_session_open (conn.cli, PI_LSARPC) ) {
+               char *domain_name = NULL;
+               char *dns_name = NULL;
+               DOM_SID *dom_sid = NULL;
+
+               mem_ctx = talloc_init("set_dc_type_and_flags on domain %s\n", domain->name);
+               if (!mem_ctx) {
+                       DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+                       return;
+               }
+
+               result = cli_lsa_open_policy2(conn.cli, mem_ctx, True, 
+                                             SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                             &conn.pol);
+               
+               if (NT_STATUS_IS_OK(result)) {
+                       /* This particular query is exactly what Win2k clients use 
+                          to determine that the DC is active directory */
+                       result = cli_lsa_query_info_policy2(conn.cli, mem_ctx, 
+                                                           &conn.pol,
+                                                           12, &domain_name,
+                                                           &dns_name, NULL,
+                                                           NULL, &dom_sid);
+               }
+
+               if (NT_STATUS_IS_OK(result)) {
+                       if (domain_name)
+                               fstrcpy(domain->name, domain_name);
+                       
+                       if (dns_name)
+                               fstrcpy(domain->alt_name, dns_name);
 
+                       if (dom_sid) 
+                               sid_copy(&domain->sid, dom_sid);
+
+                       domain->active_directory = True;
+               } else {
+                       
+                       result = cli_lsa_open_policy(conn.cli, mem_ctx, True, 
+                                                    SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                                    &conn.pol);
+                       
+                       if (!NT_STATUS_IS_OK(result))
+                               goto done;
+                       
+                       result = cli_lsa_query_info_policy(conn.cli, mem_ctx, 
+                                                          &conn.pol, 5, &domain_name, 
+                                                          &dom_sid);
+                       
+                       if (NT_STATUS_IS_OK(result)) {
+                               if (domain_name)
+                                       fstrcpy(domain->name, domain_name);
+                               
+                               if (dom_sid) 
+                                       sid_copy(&domain->sid, dom_sid);
+                       }
+               }
+       }
+       
+done:
+       
        /* close the connection;  no other cals use this pipe and it is called only
           on reestablishing the domain list   --jerry */
-
+       
        if ( conn.cli )
                cli_shutdown( conn.cli );
        
-       return ret;
+       talloc_destroy(mem_ctx);
+       
+       return;
 }
 
 
index 180a3db8e2e02c0968972a10cbcf516284a0e9dc..b31dc92b38c94154bf91cc43344d3abc816c6edc 100644 (file)
@@ -106,7 +106,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
        *num_gr_mem = 0;
        
        if ( !((group_name_type==SID_NAME_DOM_GRP) ||
-               ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+               ((group_name_type==SID_NAME_ALIAS) && domain->primary)) )
        {
                DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", 
                          sid_to_string(sid_string, group_sid), domain->name, 
@@ -152,15 +152,10 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
                    occur in Universal groups on a Windows 2000 native mode
                    server. */
 
-               if (name_types[i] != SID_NAME_USER) {
-                       DEBUG(3, ("name %s isn't a domain user\n", the_name));
-                       continue;
-               }
+               /* make sure to allow machine accounts */
 
-               /* Don't bother with machine accounts */
-               
-               if (the_name[strlen(the_name) - 1] == '$') {
-                       DEBUG(10, ("%s is machine account\n", the_name));
+               if (name_types[i] != SID_NAME_USER && name_types[i] != SID_NAME_COMPUTER) {
+                       DEBUG(3, ("name %s isn't a domain user\n", the_name));
                        continue;
                }
 
@@ -265,22 +260,20 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
                return WINBINDD_OK;
        }
 
-       /* should we deal with users for our domain? */
-       
-       if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
-               DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", 
-                       name_domain, name_group));
-               return WINBINDD_ERROR;
-       }       
-
-       
        /* Get info for the domain */
 
        if ((domain = find_domain_from_name(name_domain)) == NULL) {
-               DEBUG(0, ("could not get domain sid for domain %s\n",
+               DEBUG(3, ("could not get domain sid for domain %s\n",
                          name_domain));
                return WINBINDD_ERROR;
        }
+       /* should we deal with users for our domain? */
+       
+       if ( lp_winbind_trusted_domains_only() && domain->primary) {
+               DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", 
+                       name_domain, name_group));
+               return WINBINDD_ERROR;
+       }
 
        /* Get rid and name type from name */
         
@@ -292,7 +285,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state)
        }
 
        if ( !((name_type==SID_NAME_DOM_GRP) ||
-               ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+               ((name_type==SID_NAME_ALIAS) && domain->primary)) )
        {
                DEBUG(1, ("name '%s' is not a local or domain group: %d\n", 
                          name_group, name_type));
@@ -383,7 +376,7 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state)
        }
 
        if ( !((name_type==SID_NAME_DOM_GRP) ||
-               ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+              ((name_type==SID_NAME_ALIAS) && domain->primary) ))
        {
                DEBUG(1, ("name '%s' is not a local or domain group: %d\n", 
                          group_name, name_type));
@@ -441,7 +434,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state)
                   are a member of a Samba domain */
                
                if ( (IS_DC || lp_winbind_trusted_domains_only())
-                       && strequal(domain->name, lp_workgroup()) )
+                       && domain->primary )
                {
                        continue;
                }
@@ -547,7 +540,7 @@ static BOOL get_sam_group_entries(struct getent_state *ent)
           and are not using LDAP to get the groups */
           
        if ( lp_security() != SEC_ADS && domain->native_mode 
-               && strequal(lp_workgroup(), domain->name) )
+               && domain->primary )
        {
                DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n"));
                
@@ -887,7 +880,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state)
                        extra_data[extra_data_len++] = ',';
                }
 
-               free(groups.sam_entries);
+               SAFE_FREE(groups.sam_entries);
        }
 
        /* Assign extra_data fields in response structure */
@@ -938,21 +931,22 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
        /* Parse domain and username */
 
        parse_domain_user(state->request.data.username, 
-               name_domain, name_user);
-       
-       /* bail if there is no domain */ 
+                         name_domain, name_user);
        
-       if ( !*name_domain )
-               goto done;
-
        /* Get info for the domain */
        
        if ((domain = find_domain_from_name(name_domain)) == NULL) {
-               DEBUG(0, ("could not find domain entry for domain %s\n", 
+               DEBUG(7, ("could not find domain entry for domain %s\n", 
                          name_domain));
                goto done;
        }
 
+       if ( domain->primary && lp_winbind_trusted_domains_only()) {
+               DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getgroups() for %s\\%s.\n", 
+                       name_domain, name_user));
+               return WINBINDD_ERROR;
+       }       
+       
        /* Get rid and name type from name.  The following costs 1 packet */
 
        if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, 
@@ -961,7 +955,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                goto done;
        }
 
-       if (name_type != SID_NAME_USER) {
+       if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) {
                DEBUG(1, ("name '%s' is not a user name: %d\n", 
                          name_user, name_type));
                goto done;
@@ -1000,7 +994,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state)
                           in a win2k native mode domain. */
                        
                        if ( !((sid_type==SID_NAME_DOM_GRP) ||
-                               ((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) )
+                               ((sid_type==SID_NAME_ALIAS) && domain->primary)) )
                        {
                                DEBUG(10, ("winbindd_getgroups: sid type %d "
                                           "for %s is not a domain group\n",
@@ -1127,7 +1121,7 @@ enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state)
                          sid_string_static(&user_sid)));
                goto done;
        }
-
+       
        status = domain->methods->lookup_usergroups(domain, mem_ctx, 
                                                    &user_sid, &num_groups, 
                                                    &user_grpsids);
index 08b5be827d1faea93a486faf3ec98799573c07de..18478992f3e1714c43cdce3a909a237bbb29e08a 100644 (file)
@@ -36,7 +36,6 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
         int num_retries = 0;
         struct cli_state *cli;
        uint32 sec_channel_type;
-       const char *contact_domain_name = NULL;
        struct winbindd_domain *contact_domain;
 
        DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid));
@@ -51,18 +50,10 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat
        }
 
 
-       /* use the realm name if appropriate and possible */
-       
-       if ( lp_security() == SEC_ADS )
-               contact_domain_name = lp_realm();
-       
-       if ( !contact_domain_name || !*contact_domain_name )
-               contact_domain_name = lp_workgroup();
-       
-       contact_domain = find_domain_from_name(contact_domain_name);
+       contact_domain = find_our_domain();
         if (!contact_domain) {
                result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-                DEBUG(1, ("%s is not a trusted domain\n", contact_domain_name));
+                DEBUG(1, ("Cannot find our own domain!\n"));
                 goto done;
         }
        
@@ -132,7 +123,7 @@ enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state
 
                /* Skip own domain */
 
-               if (strequal(domain->name, lp_workgroup())) continue;
+               if (domain->primary) continue;
 
                /* Add domain to list */
 
@@ -232,6 +223,7 @@ enum winbindd_result winbindd_domain_info(struct winbindd_cli_state *state)
                sid_string_static(&domain->sid));
        
        state->response.data.domain_info.native_mode = domain->native_mode;
+       state->response.data.domain_info.active_directory = domain->active_directory;
        state->response.data.domain_info.primary = domain->primary;
 
        state->response.data.domain_info.sequence_number =
index 0dd00e9b39edb955b4bc96ab1e3c621bd1ab5800..0d110b8afa87fb503cde0264cd2e6d5341e60a05 100644 (file)
@@ -36,7 +36,7 @@
 
 /* Update this when you change the interface.  */
 
-#define WINBIND_INTERFACE_VERSION 8
+#define WINBIND_INTERFACE_VERSION 9
 
 /* Socket commands */
 
@@ -272,6 +272,7 @@ struct winbindd_response {
                        fstring alt_name;
                        fstring sid;
                        BOOL native_mode;
+                       BOOL active_directory;
                        BOOL primary;
                        uint32 sequence_number;
                } domain_info;
index f619aa3564aa0d7faa4a632afcbc6f05253788b1..21e0c3092e3f62bb8a70991e1095c4a32730cbf1 100644 (file)
@@ -950,7 +950,8 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        TALLOC_CTX *mem_ctx;
        CLI_POLICY_HND *hnd;
-       fstring level5_dom;
+       char *level5_dom;
+       DOM_SID *alloc_sid;
        int retry;
 
        DEBUG(3,("rpc: domain_sid\n"));
@@ -965,9 +966,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid)
                        goto done;
 
                result = cli_lsa_query_info_policy(hnd->cli, mem_ctx,
-                                          &hnd->pol, 0x05, level5_dom, sid);
+                                          &hnd->pol, 0x05, &level5_dom, &alloc_sid);
        } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) &&  hnd && hnd->cli && hnd->cli->fd == -1);
 
+       if (NT_STATUS_IS_OK(result)) {
+               if (alloc_sid) {
+                       sid_copy(sid, alloc_sid);
+               } else {
+                       result = NT_STATUS_NO_MEMORY;
+               }
+       }
+
 done:
        talloc_destroy(mem_ctx);
        return result;
index 7c4c8d804a813a7ff00dcc289ed7654e6a75c3fa..9fbf47046d651e684d30f14f9083c207abddb24c 100644 (file)
@@ -152,7 +152,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state)
                DOM_SID sid2;
                uint32 rid;
                
-               domain = find_domain_from_name( lp_workgroup() );
+               domain = find_our_domain();
                if ( !domain ) {
                        DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
                        return WINBINDD_ERROR;
@@ -244,7 +244,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state)
                uint32 rid;
                unid_t id;
                
-               domain = find_domain_from_name( lp_workgroup() );
+               domain = find_our_domain();
                if ( !domain ) {
                        DEBUG(0,("winbindd_sid_to_uid: can't find my own domain!\n"));
                        return WINBINDD_ERROR;
@@ -341,7 +341,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state)
                if ( !(pw = getpwuid(state->request.data.uid)) )
                        return WINBINDD_ERROR;
 
-               if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+               if ( !(domain = find_our_domain()) ) {
                        DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
                        return WINBINDD_ERROR;
                }
@@ -411,7 +411,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state)
                if ( !(grp = getgrgid(state->request.data.gid)) )
                        return WINBINDD_ERROR;
 
-               if ( !(domain = find_domain_from_name(lp_workgroup())) ) {
+               if ( !(domain = find_our_domain()) ) {
                        DEBUG(0,("winbindd_uid_to_sid: can't find my own domain!\n"));
                        return WINBINDD_ERROR;
                }
index 903a2a8bfaf269ed995e21b9c15b5c2fdc174fef..d08377c888f3b27074b4801ee915cbdf34c3f346 100644 (file)
@@ -37,7 +37,8 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
                                char *full_name, struct winbindd_pw *pw)
 {
        fstring output_username;
-       pstring homedir;
+       char *homedir;
+       char *shell;
        fstring sid_string;
        
        if (!pw || !dom_name || !user_name)
@@ -72,24 +73,32 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
           shell. */
        
        /* The substitution of %U and %D in the 'template homedir' is done
-          by lp_string() calling standard_sub_basic(). */
+          by alloc_sub_specified() below. */
 
-       fstrcpy(current_user_info.smb_name, user_name);
-       sub_set_smb_name(user_name);
        fstrcpy(current_user_info.domain, dom_name);
 
-       pstrcpy(homedir, lp_template_homedir());
+       homedir = alloc_sub_specified(lp_template_homedir(), user_name, dom_name, pw->pw_uid, pw->pw_gid);
+
+       if (!homedir)
+               return False;
        
        safe_strcpy(pw->pw_dir, homedir, sizeof(pw->pw_dir) - 1);
        
-       safe_strcpy(pw->pw_shell, lp_template_shell(), 
+       SAFE_FREE(homedir);
+       
+       shell = alloc_sub_specified(lp_template_shell(), user_name, dom_name, pw->pw_uid, pw->pw_gid);
+
+       if (!shell)
+               return False;
+
+       safe_strcpy(pw->pw_shell, shell, 
                    sizeof(pw->pw_shell) - 1);
        
        /* Password - set to "x" as we can't generate anything useful here.
           Authentication can be done using the pam_winbind module. */
 
        safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
-       
+
        return True;
 }
 
@@ -115,7 +124,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
        /* Parse domain and username */
 
        parse_domain_user(state->request.data.username, 
-               name_domain, name_user);
+                         name_domain, name_user);
        
        /* if this is our local domain (or no domain), the do a local tdb search */
        
@@ -131,17 +140,17 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
 
        /* should we deal with users for our domain? */
        
-       if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) {
-               DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", 
-                       name_domain, name_user));
-               return WINBINDD_ERROR;
-       }       
-       
        if ((domain = find_domain_from_name(name_domain)) == NULL) {
                DEBUG(5, ("no such domain: %s\n", name_domain));
                return WINBINDD_ERROR;
        }
        
+       if ( domain->primary && lp_winbind_trusted_domains_only()) {
+               DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", 
+                       name_domain, name_user));
+               return WINBINDD_ERROR;
+       }       
+       
        /* Get rid and name type from name */
 
        if (!winbindd_lookup_sid_by_name(domain, name_user, &user_sid, &name_type)) {
@@ -149,15 +158,13 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state)
                return WINBINDD_ERROR;
        }
 
-       if (name_type != SID_NAME_USER) {
+       if (name_type != SID_NAME_USER && name_type != SID_NAME_COMPUTER) {
                DEBUG(1, ("name '%s' is not a user name: %d\n", name_user, 
                          name_type));
                return WINBINDD_ERROR;
        }
        
-       /* Get some user info.  Split the user rid from the sid obtained
-          from the winbind_lookup_by_name() call and use it in a
-          winbind_lookup_userinfo() */
+       /* Get some user info. */
     
        if (!(mem_ctx = talloc_init("winbindd_getpwnam([%s]\\[%s])", 
                                          name_domain, name_user))) {
@@ -530,15 +537,6 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state)
 
                name_list = ent->sam_entries;
 
-               /* Skip machine accounts */
-
-               if (name_list[ent->sam_entry_index].
-                   name[strlen(name_list[ent->sam_entry_index].name) - 1] 
-                   == '$') {
-                       ent->sam_entry_index++;
-                       continue;
-               }
-
                /* Lookup user info */
                
                result = winbindd_fill_pwent(
index 4cc43e85d6c1e597c4cb12d17287c91760a75376..076ab1a2fc3528fde1be16537f5249082282753b 100644 (file)
@@ -49,6 +49,14 @@ static const fstring name_deadbeef = "<deadbeef>";
 
 static struct winbindd_domain *_domain_list;
 
+/**
+   When was the last scan of trusted domains done?
+   
+   0 == not ever
+*/
+
+static time_t last_trustdom_scan;
+
 struct winbindd_domain *domain_list(void)
 {
        /* Initialise list */
@@ -83,6 +91,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 {
        struct winbindd_domain *domain;
        const char *alternative_name = NULL;
+       static const DOM_SID null_sid;
        
        /* ignore alt_name if we are not in an AD domain */
        
@@ -103,6 +112,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                                return domain;
                        }
                }
+               if (sid) {
+                       if (sid_equal(sid, &null_sid) ) {
+                               
+                       } else if (sid_equal(sid, &domain->sid)) {
+                               return domain;
+                       }
+               }
        }
         
        /* Create new domain entry */
@@ -133,12 +149,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
                sid_copy(&domain->sid, sid);
        }
        
-       /* see if this is a native mode win2k domain */
+       /* set flags about native_mode, active_directory */
           
-       domain->native_mode = cm_check_for_native_mode_win2k( domain );
+       set_dc_type_and_flags( domain );
        
-       DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain->name,
-               domain->native_mode ? "native" : "mixed (or NT4)" ));
+       DEBUG(3,("add_trusted_domain: %s is an %s %s domain\n", domain->name,
+                domain->active_directory ? "ADS" : "NT4", 
+                domain->native_mode ? "native mode" : 
+                ((domain->active_directory && !domain->native_mode) ? "mixed mode" : "")));
 
        /* Link to domain list */
        DLIST_ADD(_domain_list, domain);
@@ -156,13 +174,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
 
 void rescan_trusted_domains( void )
 {
-       static time_t last_scan;
        time_t now = time(NULL);
        struct winbindd_domain *mydomain = NULL;
        
        /* see if the time has come... */
        
-       if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) )
+       if ( (now > last_trustdom_scan) && ((now-last_trustdom_scan) < WINBINDD_RESCAN_FREQ) )
                return;
                
        if ( (mydomain = find_our_domain()) == NULL ) {
@@ -174,7 +191,7 @@ void rescan_trusted_domains( void )
        
        add_trusted_domains( mydomain );
 
-       last_scan = now;
+       last_trustdom_scan = now;
        
        return; 
 }
@@ -200,7 +217,7 @@ void add_trusted_domains( struct winbindd_domain *domain )
                return;
        }
 
-       DEBUG(1, ("scanning trusted domain list\n"));
+       DEBUG(5, ("scanning trusted domain list\n"));
 
        if (!(mem_ctx = talloc_init("init_domain_list")))
                return;
@@ -221,7 +238,7 @@ void add_trusted_domains( struct winbindd_domain *domain )
                for(i = 0; i < num_domains; i++) {
                        DEBUG(10,("Found domain %s\n", names[i]));
                        add_trusted_domain(names[i], alt_names?alt_names[i]:NULL,
-                               domain->methods, &dom_sids[i]);
+                                          domain->methods, &dom_sids[i]);
                                           
                        /* if the SID was empty, we better set it now */
                        
@@ -263,7 +280,7 @@ BOOL init_domain_list(void)
        /* Free existing list */
        free_domain_list();
 
-       /* Add ourselves as the first entry.  It *must* be the first entry */
+       /* Add ourselves as the first entry. */
        
        domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL);
        
@@ -286,7 +303,9 @@ BOOL init_domain_list(void)
 
        /* do an initial scan for trusted domains */
        add_trusted_domains(domain);
-
+       
+       /* avoid rescanning this right away */
+       last_trustdom_scan = time(NULL);
        return True;
 }
 
@@ -364,10 +383,6 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain,
 {
        NTSTATUS result;
         TALLOC_CTX *mem_ctx;
-       /* Don't bother with machine accounts */
-
-       if (name[strlen(name) - 1] == '$')
-               return False;
 
        mem_ctx = talloc_init("lookup_sid_by_name for %s\n", name);
        if (!mem_ctx) 
index 779d1b2c6ce6554d59cac975f25ac5f90b9aaec6..100a103924caa3f1909a632fad831270ac0f1915 100644 (file)
@@ -194,7 +194,7 @@ int lookup(nsd_file_t *rq)
         * response needs to be a string of the following format
         * ip_address[ ip_address]*\tname[ alias]*
         */
-       if (strcasecmp(map,"hosts.byaddr") == 0) {
+       if (StrCaseCmp(map,"hosts.byaddr") == 0) {
                if ( status = lookup_byaddr_backend(key, &count)) {
                    size = strlen(key) + 1;
                    if (size > len) {
@@ -222,7 +222,7 @@ int lookup(nsd_file_t *rq)
                    response[strlen(response)-1] = '\n';
                    free(status);
                }
-       } else if (strcasecmp(map,"hosts.byname") == 0) {
+       } else if (StrCaseCmp(map,"hosts.byname") == 0) {
            if (ip_list = lookup_byname_backend(key, &count)) {
                for (i = count; i ; i--) {
                    addr = inet_ntoa(ip_list[i-1]);
index 67012ee08755badee6f9a7e63f479b37bf7eb68f..a1fb90157cf0fb4812c0b52a380b317d4874ce81 100644 (file)
@@ -217,6 +217,7 @@ typedef struct
        int change_notify_timeout;
        int map_to_guest;
        int min_passwd_length;
+       BOOL use_cracklib;
        int oplock_break_wait_time;
        int winbind_cache_time;
        int iLockSpinCount;
@@ -749,6 +750,12 @@ static const struct enum_list enum_map_to_guest[] = {
  *       Any parameter that does NOT have FLAG_ADVANCED will not disply at all
  *      Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in
  *        respective views.
+ *
+ * NOTE2: Handling of duplicated (synonym) paramters:
+ *     Only the first occurance of a parameter should be enabled by FLAG_BASIC
+ *     and/or FLAG_ADVANCED. All duplicates following the first mention should be
+ *     set to FLAG_HIDE. ie: Make you must place the parameter that has the preferred
+ *     name first, and all synonyms must follow it with the FLAG_HIDE attribute.
  */
 
 static struct parm_struct parm_table[] = {
@@ -784,6 +791,7 @@ static struct parm_struct parm_table[] = {
        {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED}, 
        {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, 
        {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, 
+       {"use cracklib", P_BOOL, P_GLOBAL, &Globals.use_cracklib, NULL, NULL, FLAG_ADVANCED}, 
        {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, 
        {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, 
        {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, 
@@ -1153,9 +1161,9 @@ static struct parm_struct parm_table[] = {
        {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, 
        {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, 
        {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, 
-       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, 
+       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_HIDE}, 
        {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, 
-       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, 
+       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_HIDE}, 
        {"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED}, 
        {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, 
        {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, 
@@ -1437,6 +1445,7 @@ static void init_globals(void)
 
        Globals.map_to_guest = 0;       /* By Default, "Never" */
        Globals.min_passwd_length = MINPASSWDLENGTH;    /* By Default, 5. */
+       Globals.use_cracklib = False; 
        Globals.oplock_break_wait_time = 0;     /* By Default, 0 msecs. */
        Globals.enhanced_browsing = True; 
        Globals.iLockSpinCount = 3; /* Try 3 times. */
@@ -1681,8 +1690,8 @@ FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript)
 FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook)
 FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners)
 FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup)
-FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
-FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell)
+FN_GLOBAL_CONST_STRING(lp_template_homedir, &Globals.szTemplateHomedir)
+FN_GLOBAL_CONST_STRING(lp_template_shell, &Globals.szTemplateShell)
 FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator)
 FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat)
 FN_GLOBAL_BOOL(lp_winbind_enable_local_accounts, &Globals.bWinbindEnableLocalAccounts)
@@ -1791,6 +1800,7 @@ FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout
 FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout)
 FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length)
+FN_GLOBAL_BOOL(lp_use_cracklib, &Globals.use_cracklib)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
index a5a2c29a8be5c666ff53c3c640e470ff5b89bf5d..f9557cac425a6a1e2359a8369b550f9586110274 100644 (file)
@@ -3,6 +3,7 @@
    Copyright (C) Andrew Tridgell 1992-2001
    Copyright (C) Andrew Bartlett      2002
    Copyright (C) Rafal Szczesniak     2002
+   Copyright (C) Tim Potter           2001
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -790,3 +791,40 @@ BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result)
 
        return True;
 }
+
+/******************************************************************************
+  When kerberos is not available, choose between anonymous or
+  authenticated connections.  
+
+  We need to use an authenticated connection if DCs have the
+  RestrictAnonymous registry entry set > 0, or the "Additional
+  restrictions for anonymous connections" set in the win2k Local
+  Security Policy.
+
+  Caller to free() result in domain, username, password
+*******************************************************************************/
+void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
+{
+       *username = secrets_fetch(SECRETS_AUTH_USER, NULL);
+       *domain = secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
+       *password = secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
+       
+       if (*username && **username) {
+
+               if (!*domain || !**domain)
+                       *domain = smb_xstrdup(lp_workgroup());
+               
+               if (!*password || !**password)
+                       *password = smb_xstrdup("");
+
+               DEBUG(3, ("IPC$ connections done by user %s\\%s\n", 
+                         *domain, *username));
+
+       } else {
+               DEBUG(3, ("IPC$ connections done anonymously\n"));
+               *username = smb_xstrdup("");
+               *domain = smb_xstrdup("");
+               *password = smb_xstrdup("");
+       }
+}
+
index f2dd7d4f221b99bfe84439dc1ba3878313fb9dde..7750239630cabfa04878a2410a90279ca36dc76b 100644 (file)
@@ -20,6 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "printing.h"
 
 static TALLOC_CTX *send_ctx;
index 77719ffc5284e07e6fa5812fe4825a646f55b78a..f0096a17c2c40a42c082eb0288ac2039716b8e9f 100644 (file)
@@ -18,6 +18,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include "includes.h"
 #include "printing.h"
 
 #ifdef HAVE_CUPS
index 1c847448da2e95b8fc01c6a65df41c5097cc6e27..9e0ea85bb9adcb6b0ad46e1ccd844649a9943fe0 100644 (file)
@@ -18,6 +18,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "printing.h"
 
 
index 791c41fe69c96e74880b86ea97373ccbddbe42cb..bdcd9504505e3b32903f95fe19bcd7f1a36d74c0 100644 (file)
@@ -20,6 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "printing.h"
 
 /* Current printer interface */
index 1c7ac713537c0a453e48e23de5ff41ddd2260996..0e0fb1b51d694689606c7b643af0f1a25cc1086f 100644 (file)
@@ -20,6 +20,7 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#include "includes.h"
 #include "printing.h"
 
 static struct tdb_print_db *print_db_head;
index 0ec9beb1a4f1b0fa4b0f1910c793e144c5a8fa46..40b83c5c0c7e7818ad79b953a2a0bf735e79785b 100644 (file)
@@ -443,7 +443,7 @@ NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *pol, uint16 info_class, 
-                                   fstring domain_name, DOM_SID *domain_sid)
+                                   char **domain_name, DOM_SID **domain_sid)
 {
        prs_struct qbuf, rbuf;
        LSA_Q_QUERY_INFO q;
@@ -481,39 +481,40 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Return output parameters */
 
-       ZERO_STRUCTP(domain_sid);
-       domain_name[0] = '\0';
-
        switch (info_class) {
 
        case 3:
-               if (r.dom.id3.buffer_dom_name != 0) {
-                       unistr2_to_ascii(domain_name,
-                                        &r.dom.id3.
-                                        uni_domain_name,
-                                        sizeof (fstring) - 1);
+               if (domain_name && (r.dom.id3.buffer_dom_name != 0)) {
+                       *domain_name = unistr2_tdup(mem_ctx, 
+                                                  &r.dom.id3.
+                                                  uni_domain_name);
                }
 
-               if (r.dom.id3.buffer_dom_sid != 0) {
-                       *domain_sid = r.dom.id3.dom_sid.sid;
+               if (domain_sid && (r.dom.id3.buffer_dom_sid != 0)) {
+                       *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+                       if (*domain_sid) {
+                               sid_copy(*domain_sid, &r.dom.id3.dom_sid.sid);
+                       }
                }
 
                break;
 
        case 5:
                
-               if (r.dom.id5.buffer_dom_name != 0) {
-                       unistr2_to_ascii(domain_name, &r.dom.id5.
-                                        uni_domain_name,
-                                        sizeof (fstring) - 1);
+               if (domain_name && (r.dom.id5.buffer_dom_name != 0)) {
+                       *domain_name = unistr2_tdup(mem_ctx, 
+                                                  &r.dom.id5.
+                                                  uni_domain_name);
                }
                        
-               if (r.dom.id5.buffer_dom_sid != 0) {
-                       *domain_sid = r.dom.id5.dom_sid.sid;
+               if (domain_sid && (r.dom.id5.buffer_dom_sid != 0)) {
+                       *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+                       if (*domain_sid) {
+                               sid_copy(*domain_sid, &r.dom.id5.dom_sid.sid);
+                       }
                }
-
                break;
-               
+                       
        default:
                DEBUG(3, ("unknown info class %d\n", info_class));
                break;                
@@ -536,10 +537,9 @@ NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *pol, uint16 info_class, 
-                                   fstring domain_name, fstring dns_name,
-                                   fstring forest_name, 
-                                   struct uuid *domain_guid, 
-                                   DOM_SID *domain_sid)
+                                   char **domain_name, char **dns_name,
+                                   char **forest_name, struct uuid **domain_guid,
+                                   DOM_SID **domain_sid)
 {
        prs_struct qbuf, rbuf;
        LSA_Q_QUERY_INFO2 q;
@@ -580,30 +580,37 @@ NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Return output parameters */
 
-       ZERO_STRUCTP(domain_sid);
        ZERO_STRUCTP(domain_guid);
-       domain_name[0] = '\0';
 
-       if (r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
-               unistr2_to_ascii(domain_name,
-                                &r.info.dns_dom_info.uni_nb_dom_name,
-                                sizeof(fstring) - 1);
+       if (domain_name && r.info.dns_dom_info.hdr_nb_dom_name.buffer) {
+               *domain_name = unistr2_tdup(mem_ctx, 
+                                           &r.info.dns_dom_info
+                                           .uni_nb_dom_name);
        }
-       if (r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
-               unistr2_to_ascii(dns_name,
-                                &r.info.dns_dom_info.uni_dns_dom_name,
-                                sizeof(fstring) - 1);
+       if (dns_name && r.info.dns_dom_info.hdr_dns_dom_name.buffer) {
+               *dns_name = unistr2_tdup(mem_ctx, 
+                                        &r.info.dns_dom_info
+                                        .uni_dns_dom_name);
        }
-       if (r.info.dns_dom_info.hdr_forest_name.buffer) {
-               unistr2_to_ascii(forest_name,
-                                &r.info.dns_dom_info.uni_forest_name,
-                                sizeof(fstring) - 1);
+       if (forest_name && r.info.dns_dom_info.hdr_forest_name.buffer) {
+               *forest_name = unistr2_tdup(mem_ctx, 
+                                           &r.info.dns_dom_info
+                                           .uni_forest_name);
        }
        
-       memcpy(domain_guid, &r.info.dns_dom_info.dom_guid,sizeof(struct uuid));
-
-       if (r.info.dns_dom_info.ptr_dom_sid != 0) {
-               *domain_sid = r.info.dns_dom_info.dom_sid.sid;
+       if (domain_guid) {
+               *domain_guid = talloc(mem_ctx, sizeof(**domain_guid));
+               memcpy(*domain_guid, 
+                      &r.info.dns_dom_info.dom_guid, 
+                      sizeof(struct uuid));
+       }
+
+       if (domain_sid && r.info.dns_dom_info.ptr_dom_sid != 0) {
+               *domain_sid = talloc(mem_ctx, sizeof(**domain_sid));
+               if (*domain_sid) {
+                       sid_copy(*domain_sid, 
+                                &r.info.dns_dom_info.dom_sid.sid);
+               }
        }
        
  done:
index b9974cba8ad324024fa13c437f6e9cf9c1e212e4..7edd34c8ddee8e91d4b3b7307311b6983c2531a9 100644 (file)
@@ -2834,11 +2834,17 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid)
                DEBUG(5, ("Changing trust account or non-unix-user password, not updating /etc/passwd\n"));
        } else  {
                /* update the UNIX password */
-               if (lp_unix_password_sync() )
-                       if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
+               if (lp_unix_password_sync() ) {
+                       struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd));
+                       if (!passwd) {
+                               DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
+                       }
+                       
+                       if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
                                pdb_free_sam(&pwd);
                                return False;
                        }
+               }
        }
  
        ZERO_STRUCT(plaintext_buf);
@@ -2899,7 +2905,12 @@ static BOOL set_user_info_pw(char *pass, DOM_SID *sid)
        } else {
                /* update the UNIX password */
                if (lp_unix_password_sync()) {
-                       if(!chgpasswd(pdb_get_username(pwd), "", plaintext_buf, True)) {
+                       struct passwd *passwd = Get_Pwnam(pdb_get_username(pwd));
+                       if (!passwd) {
+                               DEBUG(1, ("chgpasswd: Username does not exist in system !?!\n"));
+                       }
+                       
+                       if(!chgpasswd(pdb_get_username(pwd), passwd, "", plaintext_buf, True)) {
                                pdb_free_sam(&pwd);
                                return False;
                        }
index 217e6b1d68a8f25cab7fc15789ab84972d4fa552..d9afde465dac8ccbb1ae16f5ec4e2d6b6a02b23c 100644 (file)
@@ -68,9 +68,13 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
 {
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       DOM_SID dom_sid;
-       struct uuid dom_guid;
-       fstring sid_str, domain_name="", dns_name="", forest_name="";
+       DOM_SID *dom_sid;
+       struct uuid *dom_guid;
+       fstring sid_str;
+       char *domain_name = NULL;
+       char *dns_name = NULL;
+       char *forest_name = NULL;
+
        uint32 info_class = 3;
 
        if (argc > 2) {
@@ -91,8 +95,8 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                if (!NT_STATUS_IS_OK(result))
                        goto done;
                result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol,
-                                                   info_class, domain_name,
-                                                   dns_name, forest_name,
+                                                   info_class, &domain_name,
+                                                   &dns_name, &forest_name,
                                                    &dom_guid, &dom_sid);
                break;
        default:
@@ -103,28 +107,28 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                if (!NT_STATUS_IS_OK(result))
                        goto done;
                result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, 
-                                                  info_class, domain_name, 
+                                                  info_class, &domain_name, 
                                                   &dom_sid);
        }
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
+       
+       sid_to_string(sid_str, dom_sid);
 
-       sid_to_string(sid_str, &dom_sid);
-
-       if (domain_name[0])
+       if (domain_name)
                printf("domain %s has sid %s\n", domain_name, sid_str);
        else
                printf("could not query info for level %d\n", info_class);
 
-       if (dns_name[0])
+       if (dns_name)
                printf("domain dns name is %s\n", dns_name);
-       if (forest_name[0])
+       if (forest_name)
                printf("forest name is %s\n", forest_name);
 
        if (info_class == 12) {
-               printf("domain GUID is %s\n",
-                      smb_uuid_string_static(dom_guid));
+               printf("domain GUID is ");
+               smb_uuid_string_static(*dom_guid);
        }
  done:
        return result;
index 798949fae92f448ac400204d2ad34d6366a5ca6e..f5a440c024c455ffb36168555aa55a3f236660b1 100644 (file)
@@ -1336,7 +1336,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
         strupper_m(servername);
 
-       /* Fill in the DRIVER_INFO_3 struct */
+       /* Fill in the DRIVER_INFO_2 struct */
        ZERO_STRUCT(info2);
 #if 0  /* JERRY */
        init_unistr( &info2.servername,         servername);
index 027ca3511058d0eb62fb4d0ab56d9a548d60ef5e..c0285bda5589f6570788899aeec36c417df18e36 100755 (executable)
@@ -71,7 +71,7 @@ for ln in $LANGS; do
 
 done
 
-# Install html documentation
+# Install html documentation (if html documentation tree is here)
 
 if [ -d $SRCDIR../docs/htmldocs/ ]; then
 
index cdc5bd98813544c88f156b3dadde4b1c4486d5a8..9c226623109ca6e1ee22048a45175ba2900af6a4 100644 (file)
@@ -242,14 +242,14 @@ END {
        # add code to display the various type sizes
        print "       /* Output the sizes of the various types */";
        print "       output(screen, \"\\nType sizes:\\n\");";
-       print "       output(screen, \"   sizeof(char):    %u\\n\",sizeof(char));";
-       print "       output(screen, \"   sizeof(int):     %u\\n\",sizeof(int));";
-       print "       output(screen, \"   sizeof(long):    %u\\n\",sizeof(long));";
-       print "       output(screen, \"   sizeof(uint8):   %u\\n\",sizeof(uint8));";
-       print "       output(screen, \"   sizeof(uint16):  %u\\n\",sizeof(uint16));";
-       print "       output(screen, \"   sizeof(uint32):  %u\\n\",sizeof(uint32));";
-       print "       output(screen, \"   sizeof(short):   %u\\n\",sizeof(short));";
-       print "       output(screen, \"   sizeof(void*):   %u\\n\",sizeof(void*));";
+       print "       output(screen, \"   sizeof(char):    %lu\\n\",(unsigned long)sizeof(char));";
+       print "       output(screen, \"   sizeof(int):     %lu\\n\",(unsigned long)sizeof(int));";
+       print "       output(screen, \"   sizeof(long):    %lu\\n\",(unsigned long)sizeof(long));";
+       print "       output(screen, \"   sizeof(uint8):   %lu\\n\",(unsigned long)sizeof(uint8));";
+       print "       output(screen, \"   sizeof(uint16):  %lu\\n\",(unsigned long)sizeof(uint16));";
+       print "       output(screen, \"   sizeof(uint32):  %lu\\n\",(unsigned long)sizeof(uint32));";
+       print "       output(screen, \"   sizeof(short):   %lu\\n\",(unsigned long)sizeof(short));";
+       print "       output(screen, \"   sizeof(void*):   %lu\\n\",(unsigned long)sizeof(void*));";
 
        ##################################################
        # add code to give information about modules
index e6117245e7aa74bd463608eeecc2977b3399e879..692e82680dbafad4978f173937a2966b73e5ea3e 100644 (file)
 
 #include "includes.h"
 
+#ifdef HAVE_WORKING_CRACKLIB
+#include <crack.h>
+
+#ifndef HAVE_CRACKLIB_DICTPATH
+#ifndef CRACKLIB_DICTPATH
+#define CRACKLIB_DICTPATH SAMBA_CRACKLIB_DICTPATH
+#endif
+#endif
+#endif
+
 extern struct passdb_ops pdb_ops;
 
 static NTSTATUS check_oem_password(const char *user,
@@ -441,25 +451,14 @@ while we were waiting\n", WTERMSIG(wstat)));
        return (chstat);
 }
 
-BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root)
+BOOL chgpasswd(const char *name, const struct passwd *pass, 
+              const char *oldpass, const char *newpass, BOOL as_root)
 {
        pstring passwordprogram;
        pstring chatsequence;
        size_t i;
        size_t len;
 
-       struct passwd *pass;
-
-       if (!name) {
-               DEBUG(1, ("chgpasswd: NULL username specfied !\n"));
-       }
-       
-       pass = Get_Pwnam(name);
-       if (!pass) {
-               DEBUG(1, ("chgpasswd: Username does not exist in system !\n"));
-               return False;
-       }
-
        if (!oldpass) {
                oldpass = "";
        }
@@ -471,13 +470,6 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL
 #endif
 
        /* Take the passed information and test it for minimum criteria */
-       /* Minimum password length */
-       if (strlen(newpass) < lp_min_passwd_length()) {
-               /* too short, must be at least MINPASSWDLENGTH */
-               DEBUG(0, ("chgpasswd: Password Change: user %s, New password is shorter than minimum password length = %d\n",
-                      name, lp_min_passwd_length()));
-               return (False); /* inform the user */
-       }
 
        /* Password is same as old password */
        if (strcmp(oldpass, newpass) == 0) {
@@ -570,7 +562,8 @@ the string %%u, and the given string %s does not.\n", passwordprogram ));
 
 #else /* ALLOW_CHANGE_PASSWORD */
 
-BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root)
+BOOL chgpasswd(const char *name, const struct passwd *pass, 
+              const char *oldpass, const char *newpass, BOOL as_root)
 {
        DEBUG(0, ("chgpasswd: Password changing not compiled in (user=%s)\n", name));
        return (False);
@@ -909,6 +902,8 @@ static NTSTATUS check_oem_password(const char *user,
 
 NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
 {
+       struct passwd *pass;
+
        BOOL ret;
        uint32 min_len;
 
@@ -936,7 +931,47 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
 /*             return NT_STATUS_PWD_TOO_SHORT; */
        }
 
-       /* TODO:  Add cracklib support here */
+       pass = Get_Pwnam(pdb_get_username(hnd));
+       if (!pass) {
+               DEBUG(1, ("check_oem_password: Username does not exist in system !?!\n"));
+       }
+
+#ifdef HAVE_WORKING_CRACKLIB
+       if (pass) {
+               /* if we can, become the user to overcome internal cracklib sillyness */
+               if (!push_sec_ctx())
+                       return NT_STATUS_UNSUCCESSFUL;
+               
+               set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
+               set_re_uid();
+       }
+
+       if (lp_use_cracklib()) {
+               const char *crack_check_reason;
+               DEBUG(4, ("change_oem_password: Checking password for user [%s]"
+                         " against cracklib. \n", pdb_get_username(hnd)));
+               DEBUGADD(4, ("If this is your last message, then something is "
+                            "wrong with cracklib, it might be missing it's "
+                            "dictionaries at %s\n", 
+                            CRACKLIB_DICTPATH));
+               dbgflush();
+
+               crack_check_reason = FascistCheck(new_passwd, (char *)CRACKLIB_DICTPATH);
+               if (crack_check_reason) {
+                       DEBUG(1, ("Password Change: user [%s], "
+                                 "New password failed cracklib test - %s\n",
+                         pdb_get_username(hnd), crack_check_reason));
+                       
+                       /* get back to where we should be */
+                       if (pass)
+                               pop_sec_ctx();
+                       return NT_STATUS_PASSWORD_RESTRICTION;
+               }
+       }
+
+       if (pass)
+               pop_sec_ctx();
+#endif
 
        /*
         * If unix password sync was requested, attempt to change
@@ -951,7 +986,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
         */
        
        if(lp_unix_password_sync() &&
-               !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) {
+               !chgpasswd(pdb_get_username(hnd), pass, old_passwd, new_passwd, as_root)) {
                return NT_STATUS_ACCESS_DENIED;
        }
 
index 46f688a2194060489566a8bbe207a9042be571fe..19f225e9737a2d5f4b66af14287e5737314b7a1c 100644 (file)
@@ -50,33 +50,16 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B
 #ifdef LINUX
 
 #include <sys/types.h>
-#include <asm/types.h>
+#include <mntent.h>
 
 /*
  * This shouldn't be neccessary - it should be /usr/include/sys/quota.h
- * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk
- * rather than the struct dqblk defined in /usr/include/sys/quota.h.
- * This means we must include linux/quota.h to have a hope of working on
- * RH7.1 systems. And it also means this breaks if the kernel is upgraded
- * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until
- * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA.
+ * So we include all the files has *should* be in the system into a large,
+ * grungy samba_linux_quoatas.h Sometimes I *hate* Linux :-). JRA.
  */
 
-#include <linux/quota.h>
-#ifdef HAVE_LINUX_XQM_H
-#include <linux/xqm.h>
-#else
-#ifdef HAVE_XFS_XQM_H
-#include <xfs/xqm.h>
-#define HAVE_LINUX_XQM_H
-#endif
-#endif
-
-#include <mntent.h>
-#include <linux/unistd.h>
-
-
-#define LINUX_QUOTAS_2
+#include "samba_linux_quota.h"
+#include "samba_xfs_quota.h"
 
 typedef struct _LINUX_SMB_DISK_QUOTA {
        SMB_BIG_UINT bsize;
@@ -92,22 +75,20 @@ typedef struct _LINUX_SMB_DISK_QUOTA {
  Abstract out the XFS Quota Manager quota get call.
 ****************************************************************************/
 
-static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
 {
-       int ret = -1;
-#ifdef HAVE_LINUX_XQM_H
        struct fs_disk_quota D;
+       int ret;
 
        ZERO_STRUCT(D);
 
-       ret = quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+       ret = quotactl(QCMD(Q_XGETQUOTA,XFS_USER_QUOTA), path, euser_id, (caddr_t)&D);
 
-       /* As XFS has group quotas, if getting the user quota fails, try getting the group instead. */
-       if (ret) {
-               ret = quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
-               if (ret)
-                       return ret;
-       }
+       if (ret)
+               ret = quotactl(QCMD(Q_XGETQUOTA,XFS_GROUP_QUOTA), path, egrp_id, (caddr_t)&D);
+
+       if (ret)
+               return ret;
 
        dp->bsize = (SMB_BIG_UINT)512;
        dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit;
@@ -116,7 +97,7 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
        dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit;
        dp->curinodes = (SMB_BIG_UINT)D.d_icount;
        dp->curblocks = (SMB_BIG_UINT)D.d_bcount;
-#endif
+
        return ret;
 }
 
@@ -124,48 +105,90 @@ static int get_smb_linux_xfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QU
  Abstract out the old and new Linux quota get calls.
 ****************************************************************************/
 
-static int get_smb_linux_vfs_quota(char *path, uid_t euser_id, LINUX_SMB_DISK_QUOTA *dp)
+static int get_smb_linux_v1_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
 {
-       int ret = 0;
-#ifdef LINUX_QUOTAS_1
-       struct dqblk D;
+       struct v1_kern_dqblk D;
+       int ret;
+
        ZERO_STRUCT(D);
-       dp->bsize = (SMB_BIG_UINT)1024;
-#else /* LINUX_QUOTAS_2 */
-       struct mem_dqblk D;
+
+       ret = quotactl(QCMD(Q_V1_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+       if (ret && errno != EDQUOT)
+               ret = quotactl(QCMD(Q_V1_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+       if (ret && errno != EDQUOT)
+               return ret;
+
+       dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
+
+       return ret;
+}
+
+static int get_smb_linux_v2_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+       struct v2_kern_dqblk D;
+       int ret;
+
        ZERO_STRUCT(D);
-#ifndef QUOTABLOCK_SIZE
-#define QUOTABLOCK_SIZE 1024
-#endif
+
+       ret = quotactl(QCMD(Q_V2_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
+
+       if (ret && errno != EDQUOT)
+               ret = quotactl(QCMD(Q_V2_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
+
+       if (ret && errno != EDQUOT)
+               return ret;
+
        dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
-#endif
+       dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
+       dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
+       dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
+       dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
+       dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
+       dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
+
+       return ret;
+}
+
+/****************************************************************************
+ Brand-new generic quota interface.
+****************************************************************************/
+
+static int get_smb_linux_gen_quota(char *path, uid_t euser_id, gid_t egrp_id, LINUX_SMB_DISK_QUOTA *dp)
+{
+       struct if_dqblk D;
+       int ret;
+
+       ZERO_STRUCT(D);
 
        ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), path, euser_id, (caddr_t)&D);
 
-       /* Linux can have group quotas, if getting the user quota fails, try getting the group instead. */
-       if (ret) {
-               ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, getegid(), (caddr_t)&D);
-               if (ret)
-                       return ret;
-       }
+       if (ret && errno != EDQUOT)
+               ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), path, egrp_id, (caddr_t)&D);
 
+       if (ret && errno != EDQUOT)
+               return ret;
+
+       dp->bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE;
        dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit;
        dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit;
        dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit;
        dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit;
        dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes;
-
-#ifdef LINUX_QUOTAS_1
-       dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks;
-#else /* LINUX_QUOTAS_2 */
-       dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace)/ dp->bsize;
-#endif
+       dp->curblocks = ((SMB_BIG_UINT)D.dqb_curspace) / dp->bsize;
 
        return ret;
 }
 
 /****************************************************************************
-try to get the disk space from disk quotas (LINUX version)
+ Try to get the disk space from disk quotas (LINUX version).
 ****************************************************************************/
 
 BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
@@ -178,9 +201,11 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
        SMB_DEV_T devno;
        int found;
        uid_t euser_id;
+       gid_t egrp_id;
 
        euser_id = geteuid();
-  
+       egrp_id = getegid();
+
        /* find the block device file */
   
        if ( sys_stat(path, &S) == -1 )
@@ -208,10 +233,18 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
 
        save_re_uid();
        set_effective_uid(0);  
-       if (strcmp(mnt->mnt_type, "xfs") == 0)
-               r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, &D);
-       else
-               r=get_smb_linux_vfs_quota(mnt->mnt_fsname, euser_id, &D);
+
+       if (strcmp(mnt->mnt_type, "xfs")==0) {
+               r=get_smb_linux_xfs_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+       } else {
+               r=get_smb_linux_gen_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+               if (r == -1 && errno != EDQUOT) {
+                       r=get_smb_linux_v2_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+                       if (r == -1 && errno != EDQUOT)
+                               r=get_smb_linux_v1_quota(mnt->mnt_fsname, euser_id, egrp_id, &D);
+               }
+       }
+
        restore_re_uid();
 
        /* Use softlimit to determine disk space, except when it has been exceeded */
@@ -920,8 +953,8 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1)<0))
 #else
   if ((sys_stat(path, &S)<0) || (devnm(S_IFBLK, S.st_dev, dev_disk, 256, 0)<0)) 
-#endif /* ifdef HPUX */
        return (False);
+#endif /* ifdef HPUX */
 
 #endif /* !defined(__FreeBSD__) && !defined(AIX) && !defined(__OpenBSD__) */
 
index c98b0936ed07c09510f8d1a0925084b2da7c6ea6..ff7075038551497f4756a6695092aed43bbb0eea 100644 (file)
@@ -853,6 +853,8 @@ static tdb_off tdb_allocate(TDB_CONTEXT *tdb, tdb_len length,
        tdb_off rec_ptr, last_ptr, newrec_ptr;
        struct list_struct newrec;
 
+       memset(&newrec, '\0', sizeof(newrec));
+
        if (tdb_lock(tdb, -1, F_WRLCK) == -1)
                return 0;
 
diff --git a/source3/tests/crack.c b/source3/tests/crack.c
new file mode 100644 (file)
index 0000000..1342887
--- /dev/null
@@ -0,0 +1,5 @@
+
+int main(int argc, char **argv) {
+       FascistCheck("Foo", CRACKLIB_DICTPATH);
+       return 0;
+}
index b28365274c066c21a53d98e2e504a291c7fdbb1d..9f0f64edecb960d0141da0b61d1a0dab82098695 100644 (file)
@@ -48,27 +48,14 @@ typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, struct cli_state *, TALLOC_C
  * @return The Domain SID of the remote machine.
  **/
 
-static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
+static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx)
 {
        DOM_SID *domain_sid;
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_OK;
        uint32 info_class = 5;
-       fstring domain_name;
-       TALLOC_CTX *mem_ctx;
+        char *domain_name;
        
-       if (!(domain_sid = malloc(sizeof(DOM_SID)))){
-               DEBUG(0,("net_get_remote_domain_sid: malloc returned NULL!\n"));
-               goto error;
-       }
-           
-       if (!(mem_ctx=talloc_init("net_get_remote_domain_sid")))
-       {
-               DEBUG(0,("net_get_remote_domain_sid: talloc_init returned NULL!\n"));
-               goto error;
-       }
-
-
        if (!cli_nt_session_open (cli, PI_LSARPC)) {
                fprintf(stderr, "could not initialise lsa pipe\n");
                goto error;
@@ -82,7 +69,7 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
        }
 
        result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
-                                          domain_name, domain_sid);
+                                          &domain_name, &domain_sid);
        if (!NT_STATUS_IS_OK(result)) {
  error:
                fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
@@ -96,7 +83,6 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli)
 
        cli_lsa_close(cli, mem_ctx, &pol);
        cli_nt_session_close(cli);
-       talloc_destroy(mem_ctx);
 
        return domain_sid;
 }
@@ -132,7 +118,7 @@ static int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int co
                return -1;
        }
 
-       domain_sid = net_get_remote_domain_sid(cli);
+       domain_sid = net_get_remote_domain_sid(cli, mem_ctx);
 
        /* Create mem_ctx */
        
@@ -1928,10 +1914,11 @@ static int rpc_trustdom_establish(int argc, const char **argv)
        POLICY_HND connect_hnd;
        TALLOC_CTX *mem_ctx;
        NTSTATUS nt_status;
-       DOM_SID domain_sid;
+       DOM_SID *domain_sid;
        WKS_INFO_100 wks_info;
        
        char* domain_name;
+       char* domain_name_pol;
        char* acct_name;
        fstring pdc_name;
 
@@ -2052,7 +2039,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
        /* Querying info level 5 */
        
        nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
-                                             5 /* info level */, domain_name,
+                                             5 /* info level */, &domain_name_pol,
                                              &domain_sid);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2072,7 +2059,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
 
        if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer,
                                                   wks_info.uni_lan_grp.uni_str_len, opt_password,
-                                                  domain_sid)) {
+                                                  *domain_sid)) {
                DEBUG(0, ("Storing password for trusted domain failed.\n"));
                return -1;
        }
@@ -2163,7 +2150,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        struct cli_state *cli, *remote_cli;
        NTSTATUS nt_status;
        const char *domain_name = NULL;
-       DOM_SID queried_dom_sid;
+       DOM_SID *queried_dom_sid;
        fstring ascii_sid, padding;
        int ascii_dom_name_len;
        POLICY_HND connect_hnd;
@@ -2173,7 +2160,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
        int i, pad_len, col_len = 20;
        DOM_SID *domain_sids;
        char **trusted_dom_names;
-       fstring pdc_name, dummy;
+       fstring pdc_name;
+       char *dummy;
        
        /* trusting domains listing variables */
        POLICY_HND domain_hnd;
@@ -2222,7 +2210,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        /* query info level 5 to obtain sid of a domain being queried */
        nt_status = cli_lsa_query_info_policy(
                cli, mem_ctx, &connect_hnd, 5 /* info level */, 
-               dummy, &queried_dom_sid);
+               &dummy, &queried_dom_sid);
 
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
@@ -2304,8 +2292,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
        /* SamrOpenDomain - we have to open domain policy handle in order to be
           able to enumerate accounts*/
        nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
-                                                                        SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
-                                                                        &queried_dom_sid, &domain_hnd);                                                                         
+                                        SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
+                                        queried_dom_sid, &domain_hnd);                                                                  
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't open domain object. Error was %s\n",
                        nt_errstr(nt_status)));
index 96e52964b43c65357689d38e34154c726fd25ec7..74918045ee992bdf6a5dabac0b38ba5acf1bcad9 100644 (file)
@@ -1072,6 +1072,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
        DATA_BLOB session_key_krb5;
        SPNEGO_DATA reply;
        char *reply_base64;
+       int retval;
        
        const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
        ssize_t len;
@@ -1093,9 +1094,9 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
               spnego.negTokenInit.mechListMIC.length);
        principal[spnego.negTokenInit.mechListMIC.length] = '\0';
 
-       tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
 
-       if (tkt.data == NULL) {
+       if (retval) {
 
                pstring user;
 
@@ -1110,13 +1111,17 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
 
                pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
 
-               if (kerberos_kinit_password(user, opt_password, 0) != 0) {
-                       DEBUG(10, ("Requesting TGT failed\n"));
+               if ((retval = kerberos_kinit_password(user, opt_password, 0))) {
+                       DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
                        x_fprintf(x_stdout, "NA\n");
                        return True;
                }
 
-               tkt = cli_krb5_get_ticket(principal, 0, &session_key_krb5);
+               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
+
+               if (retval) {
+                       DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
+               }
        }
 
        data_blob_free(&session_key_krb5);
index eae1f97b58bedabb4c30d9c85c77643941bf3740..8a27684a4d377142cbef4a8d1b670dda42846148 100644 (file)
@@ -717,7 +717,7 @@ int main(int argc, const char **argv)
                        argc -= 2;
                        break;
                case 's':       /* --configfile */
-                       pstrcpy(dyn_CONFIGFILE, optarg);
+                       pstrcpy(dyn_CONFIGFILE, poptGetOptArg(pc));
                        argc -= 2;
                        break;
                default:
diff --git a/source3/utils/smbget.c b/source3/utils/smbget.c
new file mode 100644 (file)
index 0000000..92a3831
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+   smbget: a wget-like utility with support for recursive downloading and 
+       smb:// urls
+   Copyright (C) 2003-2004 Jelmer Vernooij <jelmer@samba.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+#include "includes.h"
+#include "libsmbclient.h"
+
+#if _FILE_OFFSET_BITS==64
+#define OFF_T_FORMAT "%lld"
+#else
+#define OFF_T_FORMAT "%ld"
+#endif
+
+int columns = 0;
+
+time_t total_start_time = 0;
+off_t total_bytes = 0;
+
+#define SMB_MAXPATHLEN MAXPATHLEN
+
+/* Number of bytes to read when checking whether local and remote file are really the same file */
+#define RESUME_CHECK_SIZE                              512
+#define RESUME_DOWNLOAD_OFFSET                 1024
+#define RESUME_CHECK_OFFSET                            RESUME_DOWNLOAD_OFFSET+RESUME_CHECK_SIZE
+/* Number of bytes to read at once */
+#define SMB_DEFAULT_BLOCKSIZE                                  64000
+
+const char *username = NULL, *password = NULL, *workgroup = NULL;
+int nonprompt = 0, quiet = 0, dots = 0, keep_permissions = 0, verbose = 0;
+int blocksize = SMB_DEFAULT_BLOCKSIZE;
+
+int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile);
+
+int get_num_cols(void)
+{
+#ifdef TIOCGWINSZ
+       struct winsize ws;
+       if(ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) {
+               perror("ioctl");
+               return 0;
+       }
+       return ws.ws_col;
+#else
+#warning No support for TIOCGWINSZ
+       char *cols = getenv("COLUMNS");
+       if(!cols) return 0;
+       return atoi(cols);
+#endif
+}
+
+void change_columns(int sig)
+{
+       columns = get_num_cols();
+}
+
+void human_readable(off_t s, char *buffer, int l)
+{
+       if(s > 1024 * 1024 * 1024) snprintf(buffer, l, "%.2fGb", 1.0 * s / (1024 * 1024 * 1024));
+       else if(s > 1024 * 1024) snprintf(buffer, l, "%.2fMb", 1.0 * s / (1024 * 1024));
+       else if(s > 1024) snprintf(buffer, l, "%.2fkb", 1.0 * s / 1024);
+       else snprintf(buffer, l, OFF_T_FORMAT"b", s);
+}
+
+void get_auth_data(const char *srv, const char *shr, char *wg, int wglen, char *un, int unlen, char *pw, int pwlen)
+{
+       static char hasasked = 0;
+       char *wgtmp, *usertmp;
+       char tmp[128];
+
+       if(hasasked) return;
+       hasasked = 1;
+
+       if(!nonprompt && !username) {
+               printf("Username for %s at %s [guest] ", shr, srv);
+               fgets(tmp, sizeof(tmp), stdin);
+               if(tmp[strlen(tmp)-1] == '\n')tmp[strlen(tmp)-1] = '\0';
+               strncpy(un, tmp, unlen-1);
+       } else if(username) strncpy(un, username, unlen-1);
+
+       if(!nonprompt && !password) {
+               char *prompt, *pass;
+               asprintf(&prompt, "Password for %s at %s: ", shr, srv);
+               pass = getpass(prompt);
+               free(prompt);
+               strncpy(pw, pass, pwlen-1);
+       } else if(password) strncpy(pw, password, pwlen-1);
+
+       if(workgroup)strncpy(wg, workgroup, wglen-1);
+
+       wgtmp = strndup(wg, wglen); 
+       usertmp = strndup(un, unlen);
+       if(!quiet)printf("Using workgroup %s, %s%s\n", wgtmp, *usertmp?"user ":"guest user", usertmp);
+       free(wgtmp); free(usertmp);
+}
+
+int smb_download_dir(const char *base, const char *name, int resume)
+{
+       char path[SMB_MAXPATHLEN];
+       int dirhandle;
+       struct smbc_dirent *dirent;
+       const char *relname = name;
+       char *tmpname;
+       struct stat remotestat;
+       snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (base[0] && name[0] && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name);
+
+       /* List files in directory and call smb_download_file on them */
+       dirhandle = smbc_opendir(path);
+       if(dirhandle < 1) {
+               if(errno == ENOTDIR) return smb_download_file(base, name, 1, resume, NULL);
+               fprintf(stderr, "Can't open directory %s: %s\n", path, strerror(errno));
+               return 0;
+       }
+
+       while(*relname == '/')relname++;
+       mkdir(relname, 0755);
+       
+       tmpname = strdup(name);
+
+       while((dirent = smbc_readdir(dirhandle))) {
+               char *newname;
+               if(!strcmp(dirent->name, ".") || !strcmp(dirent->name, ".."))continue;
+               asprintf(&newname, "%s/%s", tmpname, dirent->name);
+               switch(dirent->smbc_type) {
+               case SMBC_DIR:
+                       smb_download_dir(base, newname, resume);
+                       break;
+
+               case SMBC_WORKGROUP:
+                       smb_download_dir("smb://", dirent->name, resume);
+                       break;
+
+               case SMBC_SERVER:
+                       smb_download_dir("smb://", dirent->name, resume);
+                       break;
+
+               case SMBC_FILE:
+                       smb_download_file(base, newname, 1, resume, NULL);
+                       break;
+
+               case SMBC_FILE_SHARE:
+                       smb_download_dir(base, newname, resume);
+                       break;
+
+               case SMBC_PRINTER_SHARE:
+                       if(!quiet)printf("Ignoring printer share %s\n", dirent->name);
+                       break;
+
+               case SMBC_COMMS_SHARE:
+                       if(!quiet)printf("Ignoring comms share %s\n", dirent->name);
+                       break;
+                       
+               case SMBC_IPC_SHARE:
+                       if(!quiet)printf("Ignoring ipc$ share %s\n", dirent->name);
+                       break;
+
+               default:
+                       fprintf(stderr, "Ignoring file '%s' of type '%d'\n", newname, dirent->smbc_type);
+                       break;
+               }
+               free(newname);
+       }
+       free(tmpname);
+
+       if(keep_permissions) {
+               if(smbc_fstat(dirhandle, &remotestat) < 0) {
+                       fprintf(stderr, "Unable to get stats on %s on remote server\n", path);
+                       smbc_closedir(dirhandle);
+                       return 0;
+               }
+               
+               if(chmod(relname, remotestat.st_mode) < 0) {
+                       fprintf(stderr, "Unable to change mode of local dir %s to %o\n", relname, remotestat.st_mode);
+                       smbc_closedir(dirhandle);
+                       return 0;
+               }
+       }
+
+       smbc_closedir(dirhandle);
+       return 1;
+}
+
+char *print_time(long t)
+{
+       static char buffer[100];
+       int secs, mins, hours;
+       if(t < -1) {
+               strncpy(buffer, "Unknown", sizeof(buffer));
+               return buffer;
+       }
+
+       secs = (int)t % 60;
+       mins = (int)t / 60 % 60;
+       hours = (int)t / (60 * 60);
+       snprintf(buffer, sizeof(buffer)-1, "%02d:%02d:%02d", hours, mins, secs);
+       return buffer;
+}
+
+void print_progress(const char *name, time_t start, time_t now, off_t start_pos, off_t pos, off_t total)
+{
+       double avg = 0.0;
+       long  eta = -1; 
+       double prcnt = 0.0;
+       char hpos[20], htotal[20], havg[20];
+       char *status, *filename;
+       int len;
+       if(now - start)avg = 1.0 * (pos - start_pos) / (now - start);
+       eta = (total - pos - start_pos) / avg;
+       if(total)prcnt = 100.0 * pos / total;
+
+       human_readable(pos, hpos, sizeof(hpos));
+       human_readable(total, htotal, sizeof(htotal));
+       human_readable(avg, havg, sizeof(havg));
+
+       len = asprintf(&status, "%s of %s (%.2f%%) at %s/s ETA: %s", hpos, htotal, prcnt, havg, print_time(eta));
+       
+       if(columns) {
+               int required = strlen(name), available = columns - len - strlen("[] ");
+               if(required > available) asprintf(&filename, "...%s", name + required - available + 3);
+               else filename = strndup(name, available);
+       } else filename = strdup(name);
+
+       fprintf(stderr, "\r[%s] %s", filename, status);
+
+       free(filename); free(status);
+}
+
+int smb_download_file(const char *base, const char *name, int recursive, int resume, char *outfile) {
+       int remotehandle, localhandle;
+       time_t start_time = time(NULL);
+       const char *newpath;
+       char path[SMB_MAXPATHLEN];
+       char checkbuf[2][RESUME_CHECK_SIZE];
+       char *readbuf = NULL;
+       off_t offset_download = 0, offset_check = 0, curpos = 0, start_offset = 0;
+       struct stat localstat, remotestat;
+
+       snprintf(path, SMB_MAXPATHLEN-1, "%s%s%s", base, (*base && *name && name[0] != '/' && base[strlen(base)-1] != '/')?"/":"", name);
+       
+       remotehandle = smbc_open(path, O_RDONLY, 0755);
+
+       if(remotehandle < 0) {
+               switch(errno) {
+               case EISDIR: 
+                       if(!recursive) {
+                               fprintf(stderr, "%s is a directory. Specify -R to download recursively\n", path);
+                               return 0;
+                       }
+                       smb_download_dir(base, name, resume);
+                       return 0;
+
+               case ENOENT:
+                       fprintf(stderr, "%s can't be found on the remote server\n", path);
+                       return 0;
+
+               case ENOMEM:
+                       fprintf(stderr, "Not enough memory\n");
+                       exit(1);
+                       return 0;
+
+               case ENODEV:
+                       fprintf(stderr, "The share name used in %s does not exist\n", path);
+                       return 0;
+
+               case EACCES:
+                       fprintf(stderr, "You don't have enough permissions to access %s\n", path);
+                       return 0;
+
+               default:
+                       perror("smbc_open");
+                       return 0;
+               }
+       } 
+
+       if(smbc_fstat(remotehandle, &remotestat) < 0) {
+               fprintf(stderr, "Can't stat %s: %s\n", path, strerror(errno));
+               return 0;
+       }
+
+       if(outfile) newpath = outfile;
+       else if(!name[0]) {
+               newpath = strrchr(base, '/');
+               if(newpath)newpath++; else newpath = base;
+       } else newpath = name;
+
+       if(newpath[0] == '/')newpath++;
+       
+       /* Open local file and, if necessary, resume */
+       localhandle = open(newpath, O_CREAT | O_NONBLOCK | O_RDWR | (!resume?O_EXCL:0), 0755);
+       if(localhandle < 0) {
+               fprintf(stderr, "Can't open %s: %s\n", newpath, strerror(errno));
+               smbc_close(remotehandle);
+               return 0;
+       }
+       
+       fstat(localhandle, &localstat);
+
+       start_offset = localstat.st_size;
+
+       if(localstat.st_size && localstat.st_size == remotestat.st_size) {
+               if(verbose)fprintf(stderr, "%s is already downloaded completely.\n", path);
+               else if(!quiet)fprintf(stderr, "%s\n", path);
+               smbc_close(remotehandle);
+               close(localhandle);
+               return 1;
+       }
+
+       if(localstat.st_size > RESUME_CHECK_OFFSET && remotestat.st_size > RESUME_CHECK_OFFSET) {
+               offset_download = localstat.st_size - RESUME_DOWNLOAD_OFFSET;
+               offset_check = localstat.st_size - RESUME_CHECK_OFFSET;
+               if(verbose)printf("Trying to start resume of %s at "OFF_T_FORMAT"\n"
+                          "At the moment "OFF_T_FORMAT" of "OFF_T_FORMAT" bytes have been retrieved\n", newpath, offset_check, 
+                          localstat.st_size, remotestat.st_size);
+       }
+
+       if(offset_check) { 
+               off_t off1, off2;
+               /* First, check all bytes from offset_check to offset_download */
+               off1 = lseek(localhandle, offset_check, SEEK_SET);
+               if(off1 < 0) {
+                       fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in local file %s\n", offset_check, newpath);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+
+               off2 = smbc_lseek(remotehandle, offset_check, SEEK_SET); 
+               if(off2 < 0) {
+                       fprintf(stderr, "Can't seek to "OFF_T_FORMAT" in remote file %s\n", offset_check, newpath);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+
+               if(off1 != off2) {
+                       fprintf(stderr, "Offset in local and remote files is different (local: "OFF_T_FORMAT", remote: "OFF_T_FORMAT")\n", off1, off2);
+                       return 0;
+               }
+
+               if(smbc_read(remotehandle, checkbuf[0], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) {
+                       fprintf(stderr, "Can't read %d bytes from remote file %s\n", RESUME_CHECK_SIZE, path);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+
+               if(read(localhandle, checkbuf[1], RESUME_CHECK_SIZE) != RESUME_CHECK_SIZE) {
+                       fprintf(stderr, "Can't read %d bytes from local file %s\n", RESUME_CHECK_SIZE, name);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+
+               if(memcmp(checkbuf[0], checkbuf[1], RESUME_CHECK_SIZE) == 0) {
+                       if(verbose)printf("Current local and remote file appear to be the same. Starting download from offset "OFF_T_FORMAT"\n", offset_download);
+               } else {
+                       fprintf(stderr, "Local and remote file appear to be different, not doing resume for %s\n", path);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+       }
+
+       readbuf = malloc(blocksize);
+
+       /* Now, download all bytes from offset_download to the end */
+       for(curpos = offset_download; curpos < remotestat.st_size; curpos+=blocksize) {
+               ssize_t bytesread = smbc_read(remotehandle, readbuf, blocksize);
+               if(bytesread < 0) {
+                       fprintf(stderr, "Can't read %d bytes at offset "OFF_T_FORMAT", file %s\n", blocksize, curpos, path);
+                       smbc_close(remotehandle); close(localhandle);
+                       free(readbuf);
+                       return 0;
+               }
+
+               total_bytes += bytesread;
+
+               if(write(localhandle, readbuf, bytesread) < 0) {
+                       fprintf(stderr, "Can't write %d bytes to local file %s at offset "OFF_T_FORMAT"\n", bytesread, path, curpos);
+                       free(readbuf);
+                       smbc_close(remotehandle); close(localhandle);
+                       return 0;
+               }
+
+               if(dots)fputc('.', stderr);
+               else if(!quiet) {
+                       print_progress(newpath, start_time, time(NULL), start_offset, curpos, remotestat.st_size);
+               }
+       }
+
+       free(readbuf);
+
+       if(dots){
+               fputc('\n', stderr);
+               printf("%s downloaded\n", path);
+       } else if(!quiet) {
+               int i;
+               fprintf(stderr, "\r%s", path);
+               if(columns) {
+                       for(i = strlen(path); i < columns; i++) {
+                               fputc(' ', stderr);
+                       }
+               }
+               fputc('\n', stderr);
+       }
+
+       if(keep_permissions) {
+               if(fchmod(localhandle, remotestat.st_mode) < 0) {
+                       fprintf(stderr, "Unable to change mode of local file %s to %o\n", path, remotestat.st_mode);
+                       smbc_close(remotehandle);
+                       close(localhandle);
+                       return 0;
+               }
+       }
+       smbc_close(remotehandle);
+       close(localhandle);
+       return 1;
+}
+
+void clean_exit(void)
+{
+       char bs[100];
+       human_readable(total_bytes, bs, sizeof(bs));
+       if(!quiet)fprintf(stderr, "Downloaded %s in %lu seconds\n", bs, time(NULL) - total_start_time);
+       exit(0);
+}
+
+void signal_quit(int v)
+{
+       clean_exit();
+}
+
+int readrcfile(const char *name, const struct poptOption long_options[])
+{
+       FILE *fd = fopen(name, "r");
+       int lineno = 0, i;
+       char var[101], val[101];
+       char found;
+       int *intdata; char **stringdata;
+       if(!fd) {
+               fprintf(stderr, "Can't open RC file %s\n", name);
+               return 1;
+       }
+
+       while(!feof(fd)) {
+               lineno++;
+               if(fscanf(fd, "%100s %100s\n", var, val) < 2) {
+                       fprintf(stderr, "Can't parse line %d of %s, ignoring.\n", lineno, name);
+                       continue;
+               }
+
+               found = 0;
+
+               for(i = 0; long_options[i].shortName; i++) {
+                       if(!long_options[i].longName)continue;
+                       if(strcmp(long_options[i].longName, var)) continue;
+                       if(!long_options[i].arg)continue;
+
+                       switch(long_options[i].argInfo) {
+                       case POPT_ARG_NONE:
+                               intdata = (int *)long_options[i].arg;
+                               if(!strcmp(val, "on")) *intdata = 1;
+                               else if(!strcmp(val, "off")) *intdata = 0;
+                               else fprintf(stderr, "Illegal value %s for %s at line %d in %s\n", val, var, lineno, name);
+                               break;
+                       case POPT_ARG_INT:
+                               intdata = (int *)long_options[i].arg;
+                               *intdata = atoi(val);
+                               break;
+                       case POPT_ARG_STRING:
+                               stringdata = (char **)long_options[i].arg;
+                               *stringdata = strdup(val);
+                               break;
+                       default:
+                               fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name);
+                               break;
+                       }
+
+                       found = 1;
+               }
+               if(!found) {
+                       fprintf(stderr, "Invalid variable %s at line %d in %s\n", var, lineno, name);
+               }
+       }
+
+       fclose(fd);
+       return 0;
+}
+
+int main(int argc, const char **argv)
+{
+       int resume = 0, recursive = 0;
+       int c = 0;
+       int debuglevel = 0;
+       const char *file = NULL;
+       char *rcfile = NULL;
+       char *outputfile = NULL;
+       struct poptOption long_options[] = {
+               {"guest", 'a', POPT_ARG_NONE, NULL, 'a', "Work as user guest" },        
+               {"resume", 'r', POPT_ARG_NONE, &resume, 0, "Automatically resume aborted files" },
+               {"recursive", 'R',  POPT_ARG_NONE, &recursive, 0, "Recursively download files" },
+               {"username", 'u', POPT_ARG_STRING, &username, 'u', "Username to use" },
+               {"password", 'p', POPT_ARG_STRING, &password, 'p', "Password to use" },
+               {"workgroup", 'w', POPT_ARG_STRING, &workgroup, 'w', "Workgroup to use (optional)" },
+               {"nonprompt", 'n', POPT_ARG_NONE, &nonprompt, 'n', "Don't ask anything (non-interactive)" },
+               {"debuglevel", 'd', POPT_ARG_INT, &debuglevel, 'd', "Debuglevel to use" },
+               {"outputfile", 'o', POPT_ARG_STRING, &outputfile, 'o', "Write downloaded data to specified file" },
+               {"dots", 'D', POPT_ARG_NONE, &dots, 'D', "Show dots as progress indication" },
+               {"quiet", 'q', POPT_ARG_NONE, &quiet, 'q', "Be quiet" },
+               {"verbose", 'v', POPT_ARG_NONE, &verbose, 'v', "Be verbose" },
+               {"keep-permissions", 'P', POPT_ARG_NONE, &keep_permissions, 'P', "Keep permissions" },
+               {"blocksize", 'b', POPT_ARG_INT, &blocksize, 'b', "Change number of bytes in a block"},
+               {"rcfile", 'f', POPT_ARG_STRING, NULL, 0, "Use specified rc file"},
+               POPT_AUTOHELP
+               POPT_TABLEEND
+       };
+       poptContext pc;
+
+       /* only read rcfile if it exists */
+       asprintf(&rcfile, "%s/.smbgetrc", getenv("HOME"));
+       if(access(rcfile, F_OK) == 0) readrcfile(rcfile, long_options);
+       free(rcfile);
+
+#ifdef SIGWINCH
+       signal(SIGWINCH, change_columns);
+#endif
+       signal(SIGINT, signal_quit);
+       signal(SIGTERM, signal_quit);
+
+       pc = poptGetContext(argv[0], argc, argv, long_options, 0);
+
+       while((c = poptGetNextOpt(pc)) >= 0) {
+               switch(c) {
+               case 'f':
+                       readrcfile(poptGetOptArg(pc), long_options);
+                       break;
+               case 'a':
+                       username = ""; password = "";
+                       break;
+               }
+       }
+
+       if(outputfile && recursive) {
+               fprintf(stderr, "The -o and -R options can not be used together.\n");
+               return 1;
+       }
+
+       if(smbc_init(get_auth_data, debuglevel) < 0) {
+               fprintf(stderr, "Unable to initialize libsmbclient\n");
+               return 1;
+       }
+
+       columns = get_num_cols();
+
+       total_start_time = time(NULL);
+
+       while((file = poptGetArg(pc))) {
+               if(!recursive) return smb_download_file(file, "", recursive, resume, outputfile);
+               else return smb_download_dir(file, "", resume);
+       }
+
+       clean_exit();
+
+       return 0;
+}