The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/cmd/zfs/zfs_project.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * CDDL HEADER START
    3  *
    4  * The contents of this file are subject to the terms of the
    5  * Common Development and Distribution License (the "License").
    6  * You may not use this file except in compliance with the License.
    7  *
    8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
    9  * or https://opensource.org/licenses/CDDL-1.0.
   10  * See the License for the specific language governing permissions
   11  * and limitations under the License.
   12  *
   13  * When distributing Covered Code, include this CDDL HEADER in each
   14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
   15  * If applicable, add the following below this CDDL HEADER, with the
   16  * fields enclosed by brackets "[]" replaced with your own identifying
   17  * information: Portions Copyright [yyyy] [name of copyright owner]
   18  *
   19  * CDDL HEADER END
   20  */
   21 
   22 /*
   23  * Copyright (c) 2017, Intle Corporation. All rights reserved.
   24  */
   25 
   26 #include <errno.h>
   27 #include <getopt.h>
   28 #include <stdio.h>
   29 #include <stdlib.h>
   30 #include <string.h>
   31 #include <unistd.h>
   32 #include <fcntl.h>
   33 #include <dirent.h>
   34 #include <stddef.h>
   35 #include <libintl.h>
   36 #include <sys/stat.h>
   37 #include <sys/types.h>
   38 #include <sys/list.h>
   39 #include <sys/zfs_project.h>
   40 
   41 #include "zfs_util.h"
   42 #include "zfs_projectutil.h"
   43 
   44 typedef struct zfs_project_item {
   45         list_node_t     zpi_list;
   46         char            zpi_name[0];
   47 } zfs_project_item_t;
   48 
   49 static void
   50 zfs_project_item_alloc(list_t *head, const char *name)
   51 {
   52         zfs_project_item_t *zpi;
   53 
   54         zpi = safe_malloc(sizeof (zfs_project_item_t) + strlen(name) + 1);
   55         strcpy(zpi->zpi_name, name);
   56         list_insert_tail(head, zpi);
   57 }
   58 
   59 static int
   60 zfs_project_sanity_check(const char *name, zfs_project_control_t *zpc,
   61     struct stat *st)
   62 {
   63         int ret;
   64 
   65         ret = stat(name, st);
   66         if (ret) {
   67                 (void) fprintf(stderr, gettext("failed to stat %s: %s\n"),
   68                     name, strerror(errno));
   69                 return (ret);
   70         }
   71 
   72         if (!S_ISREG(st->st_mode) && !S_ISDIR(st->st_mode)) {
   73                 (void) fprintf(stderr, gettext("only support project quota on "
   74                     "regular file or directory\n"));
   75                 return (-1);
   76         }
   77 
   78         if (!S_ISDIR(st->st_mode)) {
   79                 if (zpc->zpc_dironly) {
   80                         (void) fprintf(stderr, gettext(
   81                             "'-d' option on non-dir target %s\n"), name);
   82                         return (-1);
   83                 }
   84 
   85                 if (zpc->zpc_recursive) {
   86                         (void) fprintf(stderr, gettext(
   87                             "'-r' option on non-dir target %s\n"), name);
   88                         return (-1);
   89                 }
   90         }
   91 
   92         return (0);
   93 }
   94 
   95 static int
   96 zfs_project_load_projid(const char *name, zfs_project_control_t *zpc)
   97 {
   98         zfsxattr_t fsx;
   99         int ret, fd;
  100 
  101         fd = open(name, O_RDONLY | O_NOCTTY);
  102         if (fd < 0) {
  103                 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
  104                     name, strerror(errno));
  105                 return (fd);
  106         }
  107 
  108         ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
  109         if (ret)
  110                 (void) fprintf(stderr,
  111                     gettext("failed to get xattr for %s: %s\n"),
  112                     name, strerror(errno));
  113         else
  114                 zpc->zpc_expected_projid = fsx.fsx_projid;
  115 
  116         close(fd);
  117         return (ret);
  118 }
  119 
  120 static int
  121 zfs_project_handle_one(const char *name, zfs_project_control_t *zpc)
  122 {
  123         zfsxattr_t fsx;
  124         int ret, fd;
  125 
  126         fd = open(name, O_RDONLY | O_NOCTTY);
  127         if (fd < 0) {
  128                 if (errno == ENOENT && zpc->zpc_ignore_noent)
  129                         return (0);
  130 
  131                 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
  132                     name, strerror(errno));
  133                 return (fd);
  134         }
  135 
  136         ret = ioctl(fd, ZFS_IOC_FSGETXATTR, &fsx);
  137         if (ret) {
  138                 (void) fprintf(stderr,
  139                     gettext("failed to get xattr for %s: %s\n"),
  140                     name, strerror(errno));
  141                 goto out;
  142         }
  143 
  144         switch (zpc->zpc_op) {
  145         case ZFS_PROJECT_OP_LIST:
  146                 (void) printf("%5u %c %s\n", fsx.fsx_projid,
  147                     (fsx.fsx_xflags & ZFS_PROJINHERIT_FL) ? 'P' : '-', name);
  148                 goto out;
  149         case ZFS_PROJECT_OP_CHECK:
  150                 if (fsx.fsx_projid == zpc->zpc_expected_projid &&
  151                     fsx.fsx_xflags & ZFS_PROJINHERIT_FL)
  152                         goto out;
  153 
  154                 if (!zpc->zpc_newline) {
  155                         char c = '\0';
  156 
  157                         (void) printf("%s%c", name, c);
  158                         goto out;
  159                 }
  160 
  161                 if (fsx.fsx_projid != zpc->zpc_expected_projid)
  162                         (void) printf("%s - project ID is not set properly "
  163                             "(%u/%u)\n", name, fsx.fsx_projid,
  164                             (uint32_t)zpc->zpc_expected_projid);
  165 
  166                 if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
  167                         (void) printf("%s - project inherit flag is not set\n",
  168                             name);
  169 
  170                 goto out;
  171         case ZFS_PROJECT_OP_CLEAR:
  172                 if (!(fsx.fsx_xflags & ZFS_PROJINHERIT_FL) &&
  173                     (zpc->zpc_keep_projid ||
  174                     fsx.fsx_projid == ZFS_DEFAULT_PROJID))
  175                         goto out;
  176 
  177                 fsx.fsx_xflags &= ~ZFS_PROJINHERIT_FL;
  178                 if (!zpc->zpc_keep_projid)
  179                         fsx.fsx_projid = ZFS_DEFAULT_PROJID;
  180                 break;
  181         case ZFS_PROJECT_OP_SET:
  182                 if (fsx.fsx_projid == zpc->zpc_expected_projid &&
  183                     (!zpc->zpc_set_flag || fsx.fsx_xflags & ZFS_PROJINHERIT_FL))
  184                         goto out;
  185 
  186                 fsx.fsx_projid = zpc->zpc_expected_projid;
  187                 if (zpc->zpc_set_flag)
  188                         fsx.fsx_xflags |= ZFS_PROJINHERIT_FL;
  189                 break;
  190         default:
  191                 ASSERT(0);
  192                 break;
  193         }
  194 
  195         ret = ioctl(fd, ZFS_IOC_FSSETXATTR, &fsx);
  196         if (ret)
  197                 (void) fprintf(stderr,
  198                     gettext("failed to set xattr for %s: %s\n"),
  199                     name, strerror(errno));
  200 
  201 out:
  202         close(fd);
  203         return (ret);
  204 }
  205 
  206 static int
  207 zfs_project_handle_dir(const char *name, zfs_project_control_t *zpc,
  208     list_t *head)
  209 {
  210         struct dirent *ent;
  211         DIR *dir;
  212         int ret = 0;
  213 
  214         dir = opendir(name);
  215         if (dir == NULL) {
  216                 if (errno == ENOENT && zpc->zpc_ignore_noent)
  217                         return (0);
  218 
  219                 ret = -errno;
  220                 (void) fprintf(stderr, gettext("failed to opendir %s: %s\n"),
  221                     name, strerror(errno));
  222                 return (ret);
  223         }
  224 
  225         /* Non-top item, ignore the case of being removed or renamed by race. */
  226         zpc->zpc_ignore_noent = B_TRUE;
  227         errno = 0;
  228         while (!ret && (ent = readdir(dir)) != NULL) {
  229                 char *fullname;
  230 
  231                 /* skip "." and ".." */
  232                 if (strcmp(ent->d_name, ".") == 0 ||
  233                     strcmp(ent->d_name, "..") == 0)
  234                         continue;
  235 
  236                 if (strlen(ent->d_name) + strlen(name) + 1 >= PATH_MAX) {
  237                         errno = ENAMETOOLONG;
  238                         break;
  239                 }
  240 
  241                 if (asprintf(&fullname, "%s/%s", name, ent->d_name) == -1) {
  242                         errno = ENOMEM;
  243                         break;
  244                 }
  245 
  246                 ret = zfs_project_handle_one(fullname, zpc);
  247                 if (!ret && zpc->zpc_recursive && ent->d_type == DT_DIR)
  248                         zfs_project_item_alloc(head, fullname);
  249 
  250                 free(fullname);
  251         }
  252 
  253         if (errno && !ret) {
  254                 ret = -errno;
  255                 (void) fprintf(stderr, gettext("failed to readdir %s: %s\n"),
  256                     name, strerror(errno));
  257         }
  258 
  259         closedir(dir);
  260         return (ret);
  261 }
  262 
  263 int
  264 zfs_project_handle(const char *name, zfs_project_control_t *zpc)
  265 {
  266         zfs_project_item_t *zpi;
  267         struct stat st;
  268         list_t head;
  269         int ret;
  270 
  271         ret = zfs_project_sanity_check(name, zpc, &st);
  272         if (ret)
  273                 return (ret);
  274 
  275         if ((zpc->zpc_op == ZFS_PROJECT_OP_SET ||
  276             zpc->zpc_op == ZFS_PROJECT_OP_CHECK) &&
  277             zpc->zpc_expected_projid == ZFS_INVALID_PROJID) {
  278                 ret = zfs_project_load_projid(name, zpc);
  279                 if (ret)
  280                         return (ret);
  281         }
  282 
  283         zpc->zpc_ignore_noent = B_FALSE;
  284         ret = zfs_project_handle_one(name, zpc);
  285         if (ret || !S_ISDIR(st.st_mode) || zpc->zpc_dironly ||
  286             (!zpc->zpc_recursive &&
  287             zpc->zpc_op != ZFS_PROJECT_OP_LIST &&
  288             zpc->zpc_op != ZFS_PROJECT_OP_CHECK))
  289                 return (ret);
  290 
  291         list_create(&head, sizeof (zfs_project_item_t),
  292             offsetof(zfs_project_item_t, zpi_list));
  293         zfs_project_item_alloc(&head, name);
  294         while ((zpi = list_remove_head(&head)) != NULL) {
  295                 if (!ret)
  296                         ret = zfs_project_handle_dir(zpi->zpi_name, zpc, &head);
  297                 free(zpi);
  298         }
  299 
  300         return (ret);
  301 }

Cache object: 321b670f1cdf6061eee91e7258e10232


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.