]>
git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - quota/project.c
2 * Copyright (c) 2005 Silicon Graphics, Inc.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #include <xfs/command.h>
20 #include <xfs/input.h>
24 static cmdinfo_t project_cmd
;
33 #define EXCLUDED_FILE_TYPES(x) \
45 " list projects or setup a project tree for tree quota management\n"
48 " 'project -c logfiles'\n"
49 " (match project 'logfiles' to a directory, and setup the directory tree)\n"
51 " Without arguments, report all projects found in the /etc/projects file.\n"
52 " The project quota mechanism in XFS can be used to implement a form of\n"
53 " directory tree quota, where a specified directory and all of the files\n"
54 " and subdirectories below it (i.e. a tree) can be restricted to using a\n"
55 " subset of the available space in the filesystem.\n"
57 " A managed tree must be setup initially using the -c option with a project.\n"
58 " The specified project name or identifier is matched to one or more trees\n"
59 " defined in /etc/projects, and these trees are then recursively descended\n"
60 " to mark the affected inodes as being part of that tree - which sets inode\n"
61 " flags and the project identifier on every file.\n"
62 " Once this has been done, new files created in the tree will automatically\n"
63 " be accounted to the tree based on their project identifier. An attempt to\n"
64 " create a hard link to a file in the tree will only succeed if the project\n"
65 " identifier matches the project identifer for the tree. The xfs_io utility\n"
66 " can be used to set the project ID for an arbitrary file, but this can only\n"
67 " be done by a privileged user.\n"
69 " A previously setup tree can be cleared from project quota control through\n"
70 " use of the -C option, which will recursively descend the tree, clearing\n"
71 " the affected inodes from project quota control.\n"
73 " The -c option can be used to check whether a tree is setup, it reports\n"
74 " nothing if the tree is correct, otherwise it reports the paths of inodes\n"
75 " which do not have the project ID of the rest of the tree, or if the inode\n"
78 " The /etc/projid and /etc/projects file formats are simple, and described\n"
79 " on the xfs_quota man page.\n"
86 const struct stat
*stat
,
95 fprintf(stderr
, _("%s: cannot stat file %s\n"), progname
, path
);
98 if (EXCLUDED_FILE_TYPES(stat
->st_mode
)) {
99 fprintf(stderr
, _("%s: skipping special file %s\n"), progname
, path
);
103 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1) {
105 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
106 progname
, path
, strerror(errno
));
107 } else if ((xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
)) < 0) {
109 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
110 progname
, path
, strerror(errno
));
112 if (fsx
.fsx_projid
!= prid
)
113 printf(_("%s - project identifier is not set"
114 " (inode=%u, tree=%u)\n"),
115 path
, fsx
.fsx_projid
, (unsigned int)prid
);
116 if (!(fsx
.fsx_xflags
& XFS_XFLAG_PROJINHERIT
))
117 printf(_("%s - project inheritance flag is not set\n"),
128 const struct stat
*stat
,
135 if (flag
== FTW_NS
){
137 fprintf(stderr
, _("%s: cannot stat file %s\n"), progname
, path
);
140 if (EXCLUDED_FILE_TYPES(stat
->st_mode
)) {
141 fprintf(stderr
, _("%s: skipping special file %s\n"), progname
, path
);
145 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1) {
147 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
148 progname
, path
, strerror(errno
));
150 } else if (xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
) < 0) {
152 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
153 progname
, path
, strerror(errno
));
159 fsx
.fsx_xflags
&= ~XFS_XFLAG_PROJINHERIT
;
160 if (xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &fsx
) < 0) {
162 fprintf(stderr
, _("%s: cannot clear project on %s: %s\n"),
163 progname
, path
, strerror(errno
));
172 const struct stat
*stat
,
179 if (flag
== FTW_NS
){
181 fprintf(stderr
, _("%s: cannot stat file %s\n"), progname
, path
);
184 if (EXCLUDED_FILE_TYPES(stat
->st_mode
)) {
185 fprintf(stderr
, _("%s: skipping special file %s\n"), progname
, path
);
189 if ((fd
= open(path
, O_RDONLY
|O_NOCTTY
)) == -1) {
191 fprintf(stderr
, _("%s: cannot open %s: %s\n"),
192 progname
, path
, strerror(errno
));
194 } else if (xfsctl(path
, fd
, XFS_IOC_FSGETXATTR
, &fsx
) < 0) {
196 fprintf(stderr
, _("%s: cannot get flags on %s: %s\n"),
197 progname
, path
, strerror(errno
));
202 fsx
.fsx_projid
= prid
;
203 fsx
.fsx_xflags
|= XFS_XFLAG_PROJINHERIT
;
204 if (xfsctl(path
, fd
, XFS_IOC_FSSETXATTR
, &fsx
) < 0) {
206 fprintf(stderr
, _("%s: cannot set project on %s: %s\n"),
207 progname
, path
, strerror(errno
));
221 printf(_("Checking project %s (path %s)...\n"), project
, dir
);
222 nftw(dir
, check_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
225 printf(_("Setting up project %s (path %s)...\n"), project
, dir
);
226 nftw(dir
, setup_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
229 printf(_("Clearing project %s (path %s)...\n"), project
, dir
);
230 nftw(dir
, clear_project
, 100, FTW_PHYS
|FTW_MOUNT
|FTW_DEPTH
);
244 fs_cursor_initialise(NULL
, FS_PROJECT_PATH
, &cursor
);
245 while ((path
= fs_cursor_next_entry(&cursor
))) {
246 if (prid
!= path
->fs_prid
)
248 project_operations(project
, path
->fs_dir
, type
);
252 printf(_("Processed %d %s paths for project %s\n"),
253 count
, projects_file
, project
);
263 while ((c
= getopt(argc
, argv
, "csC")) != EOF
) {
266 type
= CHECK_PROJECT
;
269 type
= SETUP_PROJECT
;
272 type
= CLEAR_PROJECT
;
275 return command_usage(&project_cmd
);
280 return command_usage(&project_cmd
);
282 /* no options - just check the given projects */
284 type
= CHECK_PROJECT
;
287 if (access(projects_file
, F_OK
) != 0) {
289 fprintf(stderr
, _("projects file \"%s\" doesn't exist\n"),
294 while (argc
> optind
) {
295 prid
= prid_from_string(argv
[optind
]);
298 fprintf(stderr
, _("%s - no such project in %s\n"),
299 argv
[optind
], projects_file
);
301 project(argv
[optind
], type
);
311 project_cmd
.name
= _("project");
312 project_cmd
.altname
= _("tree");
313 project_cmd
.cfunc
= project_f
;
314 project_cmd
.args
= _("[-c|-s|-C] project ...");
315 project_cmd
.argmin
= 1;
316 project_cmd
.argmax
= -1;
317 project_cmd
.oneline
= _("check, setup or clear project quota trees");
318 project_cmd
.help
= project_help
;
321 add_command(&project_cmd
);