+#endif /* NEED_QUOTACTL_WRAPPER */
+
+static int overquota( struct dqblk *);
+
+#ifdef linux
+
+#ifdef HAVE_LINUX_XQM_H
+#include <linux/xqm.h>
+#else
+#ifdef HAVE_XFS_XQM_H
+#include <xfs/xqm.h>
+#define HAVE_LINUX_XQM_H
+#else
+#ifdef HAVE_LINUX_DQBLK_XFS_H
+#include <linux/dqblk_xfs.h>
+#define HAVE_LINUX_XQM_H
+#endif /* HAVE_LINUX_DQBLK_XFS_H */
+#endif /* HAVE_XFS_XQM_H */
+#endif /* HAVE_LINUX_XQM_H */
+
+#include <linux/unistd.h>
+
+static int is_xfs = 0;
+
+static int get_linux_xfs_quota(int, char*, uid_t, struct dqblk *);
+static int get_linux_fs_quota(int, char*, uid_t, struct dqblk *);
+
+/* format supported by current kernel */
+static int kernel_iface = IFACE_UNSET;
+
+/*
+** Check kernel quota version
+** Taken from quota-tools 3.08 by Jan Kara <jack@suse.cz>
+*/
+static void linuxquota_get_api( void )
+{
+#ifndef LINUX_API_VERSION
+ struct stat st;
+
+ if (stat("/proc/sys/fs/quota", &st) == 0) {
+ kernel_iface = IFACE_GENERIC;
+ }
+ else {
+ struct dqstats_v2 v2_stats;
+ struct sigaction sig;
+ struct sigaction oldsig;
+
+ /* This signal handling is needed because old kernels send us SIGSEGV as they try to resolve the device */
+ sig.sa_handler = SIG_IGN;
+ sig.sa_sigaction = NULL;
+ sig.sa_flags = 0;
+ sigemptyset(&sig.sa_mask);
+ if (sigaction(SIGSEGV, &sig, &oldsig) < 0) {
+ LOG( log_error, logtype_afpd, "cannot set SEGV signal handler: %s", strerror(errno));
+ goto failure;
+ }
+ if (quotactl(QCMD(Q_V2_GETSTATS, 0), NULL, 0, (void *)&v2_stats) >= 0) {
+ kernel_iface = IFACE_VFSV0;
+ }
+ else if (errno != ENOSYS && errno != ENOTSUP) {
+ /* RedHat 7.1 (2.4.2-2) newquota check
+ * Q_V2_GETSTATS in it's old place, Q_GETQUOTA in the new place
+ * (they haven't moved Q_GETSTATS to its new value) */
+ int err_stat = 0;
+ int err_quota = 0;
+ char tmp[1024]; /* Just temporary buffer */
+
+ if (quotactl(QCMD(Q_V1_GETSTATS, 0), NULL, 0, tmp))
+ err_stat = errno;
+ if (quotactl(QCMD(Q_V1_GETQUOTA, 0), "/dev/null", 0, tmp))
+ err_quota = errno;
+
+ /* On a RedHat 2.4.2-2 we expect 0, EINVAL
+ * On a 2.4.x we expect 0, ENOENT
+ * On a 2.4.x-ac we wont get here */
+ if (err_stat == 0 && err_quota == EINVAL) {
+ kernel_iface = IFACE_VFSV0;
+ }
+ else {
+ kernel_iface = IFACE_VFSOLD;
+ }
+ }
+ else {
+ /* This branch is *not* in quota-tools 3.08
+ ** but without it quota version is not correctly
+ ** identified for the original SuSE 8.0 kernel */
+ unsigned int vers_no;
+ FILE * qf;
+
+ if ((qf = fopen("/proc/fs/quota", "r"))) {
+ if (fscanf(qf, "Version %u", &vers_no) == 1) {
+ if ( (vers_no == (6*10000 + 5*100 + 0)) ||
+ (vers_no == (6*10000 + 5*100 + 1)) ) {
+ kernel_iface = IFACE_VFSV0;
+ }
+ }
+ fclose(qf);
+ }
+ }
+ if (sigaction(SIGSEGV, &oldsig, NULL) < 0) {
+ LOG(log_error, logtype_afpd, "cannot reset signal handler: %s", strerror(errno));
+ goto failure;
+ }
+ }
+
+failure:
+ if (kernel_iface == IFACE_UNSET)
+ kernel_iface = IFACE_VFSOLD;
+
+#else /* defined LINUX_API_VERSION */
+ kernel_iface = LINUX_API_VERSION;