]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
Move common utility code into a libxcmd.a to ease sharing amongst multiple tools.
authorNathan Scott <nathans@sgi.com>
Tue, 19 Apr 2005 14:59:46 +0000 (14:59 +0000)
committerNathan Scott <nathans@sgi.com>
Tue, 19 Apr 2005 14:59:46 +0000 (14:59 +0000)
Merge of master-melb:xfs-cmds:22271a by kenmcd.

26 files changed:
Makefile
doc/Makefile
doc/README.LVM [deleted file]
doc/README.quota [deleted file]
growfs/Makefile
growfs/explore.c [deleted file]
growfs/xfs_growfs.c
include/Makefile
include/builddefs.in
include/command.h [moved from io/command.h with 79% similarity]
include/input.h [moved from io/input.h with 72% similarity]
include/path.h [new file with mode: 0644]
include/project.h [moved from growfs/explore.h with 56% similarity]
io/Makefile
io/attr.c
io/init.c
io/init.h
io/io.h
io/open.c
libxcmd/Makefile [new file with mode: 0644]
libxcmd/command.c [moved from io/command.c with 63% similarity]
libxcmd/help.c [moved from io/help.c with 93% similarity]
libxcmd/input.c [moved from io/input.c with 72% similarity]
libxcmd/paths.c [new file with mode: 0644]
libxcmd/projects.c [new file with mode: 0644]
libxcmd/quit.c [moved from io/quit.c with 90% similarity]

index 9cd405ec3ee19255d689471bcbdd3dcb57eedd2a..01e2a3c3a41727510a2e64135e0b0e6a0888eace 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ LSRCFILES = configure configure.in Makepkgs aclocal.m4 install-sh README VERSION
 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
 
index 3e21eb17e88c2a673b305419342e88f37b7cff5e..8d44b88fe7067780cbdf25561d8df6a276cd542d 100644 (file)
@@ -1,5 +1,5 @@
 #
-# 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
@@ -33,8 +33,7 @@
 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
@@ -46,7 +45,7 @@ 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
diff --git a/doc/README.LVM b/doc/README.LVM
deleted file mode 100644 (file)
index 06eb6de..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-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.
-
diff --git a/doc/README.quota b/doc/README.quota
deleted file mode 100644 (file)
index 4cabd29..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-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
-
index a6c87e1af68b4132572069a2b387f1aa8e188d7e..b59a3dfe99bfd6b256018ae28c7926a62139173c 100644 (file)
@@ -1,5 +1,5 @@
 #
-# 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
@@ -36,15 +36,9 @@ include $(TOPDIR)/include/builddefs
 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
 
diff --git a/growfs/explore.c b/growfs/explore.c
deleted file mode 100644 (file)
index 8c720b6..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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);
-}
index ed96e855568fc6bc6cd980a0bb7d476dac4d22fd..843fd5e806dfd8f657451f77d2f4141389d6a0ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -31,7 +31,7 @@
  */
 
 #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)
 {
@@ -125,13 +120,17 @@ main(int argc, char **argv)
        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]);
@@ -139,7 +138,6 @@ main(int argc, char **argv)
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
 
-       mtab = NULL;
        maxpct = esize = 0;
        dsize = lsize = rsize = 0LL;
        aflag = dflag = iflag = lflag = mflag = nflag = rflag = xflag = 0;
@@ -182,7 +180,7 @@ main(int argc, char **argv)
                        rflag = 1;
                        break;
                case 't':
-                       mtab = optarg;
+                       mtab_file = optarg;
                        break;
                case 'x':
                        lflag = xflag = 1;
@@ -202,7 +200,18 @@ main(int argc, char **argv)
        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) {
index be824d15fc3a41d0b167669251912c46c3e02ec2..bc3e3e9b22893b7852a69424cb78e5387cc28b21 100644 (file)
@@ -49,6 +49,7 @@ PHFILES = darwin.h freebsd.h irix.h linux.h
 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 :
index 7db6438e6ea1c1717a6069733b1ca57b27f6801e..ac5780a01d374fd109f20cfd9fe0fb9a911cae14 100644 (file)
@@ -45,6 +45,7 @@ LIBTERMCAP = @libtermcap@
 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
similarity index 79%
rename from io/command.h
rename to include/command.h
index fb3377a792e1b04c7f85f6c4f7db8ebc12777863..82cb682b24a9218df9b0ed8185bb8c049b099ef2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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;
@@ -55,8 +51,21 @@ typedef struct cmdinfo {
 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__ */
similarity index 72%
rename from io/input.h
rename to include/input.h
index 36a19ee47fc8142abc3d46070951cd560e7c63eb..d7f8362953370a04d8bae71e0fd83b7d883e199d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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);
 
@@ -47,3 +57,22 @@ enum {
 
 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__ */
diff --git a/include/path.h b/include/path.h
new file mode 100644 (file)
index 0000000..e2f8e41
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * 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__ */
similarity index 56%
rename from growfs/explore.h
rename to include/project.h
index 8f2b480badf68799f98ca959c02e0994f25b0e72..b605211bf198af49cbd71b00ef3cea5a2b4984b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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__ */
index f132273bdd55c1e2f31424a4a7dc50f4f5433c1f..0bc9c5be8b8e2439dc48adc0b665dccd5d164913 100644 (file)
@@ -35,11 +35,15 @@ include $(TOPDIR)/include/builddefs
 
 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
index 0e82b39cd4e7ac7b920d34678de4c89f9271fefa..fae6d73d83ebe450274735547bf198272a83433e 100644 (file)
--- a/io/attr.c
+++ b/io/attr.c
@@ -1,5 +1,5 @@
 /*
- * 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"
 
index dc6018d7819fab1bdf5a503374f07042b3a79fd5..c1f81ff9ec7d8fcbf28918172a4c637cbe75e9a3 100644 (file)
--- a/io/init.c
+++ b/io/init.c
@@ -33,6 +33,7 @@
 #include <xfs/libxfs.h>
 #include "command.h"
 #include "input.h"
+#include "init.h"
 #include "io.h"
 
 char   *progname;
@@ -41,9 +42,6 @@ int   expert;
 size_t pagesize;
 struct timeval stopwatch;
 
-static int     ncmdline;
-static char    **cmdline;
-
 void
 usage(void)
 {
@@ -54,6 +52,20 @@ 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();
@@ -78,6 +90,38 @@ init_commands(void)
        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,
@@ -102,13 +146,7 @@ init(
                        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;
@@ -163,6 +201,8 @@ init(
        }
 
        init_commands();
+       add_args_command(init_args_command);
+       add_check_command(init_check_command);
 }
 
 int
@@ -170,32 +210,7 @@ main(
        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;
 }
index 913718514af973a86366c64af4249ee91b5afa61..57b17a7650a2174ef7b54f4eab33d30fa5b40a8f 100644 (file)
--- a/io/init.h
+++ b/io/init.h
  * 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);
diff --git a/io/io.h b/io/io.h
index d68f013a8fab5ad4153e327014aba6b739d9e0a2..c5cdd463589a8a1517dd90c842ac264400572cac 100644 (file)
--- a/io/io.h
+++ b/io/io.h
@@ -80,6 +80,9 @@ extern int            openfile(char *, xfs_fsop_geom_t *, int, mode_t);
 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);
index 90495132e8b5a154c07985b1bbbdc99dece8c628..398e291fb4b0941dce8516e90644c870902ab66f 100644 (file)
--- a/io/open.c
+++ b/io/open.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -44,6 +44,7 @@ static cmdinfo_t statfs_cmd;
 static cmdinfo_t chproj_cmd;
 static cmdinfo_t lsproj_cmd;
 static cmdinfo_t extsize_cmd;
+static prid_t prid;
 
 off64_t
 filesize(void)
@@ -354,24 +355,111 @@ close_f(
        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;
 }
 
@@ -380,20 +468,37 @@ chproj_f(
        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;
 }
 
@@ -564,20 +669,23 @@ open_init(void)
 
        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;
diff --git a/libxcmd/Makefile b/libxcmd/Makefile
new file mode 100644 (file)
index 0000000..d989a23
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# 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)
similarity index 63%
rename from io/command.c
rename to libxcmd/command.c
index 041ad76f632afabf9d1f188a55cf5fa28dfffdbb..ce1c10609d22136e4c2cfe49a049e1101cd66f73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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);
@@ -51,14 +55,30 @@ add_command(
 {
        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;
 }
 
@@ -76,21 +96,8 @@ command(
                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,
@@ -123,3 +130,68 @@ find_command(
        }
        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);
+       }
+}
similarity index 93%
rename from io/help.c
rename to libxcmd/help.c
index 68ac15c03a5e185dff86bccaf034d818f406712d..e4dae1ffb7c599a77096a75fae755dc099f40bf2 100644 (file)
--- a/io/help.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -31,8 +31,7 @@
  */
 
 #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);
@@ -103,7 +102,7 @@ help_init(void)
        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");
 
similarity index 72%
rename from io/input.c
rename to libxcmd/input.c
index 11bf850af22da012f2cfa6c7b2a8ab47794f9433..5758d8c2c7897d312f0fb5098b460346cebdb314 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -31,9 +31,7 @@
  */
 
 #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>
@@ -45,7 +43,7 @@
 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);
@@ -123,11 +121,15 @@ breakline(
        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;
        }
@@ -144,20 +146,6 @@ doneline(
        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)
@@ -240,6 +228,54 @@ cvtstr(
        }
 }
 
+#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)
 {
@@ -292,3 +328,76 @@ timestr(
                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
diff --git a/libxcmd/paths.c b/libxcmd/paths.c
new file mode 100644 (file)
index 0000000..8ff96d5
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * 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;
+}
diff --git a/libxcmd/projects.c b/libxcmd/projects.c
new file mode 100644 (file)
index 0000000..18e7231
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * 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
+}
similarity index 90%
rename from io/quit.c
rename to libxcmd/quit.c
index a6d5a9f175d02a3ee3e33708d36ab284f24dcc57..59917174e7f4906ae0a0dcdd37ef7dd1b7fcbca6 100644 (file)
--- a/io/quit.c
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -31,7 +31,7 @@
  */
 
 #include <xfs/libxfs.h>
-#include "command.h"
+#include <xfs/command.h>
 
 static cmdinfo_t quit_cmd;
 
@@ -49,7 +49,9 @@ quit_init(void)
        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);