bug-findutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH]: xfs project quota id support


From: Arkadiusz Miskiewicz
Subject: [PATCH]: xfs project quota id support
Date: Mon, 11 Oct 2010 10:43:05 +0200
User-agent: KMail/1.13.5 (Linux/2.6.36-rc7; KDE/4.5.2; x86_64; ; )

Hi,

Long time ago I've submitted xfs project quota id support
through patches interface (https://savannah.gnu.org/patch/?6698).

Topic isn't exciting as I got no comments ;)

Anyway I would like to clean up the patch and make it into mergeable
state iif such feature patches have a chance to be merged.

Little review of the patch would be welcome.

Thanks,

From 11745d10f0c0c702716b7d40ecd3c2a7e5994313 Mon Sep 17 00:00:00 2001
From: Arkadiusz Miskiewicz <address@hidden>
Date: Tue, 16 Dec 2008 17:12:55 +0100
Subject: [PATCH] find: "XFS project quota" support

XFS filesystem provides three different quota types. UID-based,
GID-based and "project quota" path name based.

Add support for test parameter "-xfsprojquota N" which allows
looking for files with specified project quota ID.

Add support for "%q" format which allows project quota ID
to be displayed.

Note that issuing ioctl(2) requires file to be open(2) which
is bad for some type of files (exclude these as xfs_quota does).

Example:
$ ./find /home/users/arekm/xtest -printf "name=%f projquotaid=%q\n"
name=xtest projquotaid=0
name=proj50 projquotaid=50
name=aaa projquotaid=50
name=aaadsfdsf projquotaid=50
name=something projquotaid=50
name=34knjf projquotaid=50
name=proj60 projquotaid=60
name=34knjf projquotaid=60
name=34knjfwenhwjqe projquotaid=60
name=dsfdsfknjfwenhwjqe projquotaid=60
name=proj70 projquotaid=70
name=7sfdsfdsf projquotaid=70
name=7sf4344 projquotaid=70
name=7sf4344ad projquotaid=70

$ ./find /home/users/arekm/xtest -xfsprojquota 50
/home/users/arekm/xtest/proj50
/home/users/arekm/xtest/proj50/aaa
/home/users/arekm/xtest/proj50/aaadsfdsf
/home/users/arekm/xtest/proj50/something
/home/users/arekm/xtest/proj50/34knjf
---
 find/defs.h   |   25 +++++++++++++++++-
 find/find.1   |    2 +
 find/parser.c |   20 +++++++++++++-
 find/pred.c   |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 find/tree.c   |    1 +
 5 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/find/defs.h b/find/defs.h
index 1708d83..ccdddc3 100644
--- a/find/defs.h
+++ b/find/defs.h
@@ -39,6 +39,7 @@ Please stop compiling the program now
 
 /* XXX: some of these includes probably don't belong in a common header file */
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <stdio.h>             /* for FILE* */
 #include <string.h>
 #include <stdlib.h>
@@ -65,6 +66,27 @@ typedef bool boolean;
 #include "buildcmd.h"
 #include "quotearg.h"
 
+#ifndef XFS_IOC_FSGETXATTR
+struct fsxattr
+{
+  uint32_t      fsx_xflags;     /* xflags field value (get/set) */
+  uint32_t      fsx_extsize;    /* extsize field value (get/set)*/
+  uint32_t      fsx_nextents;   /* nextents field value (get)   */
+  uint32_t      fsx_projid;     /* project identifier (get/set) */
+  unsigned char fsx_pad[12];
+};
+
+#define XFS_IOC_FSGETXATTR      _IOR ('X', 31, struct fsxattr)
+#endif
+
+#define XFS_EXCLUDED_FILE_TYPES(x) \
+  (S_ISCHR((x)) \
+  || S_ISBLK((x)) \
+  || S_ISFIFO((x)) \
+  || S_ISLNK((x)) \
+  || S_ISSOCK((x)))
+
+
 /* These days we will assume ANSI/ISO C protootypes work on our compiler. */
 #define PARAMS(Args) Args
 
@@ -306,7 +328,7 @@ struct predicate
     const char *str;           /* fstype [i]lname [i]name [i]path */
     struct re_pattern_buffer *regex; /* regex */
     struct exec_val exec_vec;  /* exec ok */
-    struct long_val numinfo;   /* gid inum links  uid */
+    struct long_val numinfo;   /* gid inum links uid xfsprojquota */
     struct size_val size;      /* size */
     uid_t uid;                 /* user */
     gid_t gid;                 /* group */
@@ -458,6 +480,7 @@ PREDICATEFUNCTION pred_uid;
 PREDICATEFUNCTION pred_used;
 PREDICATEFUNCTION pred_user;
 PREDICATEFUNCTION pred_writable;
+PREDICATEFUNCTION pred_xfsprojquota;
 PREDICATEFUNCTION pred_xtype;
 
 
diff --git a/find/find.1 b/find/find.1
index 25953fc..a4a783f 100644
--- a/find/find.1
+++ b/find/find.1
@@ -1327,6 +1327,8 @@ File's name.
 .IP %P
 File's name with the name of the command line argument under which
 it was found removed.
+.IP %q
+XFS filesystem project quota ID.
 .IP %s
 File's size in bytes.
 .IP %S 
diff --git a/find/parser.c b/find/parser.c
index 102eb7d..feb3fea 100644
--- a/find/parser.c
+++ b/find/parser.c
@@ -145,6 +145,7 @@ static boolean parse_time          PARAMS((const struct 
parser_table*, char *arg
 static boolean parse_true          PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
 static boolean parse_type          PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
 static boolean parse_uid           PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
+static boolean parse_xfsprojquota  PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
 static boolean parse_used          PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
 static boolean parse_user          PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
 static boolean parse_version       PARAMS((const struct parser_table*, char 
*argv[], int *arg_ptr));
@@ -320,6 +321,7 @@ static struct parser_table const parse_table[] =
   PARSE_TEST_NP    ("wholename",             wholename), /* GNU, replaced 
-path, but anyway -path will soon be in POSIX */
   {ARG_TEST,       "writable",               parse_accesscheck, 
pred_writable}, /* GNU, 4.3.0+ */
   PARSE_OPTION     ("xdev",                  xdev), /* POSIX */
+  PARSE_TEST       ("xfsprojquota",          xfsprojquota), /* XFS Project 
Quota ID */
   PARSE_TEST       ("xtype",                 xtype),        /* GNU */
 #ifdef UNIMPLEMENTED_UNIX
   /* It's pretty ugly for find to know about archive formats.
@@ -1127,7 +1129,7 @@ tests (N can be +N or -N or N): -amin N -anewer FILE 
-atime N -cmin N\n\
       -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
       -readable -writable -executable\n\
       -wholename PATTERN -size N[bcwkMG] -true -type [bcdpflsD] -uid N\n\
-      -used N -user NAME -xtype [bcdpfls]\n"));
+      -used N -user NAME -xfsprojquota N -xtype [bcdpfls]\n"));
   puts (_("\
 actions: -delete -print0 -printf FORMAT -fprintf FILE FORMAT -print \n\
       -fprint0 FILE -fprint FILE -ls -fls FILE -prune -quit\n\
@@ -2562,6 +2564,19 @@ parse_warn (const struct parser_table* entry, char 
**argv, int *arg_ptr)
 }
 
 static boolean
+parse_xfsprojquota (const struct parser_table* entry, char **argv, int 
*arg_ptr)
+{
+  struct predicate *p = insert_num (argv, arg_ptr, entry);
+  if (p)
+  {
+    /* XXX: how to do if (parent dir has xfsprojid) { est_success_rate = 99 } 
else { 0.2 } ? */
+    p->est_success_rate = 0.2;
+    return true;
+  }
+  return false;
+}
+
+static boolean
 parse_xtype (const struct parser_table* entry, char **argv, int *arg_ptr)
 {
   return insert_type (argv, arg_ptr, entry, pred_xtype);
@@ -2784,7 +2799,7 @@ insert_fprintf (struct format_val *vec,
          if (*scan2 == '.')
            for (scan2++; ISDIGIT (*scan2); scan2++)
              /* Do nothing. */ ;
-         if (strchr ("abcdDfFgGhHiklmMnpPsStuUyY", *scan2))
+         if (strchr ("abcdDfFgGhHiklmMnpPqsStuUyY", *scan2))
            {
              segmentp = make_segment (segmentp, format, scan2 - format,
                                       KIND_FORMAT, *scan2, 0,
@@ -2927,6 +2942,7 @@ make_segment (struct segment **segment,
     case 'D':                   /* Filesystem device on which the file exits */
     case 'k':                  /* size in 1K blocks */
     case 'n':                  /* number of links */
+    case 'q':                  /* XFS Project Quota ID */
       pred->need_stat = true;
       mycost = NeedsStatInfo;
       *fmt++ = 's';
diff --git a/find/pred.c b/find/pred.c
index a458803..a51adbd 100644
--- a/find/pred.c
+++ b/find/pred.c
@@ -26,6 +26,7 @@
 #include <grp.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <errno.h>
 #include <assert.h>
 #include <stdarg.h>
@@ -229,6 +230,7 @@ struct pred_assoc pred_table[] =
   {pred_used, "used    "},
   {pred_user, "user    "},
   {pred_writable, "writable "},
+  {pred_xfsprojquota, "xfsprojquota "},
   {pred_xtype, "xtype   "},
   {0, "none    "}
 };
@@ -954,6 +956,32 @@ do_fprintf(struct format_val *dest,
          checked_print_quoted (dest, segment->text, cp);
          break;
          
+       case 'q':
+         {
+           if (!XFS_EXCLUDED_FILE_TYPES(stat_buf->st_mode)
+                           && (strcmp (filesystem_type (stat_buf, pathname), 
"xfs") == 0)) {
+             int fd;
+             struct fsxattr fsx;
+
+             if ((fd = openat(state.cwd_dir_fd, state.rel_pathname, 
O_RDONLY|O_NOCTTY
+#if defined O_LARGEFILE
+                           |O_LARGEFILE
+#endif
+                     )) >= 0) {
+               if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) >= 0) {
+                 checked_fprintf (dest, segment->text,
+                               human_readable ((uintmax_t) fsx.fsx_projid, 
hbuf,
+                                       human_ceiling, 1, 1));
+               }
+               close(fd);
+             }
+           }
+
+           /* Do nothing. */
+           /*FALLTHROUGH*/
+           break;
+         }
+
        case 's':               /* size in bytes */
          /* UNTRUSTED, probably unexploitable */
          checked_fprintf (dest, segment->text,
@@ -1804,6 +1832,58 @@ pred_user (const char *pathname, struct stat *stat_buf, 
struct predicate *pred_p
   else
     return (false);
 }
+
+boolean
+pred_xfsprojquota(const char *pathname, struct stat *stat_buf, struct 
predicate *pred_ptr)
+{
+  int fd;
+  struct fsxattr fsx;
+
+  if (XFS_EXCLUDED_FILE_TYPES(stat_buf->st_mode))
+    return false;
+
+  if (strcmp (filesystem_type (stat_buf, pathname), "xfs"))
+    return false;
+
+  if ((fd = openat(state.cwd_dir_fd, state.rel_pathname, O_RDONLY|O_NOCTTY
+#if defined O_LARGEFILE
+                 |O_LARGEFILE
+#endif
+                 )) < 0)
+  {
+         error (0, errno, "%s", safely_quote_err_filename(0, pathname));
+         state.exit_status = 1;
+         return false;
+  }
+
+  if ((ioctl(fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) {
+         error (0, errno, "%s", safely_quote_err_filename(0, pathname));
+         state.exit_status = 1;
+         close(fd);
+         return false;
+  }
+
+  close(fd);
+
+  switch (pred_ptr->args.numinfo.kind)
+    {
+    case COMP_GT:
+      if (fsx.fsx_projid > pred_ptr->args.numinfo.l_val)
+       return (true);
+      break;
+    case COMP_LT:
+      if (fsx.fsx_projid < pred_ptr->args.numinfo.l_val)
+       return (true);
+      break;
+    case COMP_EQ:
+      if (fsx.fsx_projid == pred_ptr->args.numinfo.l_val)
+       return (true);
+      break;
+    }
+  return (false);
+
+}
+
 
 boolean
 pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate 
*pred_ptr)
diff --git a/find/tree.c b/find/tree.c
index 7420c60..e5c0683 100644
--- a/find/tree.c
+++ b/find/tree.c
@@ -950,6 +950,7 @@ static struct pred_cost_lookup costlookup[] =
     { pred_true             ,  NeedsNothing         },
     { pred_type      ,  NeedsType            },
     { pred_uid       ,  NeedsStatInfo        },
+    { pred_xfsprojquota, NeedsNothing        },
     { pred_used      ,  NeedsStatInfo        },
     { pred_user      ,  NeedsStatInfo        },
     { pred_writable  ,  NeedsAccessInfo      },
-- 
1.6.0.5


-- 
Arkadiusz Miƛkiewicz        PLD/Linux Team
arekm / maven.pl            http://ftp.pld-linux.org/



reply via email to

[Prev in Thread] Current Thread [Next in Thread]