]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/project.c
2 * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 #include <xfs/command.h>
34 #include <xfs/input.h>
38 static cmdinfo_t project_cmd
;
52 " list projects or setup a project tree for tree quota management\n"
55 " 'project -c logfiles'\n"
56 " (match project 'logfiles' to a directory, and setup the directory tree)\n"
58 " Without arguments, report all projects found in the /etc/projects file.\n"
59 " The project quota mechanism in XFS can be used to implement a form of\n"
60 " directory tree quota, where a specified directory and all of the files\n"
61 " and subdirectories below it (i.e. a tree) can be restricted to using a\n"
62 " subset of the available space in the filesystem.\n"
64 " A managed tree must be setup initially using the -c option with a project.\n"
65 " The specified project name or identifier is matched to one or more trees\n"
66 " defined in /etc/projects, and these trees are then recursively descended\n"
67 " to mark the affected inodes as being part of that tree - which sets inode\n"
68 " flags and the project identifier on every file.\n"
69 " Once this has been done, new files created in the tree will automatically\n"
70 " be accounted to the tree based on their project identifier. An attempt to\n"
71 " create a hard link to a file in the tree will only succeed if the project\n"
72 " identifier matches the project identifer for the tree. The xfs_io utility\n"
73 " can be used to set the project ID for an arbitrary file, but this can only\n"
74 " be done by a privileged user.\n"
76 " A previously setup tree can be cleared from project quota control through\n"
77 " use of the -C option, which will recursively descend the tree, clearing\n"
78 " the affected inodes from project quota control.\n"
80 " The -c option can be used to check whether a tree is setup, it reports\n"
81 " nothing if the tree is correct, otherwise it reports the paths of inodes\n"
82 " which do not have the project ID of the rest of the tree, or if the inode\n"
85 " The /etc/projid and /etc/projects file formats are simple, and described\n"
86 " on the xfs_quota man page.\n"
93 const struct stat
*stat
,
100 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1)
101 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
102 progname
, path
, strerror(errno
));
103 else if ((xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
)) < 0)
104 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
105 progname
, path
, strerror(errno
));
107 if (fsx
.fsx_projid
!= prid
)
108 printf(_("%s - project identifier is not set"
109 " (inode=%u, tree=%u)\n"),
110 path
, fsx
.fsx_projid
, prid
);
111 if (!(fsx
.fsx_xflags
& XFS_XFLAG_PROJINHERIT
))
112 printf(_("%s - project inheritance flag is not set\n"),
123 const struct stat
*stat
,
130 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1) {
131 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
132 progname
, path
, strerror(errno
));
134 } else if (xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
) < 0) {
135 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
136 progname
, path
, strerror(errno
));
142 fsx
.fsx_xflags
&= ~XFS_XFLAG_PROJINHERIT
;
143 if (xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &fsx
) < 0)
144 fprintf(stderr
, _("%s: cannot clear project on %s: %s\n"),
145 progname
, path
, strerror(errno
));
153 const struct stat
*stat
,
160 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1) {
161 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
162 progname
, path
, strerror(errno
));
164 } else if (xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
) < 0) {
165 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
166 progname
, path
, strerror(errno
));
171 fsx
.fsx_projid
= prid
;
172 fsx
.fsx_xflags
|= XFS_XFLAG_PROJINHERIT
;
173 if (xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &fsx
) < 0)
174 fprintf(stderr
, _("%s: cannot set project on %s: %s\n"),
175 progname
, path
, strerror(errno
));
188 printf(_("Checking project %s (path %s)...\n"), project
, dir
);
189 nftw(dir
, check_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
192 printf(_("Setting up project %s (path %s)...\n"), project
, dir
);
193 nftw(dir
, setup_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
196 printf(_("Clearing project %s (path %s)...\n"), project
, dir
);
197 nftw(dir
, clear_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
211 fs_cursor_initialise(NULL
, FS_PROJECT_PATH
, &cursor
);
212 while ((path
= fs_cursor_next_entry(&cursor
))) {
213 if (prid
!= path
->fs_prid
)
215 project_operations(project
, path
->fs_dir
, type
);
219 printf(_("Processed %d %s paths for project %s\n"),
220 count
, projects_file
, project
);
230 while ((c
= getopt(argc
, argv
, "csC")) != EOF
) {
233 type
= CHECK_PROJECT
;
236 type
= SETUP_PROJECT
;
239 type
= CLEAR_PROJECT
;
242 return command_usage(&project_cmd
);
247 return command_usage(&project_cmd
);
249 /* no options - just check the given projects */
251 type
= CHECK_PROJECT
;
254 if (access(projects_file
, F_OK
) != 0) {
255 fprintf(stderr
, _("projects file \"%s\" doesn't exist\n"),
260 while (argc
> optind
) {
261 prid
= prid_from_string(argv
[optind
]);
263 fprintf(stderr
, _("%s - no such project in %s\n"),
264 argv
[optind
], projects_file
);
266 project(argv
[optind
], type
);
276 project_cmd
.name
= _("project");
277 project_cmd
.altname
= _("tree");
278 project_cmd
.cfunc
= project_f
;
279 project_cmd
.args
= _("[-c|-s|-C] project ...");
280 project_cmd
.argmin
= 1;
281 project_cmd
.argmax
= -1;
282 project_cmd
.oneline
= _("check, setup or clear project quota trees");
283 project_cmd
.help
= project_help
;
286 add_command(&project_cmd
);