Merge of master-melb:xfs-cmds:22271a by kenmcd.
LDIRT = config.log .dep config.status config.cache confdefs.h conftest* \
Logs/* built .census install.* install-dev.* *.gz
-SUBDIRS = include libxfs libxlog libhandle libdisk \
+SUBDIRS = include libxfs libxlog libxcmd libhandle libdisk \
copy db fsck growfs io logprint mkfile mkfs repair rtcp \
m4 man doc po debian build
#
-# Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
+# Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as
TOPDIR = ..
include $(TOPDIR)/include/builddefs
-README = README.LVM README.quota
-LSRCFILES = INSTALL PORTING CHANGES COPYING CREDITS $(README)
+LSRCFILES = INSTALL PORTING CHANGES COPYING CREDITS
LDIRT = *.gz
default: CHANGES.gz
install: default
$(INSTALL) -m 755 -d $(PKG_DOC_DIR)
- $(INSTALL) -m 644 PORTING CHANGES.gz CREDITS $(README) $(PKG_DOC_DIR)
+ $(INSTALL) -m 644 PORTING CHANGES.gz CREDITS $(PKG_DOC_DIR)
ifeq ($(PKG_DISTRIBUTION), debian)
$(INSTALL) -S CHANGES.gz $(PKG_DOC_DIR)/changelog.gz
else
+++ /dev/null
-XFS on LVM
-__________
-
-PREFACE
-
-This is a quick reference to setting XFS up on LVM. For more information
-please see the LVM HOWTO at:
-
- http://www.linuxdoc.org/HOWTO/LVM-HOWTO.html
-
-PREREQUISITES
-
-You need a kernel with LVM support either built in or as a module.
-This document assumes lvm as a module.
-
-SETTING UP LVM
-
->>> Load module
-
- [root@crash /sbin]# modprobe lvm-mod
-
->>> Set partition type to 0x8e for partitions you wish to use with LVM
-
- [root@crash /sbin]# fdisk /dev/sda1
- Command (m for help): t
- Partition number (1-4): 1
- Hex code (type L to list codes): 8e
- Changed system type of partition 1 to 8e (Unknown)
-
- Command (m for help): w
- The partition table has been altered!
-
->>> Write PV superblock on physical volumes
-
- [root@crash /root]# pvcreate /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
- pvcreate -- physical volume "/dev/sda1" successfully created
- pvcreate -- physical volume "/dev/sdb1" successfully created
- pvcreate -- physical volume "/dev/sdc1" successfully created
- pvcreate -- physical volume "/dev/sdd1" successfully created
-
->>> Create a volume group consisting of the PVs we just set up
-
-[root@crash /root]# vgcreate vg00 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1
- vgcreate -- INFO: using default physical extent size 4 MB
- vgcreate -- INFO: maximum logical volume size is 255.99 Gigabyte
- vgcreate -- doing automatic backup of volume group "vg00"
- vgcreate -- volume group "vg00" successfully created and activated
-
->>> Create a logical volume - striped across 4 PVs, 64 KB chunk size, 20 GB
-
-[root@crash /root]# lvcreate -i 4 -I 64 -L 20G -n lv00 vg00
- lvcreate -- rounding 20971520 KB to stripe boundary size 20975616 KB / 5121 PE
- lvcreate -- doing automatic backup of "vg00"
- lvcreate -- logical volume "/dev/vg00/lv00" successfully created
-
->>> Build a filesystem on the LV
-
-[root@crash /root]# mkfs -t xfs /dev/vg00/lv00
- meta-data=/dev/vg00/lv00 isize=256 agcount=20, agsize=262144 blks
- data = bsize=4096 blocks=5242879, imaxpct=25
- = sunit=0 swidth=0 blks, unwritten=1
- naming =version 2 bsize=4096
- log =internal log bsize=4096 blocks=1200
- realtime =none extsz=65536 blocks=0, rtextents=0
-
-[root@crash /root]# mount -t xfs /dev/vg00/lv00 /xfs
-
->>> Go nuts
-
-
-After a reboot you will need to reactivate the VGs/LVs:
-
- modprobe lvm-mod
- vgchange -a y
-
-These commands could be added to a startup script.
-
+++ /dev/null
-QUOTA on XFS
-____________
-
-PREFACE
-
-For an additional source of information on Linux quota, you can refer to
-the (currently out-of-date) Linux Quota HOWTO at:
-
- http://www.linuxdoc.org/HOWTO/mini/Quota.html
-
-If you are looking to get started quickly, you can skip down to the
-section GETTING STARTED below. It is recommended that you at least
-read the "Administering the XFS Quota System" section below, however.
-
-
-DESCRIPTION
-
-In most computing environments, disk space is not infinite. The quota
-subsystem provides a mechanism to control usage of disk space. Quotas
-can be set for each individual user on any/all of the local filesystems.
-The quotas subsystem warns users when they exceed their allotted limit,
-but allows some extra space for current work (hard limit/soft limit).
-In addition, XFS filesystems with limit enforcement turned off can be
-used as an effective disk usage accounting system.
-
- Users' Views of Disk Quotas
- To most users, disk quotas are either of no concern or a fact of life
- that cannot be avoided. There are two possible quotas that can be
- imposed - a limit can be set on the amount of space a user can occupy,
- and there may be a limit on the number of files (inodes) he can own.
-
- The quota(1) command provides information on the quotas that have been
- set by the system administrators and current usage.
-
- There are four numbers for each limit: current usage, soft limit
- (quota), hard limit, and time limit. The soft limit is the number of 1K
- blocks (or files) that the user is expected to remain below. The hard
- limit cannot be exceeded. If a user's usage reaches the hard limit,
- further requests for space (or attempts to create a file) fail with an
- EDQUOT/ENOSPC error.
-
- When a user exceeds the soft limit, the timer is enabled. Any time the
- quota drops below the soft limits, the timer is disabled. If the timer
- pops, the particular limit that has been exceeded is treated as if the
- hard limit has been reached, and no more resources are allocated to the
- user. The only way to reset this condition, short of turning off limit
- enforcement or increasing the limit, is to reduce usage below quota.
- Only the superuser can set the time limits and this is done on a per
- filesystem basis.
-
- Surviving When the Quota Limit Is Reached
- In most cases, the only way for a user to recover from over-quota
- conditions is to abort whatever activity is in progress on the filesystem
- that has reached its limit, remove sufficient files to bring the limit
- back below quota, and retry the failed program.
-
- However, if a user is in the editor and a write fails because of an over
- quota situation, that is not a suitable course of action. It is most
- likely that initially attempting to write the file has truncated its
- previous contents, so if the editor is aborted without correctly writing
- the file, not only are the recent changes lost, but possibly much, or
- even all, of the contents that previously existed.
-
- There are several possible safe exits for a user caught in this
- situation. He can use the editor ! shell escape command to examine his
- file space and remove surplus files. Alternatively, using csh(1), he can
- suspend the editor, remove some files, then resume it. A third
- possibility is to write the file to some other filesystem (perhaps to a
- file on /tmp) where the user's quota has not been exceeded. Then after
- rectifying the quota situation, the file can be moved back to the
- filesystem it belongs on.
-
-
-ADMINISTRATION
-
-Quotas is a configurable subsystem that is optionally built into the kernel.
-A decision as to which filesystems need to have quotas enabled needs to be
-made. Usually, only filesystems that house users' home directories or other
-user files need to be subjected to the quota system. It is recommended that
-the filesystem housing /tmp should be free of quotas.
-
-XFS and the Linux VFS quota systems (e.g. as used on ext2 filesystems) share
-many characteristics. We begin with an overview of how the Linux VFS quota
-system is administered.
-
- Administering the Linux VFS Quota System
- On most filesystems, quota file(s) should be created in the root of
- those filesystems that are to have quotas. These files should be of
- size zero and should be readable and writable only by root. After
- deciding on the filesystems that will have quotas, the administrator
- then establishes quotas for individual users.
- The edquota(8) and/or setquota(8) commands are used to actually set
- the limits desired upon each user. Where a number of users are to be
- given the same quotas (a common occurrence) the -p option to edquota
- allows this to be easily accomplished. Unless explicitly given a quota,
- users have no limits set on the amount of disk they can use or the number
- of files they can create.
-
- Once the quotas are set and ready to operate, the system must be informed
- to enforce quotas on the desired filesystems. This is accomplished with
- the quotaon(8) command. For quotas to be accurate, it should be enabled
- on a local filesystem immediately after the filesystem has been mounted.
- quotaon either enables quotas for a particular filesystem or, with the -a
- option, enables quotas for each filesystem indicated in /etc/fstab as
- using quotas. See mount(8) for details. When the quota package is
- installed,
-
- /usr/etc/quotaon -a
-
- can be automatically executed during system boot up time by the startup
- scripts.
-
- When quotas need to be disabled, the quotaoff(8) command is used.
- However, if the filesystem is about to be dismounted, the umount(8)
- command disables quotas immediately before the filesystem is unmounted.
- This is actually an effect of the umount(2) system call, and it
- guarantees that the quota system is not disabled if the umount would fail
- because the filesystem is not idle.
-
- Periodically (certainly after each reboot and when quotas are first
- enabled for a filesystem), the records retained in the quota file should
- be checked for consistency with the actual number of blocks and files
- allocated to the user. The quotacheck(8) command is used to accomplish
- this. It is not necessary to unmount the filesystem or disable the
- quota system to run this command, though on active filesystems inaccurate
- results may occur. This does no real harm in most cases; another run of
- quotacheck when the filesystem is idle corrects any inaccuracy. The
- startup scripts can be configured to run quotacheck automatically.
-
- The superuser can use the quota command to examine the usage and quotas
- of any user, and the repquota(8) command can be used to check the usages
- and limits for all users on a filesystem.
-
- Administering the XFS Quota System
- The XFS quota system is different from that of the Linux VFS in many ways.
-
- o There is no need for quota file(s) in the root of the XFS filesystem.
-
- o XFS distinguishes between quota accounting and limit enforcement.
- Quota accounting must be turned on at the time of mounting the XFS
- filesystem. However, it is possible to turn on/off limit
- enforcement any time quota accounting is turned on. The "quota"
- option in mount(8) turns on both (user) quota accounting and
- enforcement. The "uqnoenforce" option must be used to turn on
- user accounting with limit enforcement disabled. quotaon(8)
- contains some examples of frequently used procedures.
-
- o Turning on quotas on the root filesystem is slightly different
- from the above. In more recent versions of XFS, the quota mount
- flags must be passed in with the "rootflags=" boot parameter.
- In older versions of XFS and (quota-tools) quotaon(8) must be
- used on the root XFS filesystem first; and quotas will be turned
- on the next time the system is rebooted.
-
- o It is useful to use repquota(8) with the -v option to monitor
- the XFS quota state at various stages.
-
- o quotacheck(8) has no effect on XFS filesystems. The first time
- quota accounting is turned on, XFS does an automatic quotacheck
- internally; afterwards, the quota system will always be completely
- consistent until quotas are manually turned off.
-
- o repquota(8) with the -v option can be used to monitor the status of
- the quota system of an XFS filesystem. This can be used to see if
- quotas are turned on, given an XFS filesystem. It can also be used
- to monitor the space occupied by the quota system itself.
-
- o Refer to the xfsdump(8), xfsdq(8), and xfsrq(8) man pages, from the
- xfsdump package, which describes a mechanism built into xfsdump that
- allows quota limit information to be backed up and easily restored.
-
- o edquota(8) and setquota(8) cannot be used to set quota limits before
- turning on quotas on the filesystem concerned.
-
- o XFS filesystems keep quota accounting on the superuser, and quota -v
- will display the superuser's usage information. However, limits are
- never enforced on the superuser.
-
- o XFS filesystems keep quota accounting whether the user has quota
- limits or not.
-
-
-IMPLEMENTATION NOTES
-
- On filesystems using Linux VFS quota, disk quota usage information is
- stored in a file on the filesystem that the quotas are to be applied to.
- Conventionally, this file is called quotas, and resides at the root of
- the filesystem.
-
- The system is informed of the existence of the quota file by the quotactl
- system call. It then reads the quota entries for any open files owned by
- users. Each subsequent open of a file in the filesystem is accompanied
- by a pairing with its quota information.
-
- Each time a block is accessed or released and each time an inode is
- allocated or freed, the quota system gets told about it and, in the case
- of allocations, gets the opportunity to deny the allocation.
-
- Note that the XFS quota system implementation is radically different
- to the Linux VFS described above. XFS considers quota information as
- filesystem metadata and uses journaling to provide a higher level
- guarantee of consistency.
-
-
-GETTING STARTED
-
- To use quota under XFS you will need the following:
- o An XFS aware kernel;
- o XFS quota must be enabled at the time XFS is built
- (CONFIG_XFS_QUOTA, below XFS in the Filesystems menu) -
- in older kernel versions this also required CONFIG_QUOTA
- to be set, but this is no longer true;
- o Userspace quota tools which are aware of XFS quota.
-
- User tools which support XFS can be downloaded from the Linux
- quota project at:
- http://sourceforge.net/projects/linuxquota/
- The quota tools from version 3.01-pre2 onward have full support
- for XFS. They can be downloaded via cvs or as a source tarball.
-
- Building the user tools from source:
- # autoconf
- # ./configure --prefix=/usr --mandir=/usr/share/man
- # make
- # make install
-
-
-EXAMPLES
-
->>> Enabling quota enforcement on an XFS filesystem
-
-[root@troppo]# echo /dev/hdb10 /mnt/xqm xfs rw,usrquota 0 0 >>/etc/fstab
-[root@troppo]# mount /mnt/xqm
-
->>> Set limits for a user (can also use edquota, interactively)
-
-[root@troppo]# setquota nathans 600 800 15 20 /mnt/xqm
-
->>> Report current user quota
-
-[root@troppo]# repquota /mnt/xqm
-*** Report for user quotas on device /dev/hdb10
-Block grace time: 7days; Inode grace time: 7days
- Block limits File limits
-User used soft hard grace used soft hard grace
-----------------------------------------------------------------------
-root -- 1552 0 0 11 0 0
-nathans -- 440 600 800 8 15 20
-pcpqa -- 880 0 0 1 0 0
-
->>> Push user over quota (see "File limits" above for user "nathans")
-
-[nathans@troppo]$ sh
-sh-2.04$ for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13
-> do
-> touch /mnt/xqm/blat/file${i}
-> done
-touch: creating `/mnt/xqm/blat/file12': Disk quota exceeded
-touch: creating `/mnt/xqm/blat/file13': Disk quota exceeded
-sh-2.04$ ^D
-
->>> Report current user quota again
-
-[root@troppo]# repquota /mnt/xqm
-*** Report for user quotas on device /dev/hdb10
-Block grace time: 7days; Inode grace time: 7days
- Block limits File limits
-User used soft hard grace used soft hard grace
-----------------------------------------------------------------------
-root -- 1560 0 0 11 0 0
-nathans -+ 440 600 800 20 15 20 7 days
-pcpqa -- 880 0 0 1 0 0
-
->>> From the users point of view:
-
-[nathans@troppo]$ quota
-Disk quotas for user nathans (uid 16302):
- Filesystem blocks quota limit grace files quota limit grace
- /dev/hdb10 440 600 800 20* 15 20 7 days
-
->>> Run warnquota(8) via cron(8) to periodically inform users of violations.
-
-
-CAVEATS
-
-The XFS allocation mechanism will always reserve the maximum amount of
-space required before proceeding with a space allocation. If insufficient
-space for this reservation is available, due to the users block quota limit
-being reached for example, this may result in the allocation failing even
-though there is sufficient space. Quota enforcement can thus sometimes
-happen in situations where the user is under quota and the end result of
-some operation would still have left the user under quota had the operation
-been allowed to run its course. This is an unavoidable side of affect of
-the way XFS operates, so should be kept in mind when assigning users block
-limits. This additional overhead is typically in the range of tens of
-blocks - xfs_info(8) can be used to report the filesystem block size.
-
-On IRIX, XFS supports project quota. This is not (ever) likely to be
-supported on Linux/XFS, as the concept of a project is specific to IRIX.
-A filesystem that has used user quota on IRIX, however, can be migrated
-to Linux, and vice-versa, as the ondisk format is shared between both
-versions of XFS (and Linux/XFS is "endian clean"). Group quota support
-has been implemented only in more recent versions of IRIX 6.5f, and the
-same level of ondisk compatibility is now available as for user quota.
-
-Have fun,
-
- -- nathans@sgi.com
-
#
-# Copyright (c) 2000-2001 Silicon Graphics, Inc. All Rights Reserved.
+# Copyright (c) 2000-2001,2004-2005 Silicon Graphics, Inc. All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as
LTCOMMAND = xfs_growfs
CFILES = xfs_growfs.c
-ifeq ($(PKG_PLATFORM),linux)
-CFILES += explore.c
-else
-LSRCFILES = explore.c
-endif
-HFILES = explore.h
-LLDLIBS = $(LIBXFS) $(LIBUUID)
-LTDEPENDENCIES = $(LIBXFS)
+LLDLIBS = $(LIBXFS) $(LIBXCMD) $(LIBUUID)
+LTDEPENDENCIES = $(LIBXFS) $(LIBXCMD)
LLDFLAGS = -static
LSRCFILES = xfs_info.sh
+++ /dev/null
-/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-#include <xfs/libxfs.h>
-#include <mntent.h>
-
-extern char *fname; /* mount point name */
-extern char *datadev; /* data device name */
-extern char *logdev; /* log device name */
-extern char *rtdev; /* RT device name */
-
-void
-explore_mtab(char *mtab, char *mntpoint)
-{
- struct mntent *mnt;
- struct stat64 statuser;
- struct stat64 statmtab_dir;
- struct stat64 statmtab_dev;
- FILE *mtp;
- char *rtend;
- char *logend;
- int havedev;
-
- if (!mtab)
- mtab = MOUNTED;
-
- if ((mtp = setmntent(mtab, "r")) == NULL) {
- fprintf(stderr, _("%s: cannot access mount list %s: %s\n"),
- progname, MOUNTED, strerror(errno));
- exit(1);
- }
- if (stat64(mntpoint, &statuser) < 0) {
- fprintf(stderr, _("%s: cannot access mount point %s: %s\n"),
- progname, mntpoint, strerror(errno));
- exit(1);
- }
-
- while ((mnt = getmntent(mtp)) != NULL) {
- if (stat64(mnt->mnt_dir, &statmtab_dir) < 0) {
- fprintf(stderr, _("%s: ignoring entry %s in %s: %s\n"),
- progname, mnt->mnt_dir, mtab, strerror(errno));
- continue;
- }
- havedev = (stat64(mnt->mnt_fsname, &statmtab_dev) != -1);
- if ( !((statuser.st_ino == statmtab_dir.st_ino &&
- statuser.st_dev == statmtab_dir.st_dev) ||
- (statuser.st_ino == statmtab_dev.st_ino &&
- statuser.st_dev == statmtab_dev.st_dev &&
- havedev)) )
- continue;
- else if (strcmp(mnt->mnt_type, "xfs") != 0) {
- fprintf(stderr, _("%s: %s is not an XFS filesystem\n"),
- progname, mntpoint);
- exit(1);
- }
- break; /* we've found it */
- }
-
- if (mnt == NULL) {
- fprintf(stderr,
- _("%s: %s is not a mounted XFS filesystem, according to %s\n"),
- progname, mntpoint, MOUNTED);
- exit(1);
- }
-
- /* find the data, log (logdev=), and realtime (rtdev=) devices */
- rtend = logend = NULL;
- fname = mnt->mnt_dir;
- datadev = mnt->mnt_fsname;
- if ((logdev = hasmntopt(mnt, "logdev="))) {
- logdev += 7;
- logend = strtok(logdev, " ,");
- }
- if ((rtdev = hasmntopt(mnt, "rtdev="))) {
- rtdev += 6;
- rtend = strtok(rtdev, " ,");
- }
-
- /* Do this only after we've finished processing mount options */
- if (logdev && logend != logdev)
- *logend = '\0'; /* terminate end of log device name */
- if (rtdev && rtend != rtdev)
- *rtend = '\0'; /* terminate end of rt device name */
-
- endmntent(mtp);
-}
/*
- * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*/
#include <xfs/libxfs.h>
-#include "explore.h"
+#include <xfs/path.h>
/*
* When growing a filesystem, this is the most significant
#define XFS_MAX_INODE_SIG_BITS 32
-char *fname; /* mount point name */
-char *datadev; /* data device name */
-char *logdev; /* log device name */
-char *rtdev; /* RT device name */
-
static void
usage(void)
{
long long lsize; /* new log size in fs blocks */
int maxpct; /* -m flag value */
int mflag; /* -m flag */
- char *mtab; /* mount table file (/etc/mtab) */
int nflag; /* -n flag */
xfs_fsop_geom_t ngeo; /* new fs geometry */
int rflag; /* -r flag */
long long rsize; /* new rt size in fs blocks */
int unwritten; /* unwritten extent flag */
int xflag; /* -x flag */
+ char *fname; /* mount point name */
+ char *datadev; /* data device name */
+ char *logdev; /* log device name */
+ char *rtdev; /* RT device name */
+ fs_path_t *fs; /* mount point information */
libxfs_init_t xi; /* libxfs structure */
progname = basename(argv[0]);
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
- mtab = NULL;
maxpct = esize = 0;
dsize = lsize = rsize = 0LL;
aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0;
rflag = 1;
break;
case 't':
- mtab = optarg;
+ mtab_file = optarg;
break;
case 'x':
lflag = xflag = 1;
if (dflag + lflag + rflag == 0)
aflag = 1;
- explore_mtab(mtab, argv[optind]);
+ fs_table_initialise();
+ fs = fs_table_lookup(argv[optind], FS_MOUNT_POINT);
+ if (!fs) {
+ fprintf(stderr, _("%s: %s is not a mounted XFS filesystem\n"),
+ progname, argv[optind]);
+ return 1;
+ }
+
+ fname = fs->fs_dir;
+ datadev = fs->fs_name;
+ logdev = fs->fs_log;
+ rtdev = fs->fs_rt;
ffd = open(fname, O_RDONLY);
if (ffd < 0) {
DKHFILES = volume.h fstyp.h dvh.h
LSRCFILES = $(shell echo $(PHFILES) | sed -e "s/$(PKG_PLATFORM).h//g")
LSRCFILES += platform_defs.h.in builddefs.in buildmacros buildrules $(DKHFILES)
+LSRCFILES += path.h project.h command.h input.h
LDIRT = xfs disk
default install :
LIBEDITLINE = @libeditline@
LIBREADLINE = @libreadline@
LIBXFS = $(TOPDIR)/libxfs/libxfs.la
+LIBXCMD = $(TOPDIR)/libxcmd/libxcmd.la
LIBXLOG = $(TOPDIR)/libxlog/libxlog.la
LIBDISK = $(TOPDIR)/libdisk/libdisk.la
LIBHANDLE = $(TOPDIR)/libhandle/libhandle.la
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
-
-#define min(a,b) (((a)<(b))?(a):(b))
+#ifndef __COMMAND_H__
+#define __COMMAND_H__
typedef int (*cfunc_t)(int argc, char **argv);
typedef void (*helpfunc_t)(void);
-#define CMD_NOFILE_OK (1<<0) /* command doesn't need an open file */
-#define CMD_NOMAP_OK (1<<1) /* command doesn't need a mapped region */
-#define CMD_FOREIGN_OK (1<<2) /* command not restricted to XFS files */
-
typedef struct cmdinfo {
const char *name;
const char *altname;
extern cmdinfo_t *cmdtab;
extern int ncmds;
+extern void help_init(void);
+extern void quit_init(void);
+
+typedef int (*argsfunc_t)(int index);
+typedef int (*checkfunc_t)(const cmdinfo_t *ci);
+
extern void add_command(const cmdinfo_t *ci);
+extern void add_user_command(char *optarg);
+extern void add_args_command(argsfunc_t af);
+extern void add_check_command(checkfunc_t cf);
+
+extern const cmdinfo_t *find_command(const char *cmd);
+
+extern void command_loop(void);
extern int command_usage(const cmdinfo_t *ci);
extern int command(int argc, char **argv);
-extern const cmdinfo_t *find_command(const char *cmd);
+#endif /* __COMMAND_H__ */
/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
+#ifndef __INPUT_H__
+#define __INPUT_H__
+
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <xfs/project.h>
extern char **breakline(char *input, int *count);
extern void doneline(char *input, char **vec);
extern char *fetchline(void);
-extern void init_cvtnum(int *blocksize, int *sectorsize);
+
extern long long cvtnum(int blocksize, int sectorsize, char *s);
extern void cvtstr(double value, char *str, size_t sz);
+extern unsigned long cvttime(char *s);
+
+extern struct timeval tadd(struct timeval t1, struct timeval t2);
extern struct timeval tsub(struct timeval t1, struct timeval t2);
extern double tdiv(double value, struct timeval tv);
extern void timestr(struct timeval *tv, char *str, size_t sz, int flags);
+extern uid_t uid_from_string(char *user);
+extern gid_t gid_from_string(char *group);
+extern prid_t prid_from_string(char *project);
+
+#define HAVE_FTW_H 1 /* TODO: configure me */
+
+#ifdef HAVE_FTW_H
+#include <ftw.h>
+#else
+struct FTW;
+struct stat;
+extern int nftw(
+ char *dir,
+ int (*fn)(const char *, const struct stat *, int, struct FTW *),
+ int depth,
+ int flags);
+#endif
+
+#endif /* __INPUT_H__ */
--- /dev/null
+/*
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+#ifndef __PATHS_H__
+#define __PATHS_H__
+
+#include <xfs/libxfs.h>
+
+/*
+ * XFS Filesystem Paths
+ *
+ * Utility routines for iterating and searching through the list
+ * of known mounted filesystems and project paths.
+ */
+
+#define FS_MOUNT_POINT (1<<0)
+#define FS_PROJECT_PATH (1<<1)
+
+typedef struct fs_path {
+ char *fs_name; /* Data device for filesystem */
+ dev_t fs_datadev;
+ char *fs_log; /* External log device, if any */
+ dev_t fs_logdev;
+ char *fs_rt; /* Realtime device, if any */
+ dev_t fs_rtdev;
+ char *fs_dir; /* Directory / mount point */
+ uint fs_flags; /* FS_MOUNT_POINT/FS_MOUNT_TREE */
+ uint fs_prid; /* Project ID for tree root */
+} fs_path_t;
+
+extern int fs_count; /* number of entries in fs table */
+extern fs_path_t *fs_table; /* array of entries in fs table */
+extern fs_path_t *fs_path; /* current entry in the fs table */
+extern char *mtab_file;
+
+extern void fs_table_initialise(void);
+extern void fs_table_destroy(void);
+
+extern void fs_table_insert_mount(char *__mount);
+extern void fs_table_insert_project(char *__project);
+
+extern fs_path_t *fs_table_lookup(const char *__dir, uint __flags);
+
+typedef struct fs_cursor {
+ uint count; /* total count of mount entries */
+ uint index; /* current position in table */
+ uint flags; /* iterator flags: mounts/trees */
+ fs_path_t *table; /* local/global table pointer */
+ fs_path_t local; /* space for single-entry table */
+} fs_cursor_t;
+
+extern void fs_cursor_initialise(char *__dir, uint __flags, fs_cursor_t *__cp);
+extern fs_path_t *fs_cursor_next_entry(fs_cursor_t *__cp);
+
+#endif /* __PATHS_H__ */
/*
- * Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
-#ifndef XFS_GROWFS_EXPLORE_H
-#define XFS_GROWFS_EXPLORE_H
+#ifndef __PROJECT_H__
+#define __PROJECT_H__
-/*
- * This was written as part of the Linux port. On IRIX,
- * the volume managers have knowledge of log and realtime
- * subvolumes, and the equivalent functionality is built
- * into the kernel - XFS/XLV/XVM talk amongst themselves
- * and there are no rtdev/logdev mount parameters at all.
- */
-#ifdef __linux__
-extern void explore_mtab(char *mtab, char *mntpoint);
-#else
-# define explore_mtab(mtab, mpoint) do { } while (0)
-#endif
+#include <xfs/xfs.h>
+
+typedef __uint32_t prid_t;
+extern int setprojid(const char *__name, int __fd, prid_t __id);
+extern int getprojid(const char *__name, int __fd, prid_t *__id);
+
+typedef struct fs_project {
+ prid_t pr_prid; /* project identifier */
+ char *pr_name; /* project name */
+} fs_project_t;
+
+extern void setprent(void);
+extern void endprent(void);
+extern fs_project_t *getprent(void);
+extern fs_project_t *getprnam(char *__name);
+extern fs_project_t *getprprid(prid_t __id);
+
+typedef struct fs_project_path {
+ prid_t pp_prid; /* project identifier */
+ char *pp_pathname; /* pathname to root of project tree */
+} fs_project_path_t;
+
+extern void setprpathent(void);
+extern void endprpathent(void);
+extern fs_project_path_t *getprpathent(void);
+
+extern void setprfiles(void);
+extern char *projid_file;
+extern char *projects_file;
-#endif /* XFS_GROWFS_EXPLORE_H */
+#endif /* __PROJECT_H__ */
LTCOMMAND = xfs_io
LSRCFILES = xfs_bmap.sh xfs_freeze.sh
-HFILES = command.h input.h init.h io.h
-CFILES = command.c input.c init.c help.c quit.c \
+HFILES = init.h io.h
+CFILES = init.c \
attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c \
mmap.c open.c pread.c prealloc.c pwrite.c truncate.c
+LLDLIBS = $(LIBXCMD)
+LTDEPENDENCIES = $(LIBXCMD)
+LLDFLAGS = -static
+
ifeq ($(HAVE_FADVISE),yes)
CFILES += fadvise.c
LCFLAGS += -DHAVE_FADVISE
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
#include "init.h"
#include "io.h"
-#define HAVE_FTW_H 1 /* TODO: configure me */
-
-#ifdef HAVE_FTW_H
-#include <ftw.h>
-#else
-static int
-nftw(
- char *dir,
- int (*fn)(const char *, const struct stat *, int, struct FTW *),
- int depth,
- int flags)
-{
- fprintf(stderr, "%s: not implemented, no recursion available\n",
- __FUNCTION__);
- return 0;
-}
-#endif
-
static cmdinfo_t chattr_cmd;
static cmdinfo_t lsattr_cmd;
static unsigned int orflags;
static unsigned int andflags;
-static unsigned int recurse_all;
-static unsigned int recurse_dir;
+unsigned int recurse_all;
+unsigned int recurse_dir;
#define CHATTR_XFLAG_LIST "riasAdtPn"
#include <xfs/libxfs.h>
#include "command.h"
#include "input.h"
+#include "init.h"
#include "io.h"
char *progname;
size_t pagesize;
struct timeval stopwatch;
-static int ncmdline;
-static char **cmdline;
-
void
usage(void)
{
}
void
+init_cvtnum(
+ int *blocksize,
+ int *sectsize)
+{
+ if (!file || (file->flags & IO_FOREIGN)) {
+ *blocksize = 4096;
+ *sectsize = 512;
+ } else {
+ *blocksize = file->geom.blocksize;
+ *sectsize = file->geom.sectsize;
+ }
+}
+
+static void
init_commands(void)
{
attr_init();
truncate_init();
}
+static int
+init_args_command(
+ int index)
+{
+ if (index >= filecount)
+ return 0;
+ file = &filetable[index++];
+ return index;
+}
+
+static int
+init_check_command(
+ const cmdinfo_t *ct)
+{
+ if (!file && !(ct->flags & CMD_NOFILE_OK)) {
+ fprintf(stderr, _("no files are open, try 'help open'\n"));
+ return 0;
+ }
+ if (!mapping && !(ct->flags & CMD_NOMAP_OK)) {
+ fprintf(stderr, _("no mapped regions, try 'help mmap'\n"));
+ return 0;
+ }
+ if (file && !(ct->flags & CMD_FOREIGN_OK) &&
+ (file->flags & IO_FOREIGN)) {
+ fprintf(stderr,
+ _("foreign file active, %s command is for XFS filesystems only\n"),
+ ct->name);
+ return 0;
+ }
+ return 1;
+}
+
void
init(
int argc,
flags |= IO_APPEND;
break;
case 'c': /* commands */
- ncmdline++;
- cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
- if (!cmdline) {
- perror("realloc");
- exit(1);
- }
- cmdline[ncmdline-1] = optarg;
+ add_user_command(optarg);
break;
case 'd':
flags |= IO_DIRECT;
}
init_commands();
+ add_args_command(init_args_command);
+ add_check_command(init_check_command);
}
int
int argc,
char **argv)
{
- int c, i, j, done = 0;
- char *input;
- char **v;
-
init(argc, argv);
-
- for (i = 0; !done && i < ncmdline; i++) {
- for (j = 0; !done && j < filecount; j++) {
- file = &filetable[j];
- v = breakline(cmdline[i], &c);
- if (c)
- done = command(c, v);
- free(v);
- }
- }
- if (cmdline) {
- free(cmdline);
- return exitcode;
- }
- while (!done) {
- if ((input = fetchline()) == NULL)
- break;
- v = breakline(input, &c);
- if (c)
- done = command(c, v);
- doneline(input, v);
- }
+ command_loop();
return exitcode;
}
* http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
*/
+#define CMD_NOFILE_OK (1<<0) /* command doesn't need an open file */
+#define CMD_NOMAP_OK (1<<1) /* command doesn't need a mapped region */
+#define CMD_FOREIGN_OK (1<<2) /* command not restricted to XFS files */
+
extern char *progname;
extern int exitcode;
extern int expert;
extern size_t pagesize;
extern struct timeval stopwatch;
+
+#define min(a,b) (((a)<(b))?(a):(b))
+
+extern void init_cvtnum(int *blocksize, int *sectsize);
extern int addfile(char *, int , xfs_fsop_geom_t *, int);
extern void printxattr(uint, int, int, const char *, int, int);
+extern unsigned int recurse_all;
+extern unsigned int recurse_dir;
+
extern void *buffer;
extern ssize_t buffersize;
extern int alloc_buffer(ssize_t, int, unsigned int);
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
static cmdinfo_t chproj_cmd;
static cmdinfo_t lsproj_cmd;
static cmdinfo_t extsize_cmd;
+static prid_t prid;
off64_t
filesize(void)
return 0;
}
+static void
+lsproj_help(void)
+{
+ printf(_(
+"\n"
+" displays the project identifier associated with the current path\n"
+"\n"
+" Options:\n"
+" -R -- recursively descend (useful when current path is a directory)\n"
+" -D -- recursively descend, but only list projects on directories\n"
+"\n"));
+}
+
+static int
+lsproj_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
+{
+ prid_t projid;
+ int fd;
+
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
+ return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ if (getprojid(path, fd, &projid) == 0)
+ printf("[%u] %s\n", projid, path);
+ close(fd);
+ }
+ return 0;
+}
+
static int
lsproj_f(
int argc,
char **argv)
{
- __uint32_t id;
+ prid_t projid;
+ int c;
-#if defined(__sgi__)
- struct stat64 st;
- if (fstat64(file->fd, &st) < 0) {
- perror("fstat64");
+ while ((c = getopt(argc, argv, "DR")) != EOF) {
+ switch (c) {
+ case 'D':
+ recurse_all = 0;
+ recurse_dir = 1;
+ break;
+ case 'R':
+ recurse_all = 1;
+ recurse_dir = 0;
+ break;
+ default:
+ return command_usage(&lsproj_cmd);
+ }
+ }
+
+ if (argc != optind)
+ return command_usage(&lsproj_cmd);
+
+ if (recurse_all || recurse_dir)
+ nftw(file->name, lsproj_callback,
+ 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+ else if (getprojid(file->name, file->fd, &projid) < 0)
+ perror("getprojid");
+ else
+ printf(_("projid = %u\n"), projid);
+ return 0;
+}
+
+static void
+chproj_help(void)
+{
+ printf(_(
+"\n"
+" modifies the project identifier associated with the current path\n"
+"\n"
+" -R -- recursively descend (useful when current path is a directory)\n"
+" -D -- recursively descend, only modifying projects on directories\n"
+"\n"));
+}
+
+static int
+chproj_callback(
+ const char *path,
+ const struct stat *stat,
+ int status,
+ struct FTW *data)
+{
+ int fd;
+
+ if (recurse_dir && !S_ISDIR(stat->st_mode))
return 0;
+
+ if ((fd = open(path, O_RDONLY)) == -1) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"),
+ progname, path, strerror(errno));
+ } else {
+ if (setprojid(path, fd, prid) < 0)
+ perror("setprojid");
+ close(fd);
}
- id = st.st_projid;
-#else
- id = 0;
-#endif
- printf("projid = %u\n", (unsigned int)id);
return 0;
}
int argc,
char **argv)
{
- __uint32_t id;
- char *sp;
+ int c;
- id = (__uint32_t) strtoul(argv[1], &sp, 0);
- if (!sp || sp == argv[1]) {
- printf(_("non-numeric project ID -- %s\n"), argv[1]);
+ while ((c = getopt(argc, argv, "DR")) != EOF) {
+ switch (c) {
+ case 'D':
+ recurse_all = 0;
+ recurse_dir = 1;
+ break;
+ case 'R':
+ recurse_all = 1;
+ recurse_dir = 0;
+ break;
+ default:
+ return command_usage(&chproj_cmd);
+ }
+ }
+
+ if (argc != optind + 1)
+ return command_usage(&chproj_cmd);
+
+ prid = prid_from_string(argv[optind]);
+ if (prid == -1) {
+ printf(_("invalid project ID -- %s\n"), argv[optind]);
return 0;
}
-#if defined(__sgi__)
- if (fchproj(file->fd, id) < 0)
- perror("fchproj");
-#else
- printf(_("Not yet implemented\n"));
-#endif
+
+ if (recurse_all || recurse_dir)
+ nftw(file->name, chproj_callback,
+ 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH);
+ else if (setprojid(file->name, file->fd, prid) < 0)
+ perror("setprojid");
return 0;
}
chproj_cmd.name = _("chproj");
chproj_cmd.cfunc = chproj_f;
- chproj_cmd.args = _("projid");
+ chproj_cmd.args = _("[-D | -R] projid");
chproj_cmd.argmin = 1;
- chproj_cmd.argmax = 1;
+ chproj_cmd.argmax = -1;
chproj_cmd.flags = CMD_NOMAP_OK;
chproj_cmd.oneline =
_("change project identifier on the currently open file");
+ chproj_cmd.help = chproj_help;
lsproj_cmd.name = _("lsproj");
lsproj_cmd.cfunc = lsproj_f;
+ lsproj_cmd.args = _("[-D | -R]");
lsproj_cmd.argmin = 0;
- lsproj_cmd.argmax = 0;
+ lsproj_cmd.argmax = -1;
lsproj_cmd.flags = CMD_NOMAP_OK;
lsproj_cmd.oneline =
_("list project identifier set on the currently open file");
+ lsproj_cmd.help = lsproj_help;
extsize_cmd.name = _("extsize");
extsize_cmd.cfunc = extsize_f;
--- /dev/null
+#
+# Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it would be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#
+# Further, this software is distributed without any warranty that it is
+# free of the rightful claim of any third person regarding infringement
+# or the like. Any license provided herein, whether implied or
+# otherwise, applies only to this software file. Patent licenses, if
+# any, provided herein do not apply to combinations of this program with
+# other software, or any other product whatsoever.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston MA 02111-1307, USA.
+#
+# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+# Mountain View, CA 94043, or:
+#
+# http://www.sgi.com
+#
+# For further information regarding this notice, see:
+#
+# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+
+TOPDIR = ..
+include $(TOPDIR)/include/builddefs
+
+LTLIBRARY = libxcmd.la
+LT_CURRENT = 0
+LT_REVISION = 0
+LT_AGE = 0
+
+CFILES = command.c input.c paths.c projects.c help.c quit.c
+
+default: $(LTLIBRARY)
+
+include $(BUILDRULES)
+
+install: default
+
+install-dev: default
+ $(INSTALL_LTLIB_STATIC)
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*/
#include <xfs/libxfs.h>
-#include "command.h"
-#include "init.h"
-#include "io.h"
+#include <xfs/command.h>
+#include <xfs/input.h>
cmdinfo_t *cmdtab;
int ncmds;
+static argsfunc_t args_func;
+static checkfunc_t check_func;
+static int ncmdline;
+static char **cmdline;
+
static int
-cmd_compare(const void *a, const void *b)
+compare(const void *a, const void *b)
{
return strcmp(((const cmdinfo_t *)a)->name,
((const cmdinfo_t *)b)->name);
{
cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
cmdtab[ncmds - 1] = *ci;
- qsort(cmdtab, ncmds, sizeof(*cmdtab), cmd_compare);
+ qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
+}
+
+static int
+check_command(
+ const cmdinfo_t *ci)
+{
+ if (check_func)
+ return check_func(ci);
+ return 1;
+}
+
+void
+add_check_command(
+ checkfunc_t cf)
+{
+ check_func = cf;
}
int
command_usage(
const cmdinfo_t *ci)
{
- printf("%s %s\n", ci->name, ci->oneline);
+ printf("%s %s -- %s\n", ci->name, ci->args, ci->oneline);
return 0;
}
fprintf(stderr, _("command \"%s\" not found\n"), cmd);
return 0;
}
- if (!file && !(ct->flags & CMD_NOFILE_OK)) {
- fprintf(stderr, _("no files are open, try 'help open'\n"));
+ if (!check_command(ct))
return 0;
- }
- if (!mapping && !(ct->flags & CMD_NOMAP_OK)) {
- fprintf(stderr, _("no mapped regions, try 'help mmap'\n"));
- return 0;
- }
- if (file && !(ct->flags & CMD_FOREIGN_OK) &&
- (file->flags & IO_FOREIGN)) {
- fprintf(stderr,
- _("foreign file active, %s command is for XFS filesystems only\n"),
- cmd);
- return 0;
- }
if (argc-1 < ct->argmin || (ct->argmax != -1 && argc-1 > ct->argmax)) {
if (ct->argmax == -1)
fprintf(stderr,
}
return NULL;
}
+
+void
+add_user_command(char *optarg)
+{
+ ncmdline++;
+ cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
+ if (!cmdline) {
+ perror("realloc");
+ exit(1);
+ }
+ cmdline[ncmdline-1] = optarg;
+}
+
+static int
+args_command(
+ int index)
+{
+ if (args_func)
+ return args_func(index);
+ return 0;
+}
+
+void
+add_args_command(
+ argsfunc_t af)
+{
+ args_func = af;
+}
+
+void
+command_loop(void)
+{
+ int c, i, j = 0, done = 0;
+ char *input;
+ char **v;
+
+ for (i = 0; !done && i < ncmdline; i++) {
+ while (!done && (j = args_command(j))) {
+ input = strdup(cmdline[i]);
+ if (!input) {
+ fprintf(stderr,
+ _("cannot strdup command '%s': %s\n"),
+ cmdline[i], strerror(errno));
+ exit(1);
+ }
+ v = breakline(input, &c);
+ if (c)
+ done = command(c, v);
+ free(v);
+ free(input);
+ }
+ }
+ if (cmdline) {
+ free(cmdline);
+ return;
+ }
+ while (!done) {
+ if ((input = fetchline()) == NULL)
+ break;
+ v = breakline(input, &c);
+ if (c)
+ done = command(c, v);
+ doneline(input, v);
+ }
+}
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*/
#include <xfs/libxfs.h>
-#include "command.h"
-#include "io.h"
+#include <xfs/command.h>
static cmdinfo_t help_cmd;
static void help_onecmd(const char *cmd, const cmdinfo_t *ct);
help_cmd.cfunc = help_f;
help_cmd.argmin = 0;
help_cmd.argmax = 1;
- help_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
+ help_cmd.flags = -1;
help_cmd.args = _("[command]");
help_cmd.oneline = _("help for one or all commands");
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*/
#include <xfs/libxfs.h>
-#include "input.h"
-#include "init.h"
-#include "io.h"
+#include <xfs/input.h>
#if defined(ENABLE_READLINE)
# include <readline/history.h>
static char *
get_prompt(void)
{
- static char prompt[FILENAME_MAX + 1];
+ static char prompt[FILENAME_MAX + 2 /*"> "*/ + 1 /*"\0"*/ ];
if (!prompt[0])
snprintf(prompt, sizeof(prompt), "%s> ", progname);
char *p;
char **rval = calloc(sizeof(char *), 1);
- while ((p = strsep(&input, " ")) != NULL) {
+ while (rval && (p = strsep(&input, " ")) != NULL) {
if (!*p)
continue;
c++;
rval = realloc(rval, sizeof(*rval) * (c + 1));
+ if (!rval) {
+ c = 0;
+ break;
+ }
rval[c - 1] = p;
rval[c] = NULL;
}
free(vec);
}
-void
-init_cvtnum(
- int *blocksize,
- int *sectsize)
-{
- if (!file || (file->flags & IO_FOREIGN)) {
- *blocksize = 4096;
- *sectsize = 512;
- } else {
- *blocksize = file->geom.blocksize;
- *sectsize = file->geom.sectsize;
- }
-}
-
#define EXABYTES(x) ((long long)(x) << 60)
#define PETABYTES(x) ((long long)(x) << 50)
#define TERABYTES(x) ((long long)(x) << 40)
}
}
+#define MINUTES_TO_SECONDS(m) ((m) * 60)
+#define HOURS_TO_SECONDS(h) ((h) * MINUTES_TO_SECONDS(60))
+#define DAYS_TO_SECONDS(d) ((d) * HOURS_TO_SECONDS(24))
+#define WEEKS_TO_SECONDS(w) ((w) * DAYS_TO_SECONDS(7))
+
+unsigned long
+cvttime(
+ char *s)
+{
+ unsigned long i;
+ char *sp;
+
+ i = strtoul(s, &sp, 0);
+ if (i == 0 && sp == s)
+ return 0;
+ if (*sp == '\0')
+ return i;
+ if ((*sp == 'm' && sp[1] == '\0') ||
+ (strcmp(sp, "minutes") == 0) ||
+ (strcmp(sp, "minute") == 0))
+ return MINUTES_TO_SECONDS(i);
+ if ((*sp == 'h' && sp[1] == '\0') ||
+ (strcmp(sp, "hours") == 0) ||
+ (strcmp(sp, "hour") == 0))
+ return HOURS_TO_SECONDS(i);
+ if ((*sp == 'd' && sp[1] == '\0') ||
+ (strcmp(sp, "days") == 0) ||
+ (strcmp(sp, "day") == 0))
+ return DAYS_TO_SECONDS(i);
+ if ((*sp == 'w' && sp[1] == '\0') ||
+ (strcmp(sp, "weeks") == 0) ||
+ (strcmp(sp, "week") == 0))
+ return WEEKS_TO_SECONDS(i);
+ return 0;
+}
+
+struct timeval
+tadd(struct timeval t1, struct timeval t2)
+{
+ t1.tv_usec += t2.tv_usec;
+ if (t1.tv_usec > 1000000) {
+ t1.tv_usec -= 1000000;
+ t1.tv_sec++;
+ }
+ t1.tv_sec += t2.tv_sec;
+ return t1;
+}
+
struct timeval
tsub(struct timeval t1, struct timeval t2)
{
snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
}
}
+
+/*
+ * Convert from arbitrary user strings into a numeric ID.
+ * If its all numeric, we convert that inplace, else we do
+ * the name lookup, and return the found identifier.
+ */
+
+prid_t
+prid_from_string(
+ char *project)
+{
+ fs_project_t *prj;
+ prid_t prid;
+ char *sp;
+
+ prid = strtoul(project, &sp, 10);
+ if (sp != project)
+ return prid;
+ prj = getprnam(project);
+ if (prj)
+ return prj->pr_prid;
+ return -1;
+}
+
+uid_t
+uid_from_string(
+ char *user)
+{
+ struct passwd *pwd;
+ uid_t uid;
+ char *sp;
+
+ uid = strtoul(user, &sp, 10);
+ if (sp != user)
+ return uid;
+ pwd = getpwnam(user);
+ if (pwd)
+ return pwd->pw_uid;
+ return -1;
+}
+
+gid_t
+gid_from_string(
+ char *group)
+{
+ struct group *grp;
+ gid_t gid;
+ char *sp;
+
+ gid = strtoul(group, &sp, 10);
+ if (sp != group)
+ return gid;
+ grp = getgrnam(group);
+ if (grp)
+ return grp->gr_gid;
+ return -1;
+}
+
+#define HAVE_FTW_H 1 /* TODO: configure me */
+
+#ifndef HAVE_FTW_H
+int
+nftw(
+ char *dir,
+ int (*fn)(const char *, const struct stat *, int, struct FTW *),
+ int depth,
+ int flags)
+{
+ fprintf(stderr, "%s: not implemented, no recursion available\n",
+ __FUNCTION__);
+ return 0;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <paths.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <xfs/path.h>
+#include <xfs/input.h>
+#include <xfs/project.h>
+
+#define HAVE_MNTENT_H 1 /* TODO - configure me (+HAVE_GETMNTINFO) */
+
+int fs_count;
+struct fs_path *fs_table;
+struct fs_path *fs_path;
+char *mtab_file;
+
+struct fs_path *
+fs_table_lookup(
+ const char *dir,
+ uint flags)
+{
+ struct stat64 sbuf;
+ uint i;
+
+ if (stat64(dir, &sbuf) < 0)
+ return NULL;
+ for (i = 0; i < fs_count; i++) {
+ if ((flags & fs_table[i].fs_flags) == 0)
+ continue;
+ if (sbuf.st_dev == fs_table[i].fs_datadev)
+ return &fs_table[i];
+ }
+ return NULL;
+}
+
+static int
+fs_table_insert(
+ char *dir,
+ uint prid,
+ uint flags,
+ char *fsname,
+ char *fslog,
+ char *fsrt)
+{
+ struct stat64 sbuf;
+ dev_t datadev, logdev, rtdev;
+
+ if (!dir || !fsname)
+ return EINVAL;
+
+ datadev = logdev = rtdev = 0;
+ if (stat64(dir, &sbuf) < 0)
+ return errno;
+ datadev = sbuf.st_dev;
+ if (fslog) {
+ if (stat64(fslog, &sbuf) < 0)
+ return errno;
+ logdev = sbuf.st_dev;
+ }
+ if (fsrt) {
+ if (stat64(fsrt, &sbuf) < 0)
+ return errno;
+ rtdev = sbuf.st_dev;
+ }
+
+ fs_table = realloc(fs_table, sizeof(fs_path_t) * (fs_count + 1));
+ if (!fs_table)
+ goto error;
+
+ fs_path = &fs_table[fs_count];
+ fs_path->fs_dir = dir;
+ fs_path->fs_prid = prid;
+ fs_path->fs_flags = flags;
+ fs_path->fs_name = fsname;
+ fs_path->fs_log = fslog;
+ fs_path->fs_rt = fsrt;
+ fs_path->fs_datadev = datadev;
+ fs_path->fs_logdev = logdev;
+ fs_path->fs_rtdev = rtdev;
+ fs_count++;
+ return 0;
+
+ error:
+ if (dir) free(dir);
+ if (fsrt) free(fsrt);
+ if (fslog) free(fslog);
+ if (fsname) free(fsname);
+ return errno;
+}
+
+void
+fs_table_destroy(void)
+{
+ while (--fs_count >= 0) {
+ free(fs_table[fs_count].fs_name);
+ if (fs_table[fs_count].fs_log)
+ free(fs_table[fs_count].fs_log);
+ if (fs_table[fs_count].fs_rt)
+ free(fs_table[fs_count].fs_rt);
+ free(fs_table[fs_count].fs_dir);
+ }
+ if (fs_table)
+ free(fs_table);
+ fs_table = NULL;
+ fs_count = 0;
+}
+
+
+#if defined(HAVE_MNTENT_H)
+#include <mntent.h>
+
+static void
+fs_extract_mount_options(
+ struct mntent *mnt,
+ char **logp,
+ char **rtp)
+{
+ char *fslog, *fsrt, *fslogend, *fsrtend;
+
+ fslog = fsrt = fslogend = fsrtend = NULL;
+
+ /* Extract log device and realtime device from mount options */
+ if ((fslog = hasmntopt(mnt, "logdev="))) {
+ fslog += 7;
+ fslogend = strtok(fslog, " ,");
+ }
+ if ((fsrt = hasmntopt(mnt, "rtdev="))) {
+ fsrt += 6;
+ fsrtend = strtok(fsrt, " ,");
+ }
+
+ /* Do this only after we've finished processing mount options */
+ if (fslog) {
+ if (fslogend != fslog)
+ *fslogend = '\0'; /* terminate end of logdev name */
+ fslog = strdup(fslog);
+ }
+ if (fsrt) {
+ if (fsrtend != fsrt)
+ *fsrtend = '\0'; /* terminate end of rtdev name */
+ fsrt = strdup(fsrt);
+ }
+
+ *logp = fslog;
+ *rtp = fsrt;
+}
+
+static int
+fs_table_initialise_mounts(
+ char *path)
+{
+ struct mntent *mnt;
+ FILE *mtp;
+ char *dir = NULL, *fsname = NULL, *fslog, *fsrt;
+ int error = 0, found = 0;
+
+ if (!mtab_file)
+ mtab_file = MOUNTED;
+
+ if ((mtp = setmntent(mtab_file, "r")) == NULL)
+ return ENOENT;
+
+ while ((mnt = getmntent(mtp)) != NULL) {
+ if (strcmp(mnt->mnt_type, "xfs") != 0)
+ continue;
+ if (path &&
+ ((strcmp(path, mnt->mnt_dir) != 0) &&
+ (strcmp(path, mnt->mnt_fsname) != 0)))
+ continue;
+ found = 1;
+ dir = strdup(mnt->mnt_dir);
+ fsname = strdup(mnt->mnt_fsname);
+ if (!dir || !fsname) {
+ error = ENOMEM;
+ break;
+ }
+ fs_extract_mount_options(mnt, &fslog, &fsrt);
+ if ((error = fs_table_insert(dir, 0, FS_MOUNT_POINT,
+ fsname, fslog, fsrt)))
+ break;
+ }
+ endmntent(mtp);
+ if (!error && path && !found)
+ error = ENXIO;
+ if (error) {
+ free(dir);
+ free(fsname);
+ }
+ return error;
+}
+
+#elif defined(HAVE_GETMNTINFO)
+#include <sys/mount.h>
+
+static int
+fs_table_initialise_mounts(
+ char *path)
+{
+ struct statfs *stats;
+ char *dir = NULL, *fsname = NULL, *fslog = NULL, *fsrt = NULL;
+ int i, count, found = 0, error = 0;
+
+ if ((count = getmntinfo(&stats, 0)) < 0) {
+ perror("getmntinfo");
+ return 0;
+ }
+
+ for (i = 0; i < count; i++) {
+ if (strcmp(stats[i].f_fstypename, "xfs") != 0)
+ continue;
+ if (path &&
+ ((strcmp(path, stats[i].f_mntonname) != 0) &&
+ (strcmp(path, stats[i].f_mntfromname) != 0)))
+ continue;
+ found = 1;
+ dir = strdup(stats[i].f_mntonname);
+ fsname = strdup(stats[i].f_mntfromname);
+ if (!dir || !fsname) {
+ error = ENOMEM;
+ break;
+ }
+ /* TODO: external log and realtime device? */
+ if ((error = fs_table_insert(dir, 0, FS_MOUNT_POINT,
+ fsname, fslog, fsrt);
+ break;
+ }
+ if (!error && path && !found)
+ error = ENXIO;
+ if (error) {
+ free(dir);
+ free(fsname);
+ }
+ return error;
+}
+
+#else
+# error "How do I extract info about mounted filesystems on this platform?"
+#endif
+
+/*
+ * Given a directory, match it up to a filesystem mount point.
+ */
+static struct fs_path *
+fs_mount_point_from_path(
+ const char *dir)
+{
+ fs_cursor_t cursor;
+ fs_path_t *fs;
+ struct stat64 s;
+
+ if (stat64(dir, &s) < 0) {
+ perror(dir);
+ return NULL;
+ }
+
+ fs_cursor_initialise(NULL, FS_MOUNT_POINT, &cursor);
+ while ((fs = fs_cursor_next_entry(&cursor))) {
+ if (fs->fs_datadev == s.st_dev)
+ break;
+ }
+ return fs;
+}
+
+static int
+fs_table_initialise_projects(
+ char *project)
+{
+ fs_project_path_t *path;
+ fs_path_t *fs;
+ prid_t prid = 0;
+ char *dir = NULL, *fsname = NULL;
+ int error = 0, found = 0;
+
+ if (project)
+ prid = prid_from_string(project);
+
+ setprpathent();
+ while ((path = getprpathent()) != NULL) {
+ if (project && prid != path->pp_prid)
+ continue;
+ if ((fs = fs_mount_point_from_path(path->pp_pathname)) == NULL)
+ continue;
+ found = 1;
+ dir = strdup(path->pp_pathname);
+ fsname = strdup(fs->fs_name);
+ if (!dir || !fsname) {
+ error = ENOMEM;
+ break;
+ }
+ if ((error = fs_table_insert(dir, path->pp_prid,
+ FS_PROJECT_PATH, fsname, NULL, NULL)))
+ break;
+ }
+ endprpathent();
+
+ if (!error && project && !found)
+ error = ENOENT;
+ if (error) {
+ free(dir);
+ free(fsname);
+ }
+ return error;
+}
+
+void
+fs_table_initialise(void)
+{
+ int error;
+
+ error = fs_table_initialise_mounts(NULL);
+ if (!error)
+ error = fs_table_initialise_projects(NULL);
+ if (error) {
+ fs_table_destroy();
+ fprintf(stderr, _("%s: cannot initialise path table: %s\n"),
+ progname, strerror(error));
+ exit(1);
+ }
+}
+
+void
+fs_table_insert_mount(
+ char *mount)
+{
+ int error;
+
+ error = fs_table_initialise_mounts(mount);
+ if (error) {
+ fs_table_destroy();
+ fprintf(stderr, _("%s: cannot setup path for mount %s: %s\n"),
+ progname, mount, strerror(error));
+ exit(1);
+ }
+}
+
+void
+fs_table_insert_project(
+ char *project)
+{
+ int error;
+
+ if (!fs_count) {
+ fprintf(stderr, _("%s: no mount table yet, so no projects\n"),
+ progname);
+ exit(1);
+ }
+ error = fs_table_initialise_projects(project);
+ if (error) {
+ fs_table_destroy();
+ fprintf(stderr, _("%s: cannot setup path for project %s: %s\n"),
+ progname, project, strerror(error));
+ exit(1);
+ }
+}
+
+/*
+ * Table iteration (cursor-based) interfaces
+ */
+
+void
+fs_cursor_initialise(
+ char *dir,
+ uint flags,
+ fs_cursor_t *cur)
+{
+ fs_path_t *path;
+
+ memset(cur, 0, sizeof(*cur));
+ if (dir) {
+ if ((path = fs_table_lookup(dir, flags)) == NULL)
+ return;
+ cur->local = *path;
+ cur->count = 1;
+ cur->table = &cur->local;
+ } else {
+ cur->count = fs_count;
+ cur->table = fs_table;
+ }
+ cur->flags = flags;
+}
+
+struct fs_path *
+fs_cursor_next_entry(
+ fs_cursor_t *cur)
+{
+ fs_path_t *next = NULL;
+
+ while (cur->index < cur->count) {
+ next = &cur->table[cur->index++];
+ if (cur->flags & next->fs_flags)
+ break;
+ next = NULL;
+ }
+ return next;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xfs/project.h>
+
+#define PROJID "/etc/projid"
+#define PROJECT_PATHS "/etc/projects"
+char *projid_file;
+char *projects_file;
+
+static FILE *projects;
+static fs_project_t p;
+static char projects_buffer[512];
+
+static FILE *project_paths;
+static fs_project_path_t pp;
+static char project_paths_buffer[1024];
+
+void
+setprfiles(void)
+{
+ if (!projid_file)
+ projid_file = PROJID;
+ if (!projects_file)
+ projects_file = PROJECT_PATHS;
+}
+
+void
+setprent()
+{
+ setprfiles();
+ projects = fopen(projid_file, "r");
+}
+
+void
+setprpathent()
+{
+ setprfiles();
+ project_paths = fopen(projects_file, "r");
+}
+
+void
+endprent(void)
+{
+ if (projects)
+ fclose(projects);
+ projects = NULL;
+}
+
+void
+endprpathent(void)
+{
+ if (project_paths)
+ fclose(project_paths);
+ project_paths = NULL;
+}
+
+fs_project_t *
+getprent(void)
+{
+ char *idstart, *idend;
+ size_t size = sizeof(projects_buffer) - 1;
+
+ if (!projects)
+ return NULL;
+ do {
+ if (!fgets(projects_buffer, size, projects))
+ break;
+ /*
+ * /etc/projid file format -- "name:id\n", ignore "^#..."
+ */
+ if (projects_buffer[0] == '#')
+ continue;
+ idstart = strchr(projects_buffer, ':');
+ if (!idstart)
+ continue;
+ if ((idstart + 1) - projects_buffer >= size)
+ continue;
+ idend = strchr(idstart+1, ':');
+ if (idend)
+ *idend = '\0';
+ *idstart = '\0';
+ p.pr_prid = atoi(idstart+1);
+ p.pr_name = &projects_buffer[0];
+ return &p;
+ } while (1);
+
+ return NULL;
+}
+
+fs_project_t *
+getprnam(
+ char *name)
+{
+ fs_project_t *p = NULL;
+
+ setprent();
+ while ((p = getprent()) != NULL)
+ if (strcmp(p->pr_name, name) == 0)
+ break;
+ endprent();
+ return p;
+}
+
+fs_project_t *
+getprprid(
+ prid_t prid)
+{
+ fs_project_t *p = NULL;
+
+ setprent();
+ while ((p = getprent()) != NULL)
+ if (p->pr_prid == prid)
+ break;
+ endprent();
+ return p;
+}
+
+fs_project_path_t *
+getprpathent(void)
+{
+ char *nmstart, *nmend;
+ size_t size = sizeof(project_paths_buffer) - 1;
+
+ if (!project_paths)
+ return NULL;
+ do {
+ if (!fgets(project_paths_buffer, size, project_paths))
+ break;
+ /*
+ * /etc/projects format -- "id:pathname\n", ignore "^#..."
+ */
+ if (project_paths_buffer[0] == '#')
+ continue;
+ nmstart = strchr(project_paths_buffer, ':');
+ if (!nmstart)
+ continue;
+ if ((nmstart + 1) - project_paths_buffer >= size)
+ continue;
+ nmend = strchr(nmstart + 1, '\n');
+ if (nmend)
+ *nmend = '\0';
+ *nmstart = '\0';
+ pp.pp_pathname = nmstart + 1;
+ pp.pp_prid = atoi(&project_paths_buffer[0]);
+ return &pp;
+ } while (1);
+
+ return NULL;
+}
+
+
+int
+getprojid(
+ const char *name,
+ int fd,
+ prid_t *projid)
+{
+#if defined(__sgi__)
+ struct stat64 st;
+ if (fstat64(fd, &st) < 0) {
+ perror("fstat64");
+ return -1;
+ }
+ *projid = st.st_projid;
+#else
+ if (xfsctl(name, fd, XFS_IOC_GETPROJID, projid)) {
+ perror("XFS_IOC_GETPROJID");
+ return -1;
+ }
+#endif
+ return 0;
+}
+
+int
+setprojid(
+ const char *name,
+ int fd,
+ prid_t projid)
+{
+#if defined(__sgi__)
+ return fchproj(fd, projid);
+#else
+ return xfsctl(name, fd, XFS_IOC_SETPROJID, &projid);
+#endif
+}
/*
- * Copyright (c) 2003-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2003-2005 Silicon Graphics, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
*/
#include <xfs/libxfs.h>
-#include "command.h"
+#include <xfs/command.h>
static cmdinfo_t quit_cmd;
quit_cmd.name = _("quit");
quit_cmd.altname = _("q");
quit_cmd.cfunc = quit_f;
- quit_cmd.flags = CMD_NOMAP_OK | CMD_NOFILE_OK | CMD_FOREIGN_OK;
+ quit_cmd.argmin = -1;
+ quit_cmd.argmax = -1;
+ quit_cmd.flags = -1;
quit_cmd.oneline = _("exit the program");
add_command(&quit_cmd);