summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjkar8572 <jkar8572>2001-03-23 12:03:26 +0000
committerjkar8572 <jkar8572>2001-03-23 12:03:26 +0000
commit869fe242340fefe0540fdcf51698ba4c3c8c07bb (patch)
tree950fa3f5997c1e8ee68c0f17d4eaf17abef64f34
downloadlinuxquota-869fe242340fefe0540fdcf51698ba4c3c8c07bb.tar.gz
Initial revision
-rw-r--r--Changelog497
-rw-r--r--Makefile.in140
-rw-r--r--README.gettext21
-rw-r--r--bylabel.c256
-rw-r--r--bylabel.h4
-rw-r--r--common.c74
-rw-r--r--common.h30
-rwxr-xr-xconfigure1721
-rw-r--r--configure.in73
-rw-r--r--convertquota.851
-rw-r--r--convertquota.c136
-rw-r--r--doc/edquota(8).html96
-rw-r--r--doc/fstab(5).html127
-rw-r--r--doc/quota(1).html92
-rw-r--r--doc/quota.html288
-rw-r--r--doc/quota4th.fig62
-rw-r--r--doc/quotacheck(8).html94
-rw-r--r--doc/quotactl(2).html197
-rw-r--r--doc/quotaon(8).html80
-rw-r--r--doc/quotas-1.eps3716
-rw-r--r--doc/quotas.ms318
-rw-r--r--doc/quotas.preformated330
-rw-r--r--doc/repquota(8).html68
-rw-r--r--doc/rquotad(8).html38
-rw-r--r--dqblk_rpc.h20
-rw-r--r--dqblk_v1.h18
-rw-r--r--dqblk_v2.h36
-rw-r--r--dqblk_xfs.h25
-rw-r--r--edquota.895
-rw-r--r--edquota.c200
-rwxr-xr-xinstall-sh251
-rw-r--r--mntopt.h22
-rw-r--r--po/pl.po857
-rw-r--r--pot.c15
-rw-r--r--pot.h24
-rw-r--r--quot.845
-rw-r--r--quot.c352
-rw-r--r--quot.h113
-rw-r--r--quota.1100
-rw-r--r--quota.c226
-rw-r--r--quota.h83
-rw-r--r--quotacheck.894
-rw-r--r--quotacheck.c849
-rw-r--r--quotacheck.h44
-rw-r--r--quotacheck_v1.c83
-rw-r--r--quotacheck_v2.c344
-rw-r--r--quotactl.2231
-rw-r--r--quotaio.c238
-rw-r--r--quotaio.h141
-rw-r--r--quotaio_rpc.c55
-rw-r--r--quotaio_v1.c302
-rw-r--r--quotaio_v1.h39
-rw-r--r--quotaio_v2.c734
-rw-r--r--quotaio_v2.h88
-rw-r--r--quotaio_xfs.c277
-rw-r--r--quotaio_xfs.h159
-rw-r--r--quotaon.8168
-rw-r--r--quotaon.c277
-rw-r--r--quotaon.h22
-rw-r--r--quotaon_xfs.c206
-rw-r--r--quotaops.c476
-rw-r--r--quotaops.h16
-rw-r--r--quotastats.c59
-rw-r--r--quotasys.c442
-rw-r--r--quotasys.h75
-rw-r--r--repquota.871
-rw-r--r--repquota.c160
-rw-r--r--rquota.334
-rw-r--r--rquota.x139
-rw-r--r--rquota_client.c309
-rw-r--r--rquota_client.h18
-rw-r--r--rquota_server.c342
-rw-r--r--rquota_svc.c233
-rw-r--r--rquotad.845
-rw-r--r--set_limits_example.c60
-rw-r--r--setquota.888
-rw-r--r--setquota.c232
-rwxr-xr-xsetup_quota_group12
-rw-r--r--warnquota.837
-rw-r--r--warnquota.c374
-rw-r--r--warnquota.conf16
-rw-r--r--xqmstats.c53
82 files changed, 18633 insertions, 0 deletions
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..2f009ca
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,497 @@
+Changes in quota-package from 2.00 to 3.01
+
+* This is a complete rewrite of the quota package, most importantly adding
+ support for the new Linux quota format and also support for XFS quota.
+
+* The internal data structures and algorithms were redesigned and rewritten by
+ Jan Kara (jack@ucw.cz) so that different versions and different types of
+ quota can be used with these tools.
+
+* Support for XFS quota has been added by Nathan Scott (nathans@sgi.com).
+
+* Add options like RPC, ALT_FORMAT, RPC_SETQUOTA, EXT2_DIRECT to configure.
+ (Jan Kara)
+
+* Fix atoi() -> strtol() and detect mistakes in numeric input. (Jan Kara)
+
+* Add '-V' option to all tools to display the version. (Jan Kara)
+
+* Reworked time conversion routines. (Jan Kara)
+
+* setquota - added -t parameter and allow variable number of filesystems to
+ be specified. (Jan Kara)
+
+* Fixed endian bug in the ext2 mount by LABEL or by UUID handling code, and
+ added XFS support to this code also. (Nathan Scott)
+
+* Fix bug in handling of multiple mount points sharing the same device.
+ (Jan Kara)
+
+* Fix warnquota output for devices with long names. (Jan Kara)
+
+* Updated man pages. (Jan Kara, Nathan Scott)
+
+* Added a port of the BSD quot(8) utility, with XFS support. (Nathan Scott)
+
+* Added xqmstats(8) utility for reporting activity statistics for the XFS
+ Quota Manager - XQM. (Nathan Scott)
+
+* Fix up numerous compiler warnings and all the minor problems that revealed -
+ package now compiled with -Wall by default. (Jan Kara, Nathan Scott)
+
+Changes in quota-package from 1.70 to 2.00
+
+* Added patches from Steven Walker <smw8923@cmsu2.cmsu.edu> for supporting
+ rpc_setquota call and tcp-wrappers check in rquotad.
+
+* Splited quota manipulation from setquota, edquota, quota etc. to quotaops.c
+ so things are coded only once. Also added support for remote quota editing
+ and setting using rquota extensions.
+
+* Fixed problems with parsing of /etc/fstab in hasquota.c (incorrectly
+ assumed that it was the only option followed by an '='). Patch by
+ Simon Huggins <huggie@earth.li>.
+
+* Extracted quota-io into quotaio.c so we only need to update repquota.c and
+ quotaio.c when we change the way quotas are stored in the quotafile for bigger
+ uids and gids.
+
+* Added prototype user copying to setquota ala edquota -p only this
+ time only for a specific filesystem.
+
+* Fixed quota tools for quotas bigger then 4 Gb.
+ Patch by Stephen C. Tweedie <sct@redhat.com>
+
+* Changed rpc.rquotad to scan all device entries in /dev to support also devfs
+ systems and systems with special hardware RAID controllers.
+
+* Added autoconf support to the quota-utils.
+ Patches by Andreas Gruenbacher <a.gruenbacher@bestbits.at>
+
+* Added extra filesystem types to mntent to reflect the current linux filesystems
+
+* Rewrote hasquota.c to check for the MNTOPT_QUOTA option.
+ (Request from Phil Stracchino <alaric@babcom.com>)
+
+* Removed searching of /dev dir from rquota_server. Only lookup mounted filesystems.
+ (Patch by Roman Kagan <Roman.Kagan@itep.ru>)
+
+* Added gettext NLS support all credits go to the guys named in the
+ README.gettext.
+
+* Added the redhat patches to the standard tree.
+ * blocksize patch
+ * fhs patch
+ * hjl patch
+ * label patch
+ * SPARC patch
+
+* Changed Q_SETQUOTA to Q_SETQLIM in quotaops.c for the putprivs function. This fixed
+ a problem where we restore bogos usage info by edquota etc. when a user resets its
+ quota usage while running for example edquota. We should only change the limits
+ because thats the only things we can change using these kind of tools.
+ (Bug report by Dr. Michael Meskes <michael@fam-meskes.de> from the Debian bug-archive)
+
+* Added numeric option to quota and setquota to allow to set quota for users/groups not
+ in the localy known through name-services.
+ (Modified the patches send by Oscar Martín <oscar@cdrtcampos.es>)
+
+Changes in quota-package from 1.65 to 1.70
+
+* Fixed problems when turning off one type of quota taking offline the
+ other type too.
+
+* Fixed bugs as reported on bugtraq for negative ids and problems
+ with usernames with only digits.
+
+* Added setquota (to se quotas from the commandline) as send to me by
+ Martin Bene <mb@sime.com>
+
+Changes in quota-package from 1.60 to 1.65
+
+* Created new diffs again for the newer kernel (2.1.[78]x).
+
+* Added sample program that copies quota-settings from one user
+ to an other.
+
+* Added /etc/quotatab support as developed by Jon Lewis
+ <jlewis@inorganic5.fdt.net>
+
+* Added some changes to /usr/src/linux/fs/nfsd/vfs.c to support quotas
+ for the kernel-nfsd too. (Most other filesystems are gone and the ones
+ remaining either don't need quotas or are not used by big groups of users.)
+
+Changes in quota-package from 1.55 to 1.60
+
+* Added new option to kernel root_squash which means when that option is
+ set the kernel system threats root as any normal user and he cannot
+ write to any file anymore without obeing the quota limits.
+
+* Added support for root_squash to quotaon and quotaoff using the new
+ rsquash option in mntent. In the run also rewrote the hasquota function.
+
+* Added patches to Makefile.std which should make it more FSSTND compliant.
+
+* Added extra check to rpc.rquotad to check the special device type when
+ scanning the /dev dir for the right device.
+
+Changes in quota-package from 1.52 to 1.55
+
+* Added all patches and enhancements I collected the last few months.
+ (As always some have undergone some rewriting and are only a special
+ option. But they are in)
+
+* Changed check on ruid in edquota to an access-check on the quota-files.
+ If you have write permissions on the quota-files as a group its probably
+ ok to allow you to change the quotas. If not the system operator should
+ take apropriate actions. Install edquota SUID-root if you want people
+ who are able to write to your quotafiles to change quotas. If you don't
+ install it SUID root it will only update the files which can give strange
+ problems with the kernel overwriting your updates.
+
+* Added the EPS-file of the sheets from Remy Card which he used at the
+ Berlin Linux seminar. And because they describe everything in detail
+ its a nice enhancement to the current HTML docs.
+
+Changes in quota-package from 1.50 to 1.52
+
+* Hopefully fixed some problems with makefiles and the like.
+
+* Did some rewrite on the mountlist handling, removed limit on number of
+ superblocks by allocating them within the mountlist.
+ (This code is not available within the standard kernel. Until I find the
+ time and feel like it I will put all my new enhancements in my very own
+ (just a bit different) kernel sourcetree back into the mainstream kernels.)
+
+Changes in quota-package from 1.34 to 1.50
+
+* Wrote some new docs, right into html use Mosaic, Netscape or lynx or
+ whatever HTML-browser to see whats in. Also did the manual-pages,
+ its just a quick hack hope this helps people using quota.
+
+* Added DIRECT EXT2 access to quotacheck which should make scanning ext2
+ disks quite some faster. On the other hand you now need the ext2fs
+ libs to compile the quotacheck program. (Enhancement by Edvard Tuinder)
+
+* Added dquot_operations to include/linux/fs.h
+
+* Changed include/linux/quota.h according to new standard.
+
+* Changed fs/dquot.c according to new standard.
+
+* Added support to quotaon-systemcall for initializing the superblock
+ with a pointer to the dquot operations.
+
+* Remove fs/fileio.c and include/linux/fileio.h including all references to it.
+
+* Added support to the different filesystems to call the new dquot_alloc and
+ dquot_free functions on block/inode allocation or freeing. (currently ext2)
+
+* People can add support to any filesystem if they want, for now I have been
+ lazy and only implemented it for ext2-fs. Which by the way is probably
+ the most difficult of all the filesystems. If one feels up to it you can
+ try adding it to your favorit filesystem. I will accept patches, and
+ include them with or without changes.
+
+* Added some patches for dynamic allocation of quotafilenames in hasquota.
+ (patches by Remy Card)
+
+* Rewrote quota_transfer again, as a never ending story...
+
+* A new run off cleanups have been taking place, removed the QF_OPENING and
+ QF_CLOSING flags because we don't need them anymore. The new code uses dquot
+ pointers. If we initialize the dquot pointer after we have setup everything
+ we don't have do be afraid that we get dqget calls while we don't want them.
+
+* Fixed some bugs with not dropping dquot pointers which lead to memory leaks
+ in the long run because dquots kept being hold because the kernel thought
+ it was still being used.
+
+* Added some stats to the code which can be viewed with quotastats. Not real
+ interesting at the user level but quite handy debugging the quota system.
+
+Changes in quota-package from 1.33 to 1.34
+
+* Changed hasquota.c to not insert a slash when the mnt->mnt_dir already ends
+ with a slash. So something like //quota.user shouldn't happen anymore.
+
+* Cleaned up fs/fileio.c, removed some unneeded dummy_inodes in unlink and
+ rmdir vfs functions. Now rely on incrementing i_count when deleting a
+ dir or file and release it when I iput the inode. Should work because when
+ a executable is running when it gets deleted this also happens. Also
+ renamed and cleanup the rest of the funtions. vfs_rename function should
+ now also work for a hardlinked file.
+
+* Changed vfs_chown functions to reset SUID and SGID on a chown because the
+ new kernel wants that.
+
+* Changed locking on I/O to use semaphores instead off the mnt_flags
+ used before. The old stuff could lock quota easily probably because
+ the operation wasn't atomic. This should now be fixed.
+
+* Fixed check_bdq to only give back a available blocks when the current
+ number of blocks are below the hardlimit. There was a bugfix for this
+ one so I applied that.
+
+* Changed has_quota funtion to use a static buffer instead of mallocing
+ one everytime it needs one. Hope this helps with the reported memory
+ leak on the rquotad.
+
+* Fixed some little bugs in dquot.c with the setting of the QF_OPENING
+ flag and not resseting it on failure of opening the quotafile.
+
+* Added changes needed because the VFS-layer changed to use iattr structs
+ for the notify_change function.
+
+* Fixed quota_transfer to work again with the new iattr structs, hopefully
+ it works ok now. It was brought to my attension that it wasn't working
+ the way it should in the old version. So I first checked out the fix that
+ I received, but that didn't solve the problem either so I fixed it myself.
+
+* Combined the new writeaccess stuff with the stuff I already had. Also
+ cleaned up vfs layer some more because of the use of the new
+ vfs_getwriteaccess and vfs_putwriteaccess functions. This also involved
+ the quotaon function that should now return a propper errno on failure and
+ not the standard EIO that it was in earlier versions.
+
+Changes in quota-package from 1.32 to 1.33
+
+* Ported the stuff back to the normal kernel to make a diff-file quite easy.
+
+* Fixed some typos that could trigger a kernel panic because the locking gets
+ killed when a quota is exeeded.
+
+* Fixed the stuff to work with the the new-tty-drivers.
+
+* This patches aren't that well tested on the machines I use because I use a
+ complete different kernel over here. But thats why this is called BETA
+ software. The bigfiles in this package are copies of the files used in my
+ kernel so some thing are tested more then others.
+
+* Fixed quotacheck not to memset the whole quota when there are no blocks
+ allocated by this user.
+
+Changes in quota-package from 1.31 to 1.32
+
+* Fixed diff-files, the are now made as unified diffs.
+
+* Checked the specifications for the rquota service, I was correct we only need
+ to respond to udp connections.
+
+Changes in quota-package from 1.3 to 1.31
+
+* Changed quotacheck program to stuff directories it encounters on a
+ directory stack and check them later on. This way there is at any
+ time one directory opened for reading. In the old situation it could
+ happen that more then one directory were open at the same time and
+ with nasty directory structures this could give to much open directories
+ at ones, leading to an error by the O.S.
+
+* Added some hooks for debugging the memory usage by the program, and make
+ the stdout used for the -v flag non-buffered for more speed.
+
+* Added variabele to mountstruct for flags, now we can mask when we are
+ opening or closeing a quotafile, when we are we may not give out
+ pointers with the dq_get function, otherwise we run into problems
+ later on.
+
+* Ok updated fs/*.c missed patch to fs/inode.c that solves a race condition.
+
+* Added vfs_rename function that takes care of renaming files on top of already
+ existing files. We were missing those ones, thanks to David Black for
+ reporting this. If there are still problems I will hear so and try to fix them
+ as soon as I can.
+
+Changes in quota-package from 1.2 to 1.3
+
+* We only reply to rpc_quota_request made to the udp port of the
+ rquotad, I just removed support for the TCP service, I don't
+ think it's needed to have the TCP service for just exchanging
+ about 40 bytes of data. Too much overhead setting up a TCP connection.
+
+* Changed vfs_write function within fileio.h to be a bit smarter. If
+ the fileposition + number of bytes to be written is less then the
+ current size of the file we should even bother checking it. And if
+ the number of wanted_blocks equals to 0 why even bother checking
+ the quota no changes are made anyway.
+
+* Rewrote the quota stuff to be much more flexible, we now use pointers
+ that are located within the inode for fast lookup. This is a bit more
+ to setup but is much faster when used over and over again. Its based
+ on the setup used for inode caching and is mostly rewritten code with
+ some extensions that were needed for the dquot structs. And of course
+ a lot extra because dquot aren't exactly inodes.
+
+* Ok file is called dquot.c again because it specific to diskquotas. If
+ we ever get process quota, we have to move the system-call interface to
+ the kernel dir.
+
+* splitted fileio header into fileio.c and fileio.h. Fileio.c contains
+ the code for all the functions, fileio.h contains the prototypes for
+ the functions when quota is enabled and defines to the the default
+ inode operations if it is disabled.
+
+* Moved device management code to the file fs/super.c and made it a
+ bit more general. The stuff now can also be used for other purposes.
+ For now it contains the devicename, the directory the filesystem is
+ mounted on, a pointer to the superblock and the quota expire times
+ and filepointers, this can be extended in the future and this can be
+ used for other purposes then only quota. Its in super.c because it
+ is related to mounting a filesystem. The rootfilesystem is a special
+ case for which I don't have a nice solution right now.
+
+* Cleaned up the file file_table.c and renamed it to file.c, otherwise
+ we should call inode.c inode_table.c etc. More is static now, the
+ file_table isn't accesable anymore from everywhere, and the functions
+ that need the info within file.c should be located within that file.
+ A good example is the function used by the vhangup code, it now calls
+ a routine within file.c and so we don't have export any data anymore.
+
+* changed decrement quota to reset the DQ_INODES and DQ_BLKS flag on
+ a decrement of a quota. It seems that we should bark again when one
+ goes over his quota after he removed something, ok should work this
+ way.
+
+* changed set_dqblk to set the grace period when a new usage is set
+ and one exceeds his softlimit by that operation. Better then just
+ setting the graceperiod when he allocates any more inodes or blocks.
+ Only can give surprises when logging in but who cares they can ask
+ the sysadmin to give them a hand with cleaning there dirs.
+
+* quotaoff is very simple now just reset all the pointers that point
+ to a dquot and trash the cache for all dquots that are related to
+ the device being turned of. This way the next time you put it on the
+ stuff get read again from disk and not from the cache.
+
+* changed most of the file structs to be a filepointer and request it
+ with get_empty_filp. This way we allocate it from the file_table which
+ is more the way it should be, Ok I know the dummy_inodes isn't that
+ nice either, but for that we don't have an other choice. Also it makes
+ live much easier this way. See the core dump stuff.
+
+* used some more constants for setting up the file pointers, this should
+ make it easier to read. So ok Edvard ?
+
+* rewrote most functions such as quota_alloc, quota_remove and quota_transfer
+ to use a for loop which counts from 0 to the number of quotas -1. This way
+ it should be easy to extend the quota stuff to maintain even more types of
+ quota. (At the moment I can think of one more, what about quotas for a
+ processgroups) :-)
+
+* rewrote quota_transfer, its still the most complicated function of the
+ three manipulate functions, but it looks much cleaner then the one we
+ had.
+
+* changed the system-call interface again this should be the last time,
+ hope to have it made more intelligent now, most of the calls are quite
+ the same, so just set flags and call one functions. Saves some functions.
+
+* And more cleanups to the vfs-layer. Did a kind of indent on all the sources
+ in the fs-dir by hand. All references to file pointers are now done by a
+ variable that is called filp. This is done to be a bit more consistent all
+ through the code. Before is was called file, filp, f etc.
+
+* As of the indent I changed all tabs to be 3 spaces this makes it a bit
+ larger but much better to read.
+
+* Someone reported that there are problems with fstab when you use something
+ like usrquota=/usr/adm/quota.user,grpquota=/usr/adm/quota.grp. I don't know
+ if the problems is also in the new libs, if so I have a replacement here for
+ the entire mntent stuff. I wrote this way back and it work ok so if you
+ have problems mail me and I will send you the sources. For now I didn't
+ include it yet in the standard mainline distribution.
+
+* Ok added hooks to the fork code forgot that, ok this has cost me some
+ searching. We must doe an vfs_open_filp when a process forks and the
+ filepointers are copied or incremented.
+
+Changes in quota-package from 1.1 to 1.2
+
+* Changed repquota.c to display at max 8 chars of username.
+
+* Changed rquota_svc.c and rquota_server.c to handle both version 1
+ and 2 requests. Now we should be able to communicate with sun systems.
+ SUN systems send out version 1 request which we can handle now.
+
+* Changed quota.c to first send out a version 2 rquota request and if
+ that fails to try it with a version 1 request. Now we should be able to
+ query a rquotad on a sun-server exporting a NFS disk.
+
+* Changed kernel diffs, now use a header file fileio.h with vfs functions
+ for writing, truncating, creating files/nodes. This cleaned up the
+ kernel diffs quite a bit. (Should have done this way back, but it is
+ done now)
+
+* Fixed some small bugs with handling graceperiods again. Changed the code
+ in the systemcall interface all bugs should be gone now there.
+
+* Wrote a new program warnquota. No manpage yet but it has no flags so
+ that's simple. You can run this from your crontab just like you run
+ quotacheck every night from cron. This program mails a message to all
+ users that violated the quota system.
+
+* Changed fileio.h with unlinking and rmdir to make a copy of the inode.
+ Hope this fixes some problems we have seen with xiafs. It isn't to bad
+ either should have been this way from the beginning. A pointer to a
+ inode that is removed is a bit to tricky a copy in local memory is much
+ saver.
+
+* Changed fs/quota.c to not check if the quotafile is on the same device
+ as the device for which it contains info. Found that in a document but
+ it's silly and so it's removed now. Who cares where you put it as long
+ the kernel can find it and it is the right format.
+ (Now something like usrquota="/var/adm/quota_src.user" should work :-))
+
+* Changed edquota behaviour with -p flag. It now copies the current
+ usage to the new situation.
+
+Changes in quota-package from 1.0 to 1.1
+
+* Moved check to test on quota on a certain filesystem to seperate file
+ hasquota.c
+
+* Changed hasquota.c to use quotafile given in fstab file instead
+ of the default name of a quotafile. We now can define ourself where
+ to put our quotafile. Something like "usrquota=/usr/adm/quotasrc.user"
+
+* Changed graceperiod counting was doing it the wrong way around. Now we
+ add the expiretime to the current time and that is the grace-period a user
+ has before we see a softlimit as a hardlimit.
+
+* Changed allocation when not enough blocks can be allocated from ones quota.
+ Now you get as many blocks as you can affort yourself and not as in the
+ earlier version, nothing. This was a bit of a bitch to tackle but it seems
+ to work ok now for regular files and core-files.
+
+* Changed the quota.h file to include a prototype for a new function
+ blocks_to_isize that calculates the maximum isize for a file when allocating
+ less blocks than requested. Also included macro's for min() and max().
+
+* Added rquotad program for own convinience, this was build from scratch with
+ only the rquota.x file. It seems to work quite nice between LINUX machines
+ don't have the resources to test it with other then LINUX machines.
+ We probably need a new version number for this type of rquota.
+ Something like rquota version 2 or something like that.
+
+* Changed quota program to use a rpc-call to the rquotad on one of you
+ disk server machines. See #ifdef RPC in quota.c. Use small timeout because
+ I don't wanna wait to long when a machine is down. Increase it when you have
+ problems with slow hosts.
+
+* Rewrite of quotacheck program. This one is much faster, about 60%. Thanks
+ to Edvard for this big improvement.
+
+* Changed namei.c to iput the inode of a dir when doing a remove of a dir.
+ I never had problems with it but it seems that ext2 doesn't care to much when
+ you unlink a dir while you have the inode still open. Fixed it and it works
+ now ok also on xiafs which had problems with it, and of course the fragment
+ should have give this error because you have to iput the dir before you remove
+ it.
+
+* Changed source of quotacheck to create new quotafile with at least the
+ gracetimes. Now there should never be a problem when turning on quota with
+ the quotactl systemcall after one has run quotacheck to create the correct
+ quotafiles.
+
+* Changed code of quota.c to read MOUNTED(mtab) instead of FSTAB(fstab) when
+ showing quotainfo.
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..7033965
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,140 @@
+PROGS = quotacheck quotaon quota quot repquota warnquota quotastats xqmstats edquota setquota convertquota rpc.rquotad
+CFLAGS = @CFLAGS@ @EXT2_DIRECT@ -D_GNU_SOURCE -Wall
+EXT2LIBS = @EXT2LIBS@
+RPCSRC = rquota.h rquota_xdr.c rquota_clnt.c
+VERSIONDEF = -DQUOTA_VERSION=\"3.01\"
+LIBS = @LIBS@
+LDFLAGS = @LDFLAGS@
+
+#
+# Uncomment the two lines below to add tcp_wrapper support for rpc.rquotad
+# Then add lines to /etc/hosts.allow and /etc/hosts.deny
+# like: "rquotad: ALL@ALL except my.host.i.want.com" in hosts.deny means
+# only the host designated can get info from rquotad
+# NOTE: I used gethostbyaddr(), so you may need FQDN or merely host name
+# depending on how your resolver returns first. IP Addresses will work as well.
+#
+CFLAGS += @HOSTS_ACCESS@
+CFLAGS += $(VERSIONDEF)
+
+INSTALL = @INSTALL@
+LN = ln -sf
+ROOTDIR =
+SUPER_OWNER = root
+BIN_OWNER = bin
+BIN_GROUP = bin
+DEF_SUID_MODE = 4511
+DEF_BIN_MODE = 555
+DEF_SBIN_MODE = 555
+DEF_MAN_MODE = 444
+RPCGEN = rpcgen
+
+prefix = @prefix@
+bindir = $(prefix)/bin
+sbindir = $(prefix)/sbin
+mandir = @mandir@
+includedir = $(prefix)/include
+root_sbindir = /sbin
+locale_dir = $(prefix)/share/locale
+
+RPCCLNTOBJS = rquota_xdr.o rquota_client.o rquota_clnt.o
+IOOBJS = quotaio.o quotaio_v1.o quotaio_v2.o quotaio_rpc.o quotaio_xfs.o
+IOOBJS += $(RPCCLNTOBJS)
+LIBOBJS = bylabel.o common.o quotasys.o pot.o $(IOOBJS)
+LIBOBJS += @LIBMALLOC@
+INCLUDE = common.h quotasys.h bylabel.h
+
+all: $(PROGS)
+
+clean:
+ -rm -f core *.o
+
+clobber: clean
+ -rm -f $(PROGS) Makefile config.{status,cache,log}
+
+realclean: clobber
+ -rm -f $(RPCSRC) po/*.mo
+
+pot:
+ xgettext -k_ -d pot *.c
+
+mo: po
+ for n in $(shell ls po/*.po); do \
+ msgfmt -o po/`basename $$n .po`.mo $$n; \
+ done
+
+inst_mo: mo
+ mkdir -p $(locale_dir)
+ for n in $(shell ls po/*.po | sed 's/\.po/\.mo/'); do \
+ l=`basename $$n .mo`; \
+ $(INSTALL) -m 755 -d $(ROOTDIR)$(locale_dir)/$$l; \
+ $(INSTALL) -m 755 -d $(ROOTDIR)$(locale_dir)/$$l/LC_MESSAGES; \
+ $(INSTALL) -m 644 $$n $(ROOTDIR)$(locale_dir)/$$l/LC_MESSAGES/quota.mo; \
+ done
+
+install: all inst_mo
+ -$(INSTALL) -m $(DEF_SBIN_MODE) \
+ quotacheck quotaon $(ROOTDIR)$(root_sbindir)
+ $(LN) quotaon $(ROOTDIR)$(root_sbindir)/quotaoff
+ chown -h $(BIN_OWNER):$(BIN_GROUP) $(ROOTDIR)$(root_sbindir)/quotaoff
+ -$(INSTALL) -m $(DEF_SBIN_MODE) \
+ edquota repquota warnquota quotastats setquota quot $(ROOTDIR)$(sbindir)
+ -$(INSTALL) -m 755 -d $(ROOTDIR)$(includedir)/rpcsvc
+ -$(INSTALL) -m 644 rquota.h rquota.x $(ROOTDIR)$(includedir)/rpcsvc
+ -$(INSTALL) -s -m $(DEF_SBIN_MODE) quota $(ROOTDIR)$(bindir)
+ -$(INSTALL) -s -m $(DEF_SBIN_MODE) rpc.rquotad $(ROOTDIR)$(sbindir)
+ -$(INSTALL) -m $(DEF_MAN_MODE) *.1 $(ROOTDIR)$(mandir)/man1
+ -$(INSTALL) -m $(DEF_MAN_MODE) *.2 $(ROOTDIR)$(mandir)/man2
+ -$(INSTALL) -m $(DEF_MAN_MODE) *.3 $(ROOTDIR)$(mandir)/man3
+ -$(INSTALL) -m $(DEF_MAN_MODE) *.8 $(ROOTDIR)$(mandir)/man8
+
+quotaon: $(INCLUDE) quotaon.o quotaon_xfs.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ quotaon.o quotaon_xfs.o $(LIBOBJS)
+
+quotacheck: $(INCLUDE) quotacheck.o quotacheck_v1.o quotacheck_v2.o quotacheck.h $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ quotacheck.o quotacheck_v1.o quotacheck_v2.o $(EXT2LIBS) $(LIBOBJS)
+
+quota: $(INCLUDE) rquota.h quota.o quotaops.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ quota.o quotaops.o $(LIBOBJS)
+
+quot: $(INCLUDE) quot.h quot.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ quot.o $(LIBOBJS)
+
+repquota: $(INCLUDE) repquota.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ repquota.o $(LIBOBJS)
+
+warnquota: $(INCLUDE) common.h warnquota.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ warnquota.o $(LIBOBJS)
+
+quotastats: quotastats.o pot.o
+ $(CC) $(LDFLAGS) -o $@ quotastats.o pot.o
+
+xqmstats: xqmstats.o pot.o
+ $(CC) $(LDFLAGS) -o $@ xqmstats.o pot.o
+
+edquota: $(INCLUDE) quotaops.h quotaio.h edquota.o quotaops.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ edquota.o quotaops.o $(LIBOBJS)
+
+setquota: $(INCLUDE) setquota.o quotaops.o rquota.h $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ setquota.o quotaops.o $(LIBOBJS)
+
+convertquota: $(INCLUDE) convertquota.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ convertquota.o $(LIBOBJS)
+
+rpc.rquotad: $(INCLUDE) rquota.h rquota_server.o rquota_svc.o $(LIBOBJS)
+ $(CC) $(LDFLAGS) -o $@ rquota_server.o rquota_svc.o $(LIBOBJS) $(LIBS)
+
+pot.o: pot.c pot.h
+ $(CC) $(CFLAGS) -c $<
+
+rquota.h: rquota.x
+ $(RPCGEN) -h -o $@ $<
+
+rquota_xdr.c: rquota.x
+ $(RPCGEN) -c -o $@ $<
+
+rquota_xdr.o: rquota_xdr.c rquota.h
+ $(CC) $(CFLAGS) -Wno-unused -c $<
+
+rquota_clnt.c: rquota.x
+ $(RPCGEN) -l -o $@ $<
diff --git a/README.gettext b/README.gettext
new file mode 100644
index 0000000..6bcb14f
--- /dev/null
+++ b/README.gettext
@@ -0,0 +1,21 @@
+If you want to generate new po file: "make pot" and look for a file named
+pot.po. To generate mo files from po files: "make mo", it's also done when
+you "make install", if you want to install only mo files ( no programs )
+"make inst_mo", mo files will be copied to:
+/usr/share/locale/'languages names'/LC_MESSAGES/quota.mo.
+
+warnquota
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+this program was modifiated to be more configurable - you can now specify
+new warning message ( also sender, cc, etc. ) without recompiling the
+program. all you need is to edit pot.po ( make pot ), you will find
+in it mail message, and etc. - create new strings, make mo with msgfmt, and copy
+mo file to /usr/share/locale/'lang'/LC_MESSAGES/quota.mo. now you have new
+warning mail message.
+
+gettext support was added by Paul Niewiadomski <lilo@free.poltronic.net>, any
+questions, suggestions are welcome.
+
+thanks to
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Roman_Kaminski@saba.com.pl \ No newline at end of file
diff --git a/bylabel.c b/bylabel.c
new file mode 100644
index 0000000..3ce77b2
--- /dev/null
+++ b/bylabel.c
@@ -0,0 +1,256 @@
+/*
+ * Derived from the util-linux/mount/mount_by_label.c source,
+ * currently maintained by Andries Brouwer <aeb@cwi.nl>.
+ *
+ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
+ * - added Native Language Support
+ * 2000-01-20 James Antill <james@and.org>
+ * - Added error message if /proc/partitions cannot be opened
+ * 2000-05-09 Erik Troan <ewt@redhat.com>
+ * - Added cache for UUID and disk labels
+ * 2000-11-07 Nathan Scott <nathans@sgi.com>
+ * - Added XFS support
+ */
+
+#include <stdio.h>
+#include <sys/param.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "bylabel.h"
+#include "common.h"
+#include "pot.h"
+
+#define PROC_PARTITIONS "/proc/partitions"
+#define DEVLABELDIR "/dev"
+
+static struct uuidCache_s {
+ struct uuidCache_s *next;
+ char uuid[16];
+ char *label;
+ char *device;
+} *uuidCache = NULL;
+
+#define EXT2_SUPER_MAGIC 0xEF53
+struct ext2_super_block {
+ u_char s_dummy1[56];
+ u_char s_magic[2];
+ u_char s_dummy2[46];
+ u_char s_uuid[16];
+ u_char s_volume_name[16];
+};
+
+#define ext2magic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+
+#define XFS_SUPER_MAGIC "XFSB"
+#define XFS_SUPER_MAGIC2 "BSFX"
+struct xfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[28];
+ u_char s_uuid[16];
+ u_char s_dummy2[60];
+ u_char s_fsname[12];
+};
+
+static inline unsigned short swapped(unsigned short a)
+{
+ return (a >> 8) | (a << 8);
+}
+
+/* for now, only ext2 and xfs are supported */
+static int get_label_uuid(const char *device, char **label, char *uuid)
+{
+
+ /* start with ext2 and xfs tests, taken from mount_guess_fstype */
+ /* should merge these later */
+ int fd;
+ int rv = 1;
+ size_t namesize;
+ struct ext2_super_block e2sb;
+ struct xfs_super_block xfsb;
+
+ fd = open(device, O_RDONLY);
+ if (fd < 0)
+ return rv;
+
+ if (lseek(fd, 1024, SEEK_SET) == 1024
+ && read(fd, (char *)&e2sb, sizeof(e2sb)) == sizeof(e2sb)
+ && ext2magic(e2sb) == EXT2_SUPER_MAGIC) {
+ memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+ namesize = sizeof(e2sb.s_volume_name);
+ *label = smalloc(namesize + 1);
+ sstrncpy(*label, e2sb.s_volume_name, namesize);
+ rv = 0;
+ }
+ else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char *)&xfsb, sizeof(xfsb)) == sizeof(xfsb)
+ && (strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0 ||
+ strncmp((char *)&xfsb.s_magic, XFS_SUPER_MAGIC2, 4) == 0)) {
+ memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+ namesize = sizeof(xfsb.s_fsname);
+ *label = smalloc(namesize + 1);
+ sstrncpy(*label, xfsb.s_fsname, namesize);
+ rv = 0;
+ }
+
+ close(fd);
+ return rv;
+}
+
+static void uuidcache_addentry(char *device, char *label, char *uuid)
+{
+ struct uuidCache_s *last;
+
+ if (!uuidCache) {
+ last = uuidCache = smalloc(sizeof(*uuidCache));
+ }
+ else {
+ for (last = uuidCache; last->next; last = last->next);
+ last->next = smalloc(sizeof(*uuidCache));
+ last = last->next;
+ }
+ last->next = NULL;
+ last->device = device;
+ last->label = label;
+ memcpy(last->uuid, uuid, sizeof(last->uuid));
+}
+
+static void uuidcache_init(void)
+{
+ char line[100];
+ char *s;
+ int ma, mi, sz;
+ static char ptname[100];
+ FILE *procpt;
+ char uuid[16], *label;
+ char device[110];
+ int firstPass;
+ int handleOnFirst;
+
+ if (uuidCache)
+ return;
+
+ procpt = fopen(PROC_PARTITIONS, "r");
+ if (!procpt)
+ return;
+
+ for (firstPass = 1; firstPass >= 0; firstPass--) {
+ fseek(procpt, 0, SEEK_SET);
+
+ while (fgets(line, sizeof(line), procpt)) {
+ if (sscanf(line, " %d %d %d %[^\n ]", &ma, &mi, &sz, ptname) != 4)
+ continue;
+
+ /* skip extended partitions (heuristic: size 1) */
+ if (sz == 1)
+ continue;
+
+ /* look only at md devices on first pass */
+ handleOnFirst = !strncmp(ptname, "md", 2);
+ if (firstPass != handleOnFirst)
+ continue;
+
+ /* skip entire disk (minor 0, 64, ... on ide;
+ 0, 16, ... on sd) */
+ /* heuristic: partition name ends in a digit */
+
+ for (s = ptname; *s; s++);
+ if (isdigit(s[-1])) {
+ /*
+ * Note: this is a heuristic only - there is no reason
+ * why these devices should live in /dev.
+ * Perhaps this directory should be specifiable by option.
+ * One might for example have /devlabel with links to /dev
+ * for the devices that may be accessed in this way.
+ * (This is useful, if the cdrom on /dev/hdc must not
+ * be accessed.)
+ */
+ sprintf(device, "%s/%s", DEVLABELDIR, ptname);
+ if (!get_label_uuid(device, &label, uuid))
+ uuidcache_addentry(sstrdup(device), label, uuid);
+ }
+ }
+ }
+
+ fclose(procpt);
+}
+
+#define UUID 1
+#define VOL 2
+
+static char *get_spec_by_x(int n, const char *t)
+{
+ struct uuidCache_s *uc;
+
+ uuidcache_init();
+ uc = uuidCache;
+
+ while (uc) {
+ switch (n) {
+ case UUID:
+ if (!memcmp(t, uc->uuid, sizeof(uc->uuid)))
+ return sstrdup(uc->device);
+ break;
+ case VOL:
+ if (!strcmp(t, uc->label))
+ return sstrdup(uc->device);
+ break;
+ }
+ uc = uc->next;
+ }
+ return NULL;
+}
+
+static u_char fromhex(char c)
+{
+ if (isdigit(c))
+ return (c - '0');
+ else if (islower(c))
+ return (c - 'a' + 10);
+ else
+ return (c - 'A' + 10);
+}
+
+static char *get_spec_by_uuid(const char *s)
+{
+ u_char uuid[16];
+ int i;
+
+ if (strlen(s) != 36 || s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-')
+ goto bad_uuid;
+ for (i = 0; i < 16; i++) {
+ if (*s == '-')
+ s++;
+ if (!isxdigit(s[0]) || !isxdigit(s[1]))
+ goto bad_uuid;
+ uuid[i] = ((fromhex(s[0]) << 4) | fromhex(s[1]));
+ s += 2;
+ }
+ return get_spec_by_x(UUID, uuid);
+
+ bad_uuid:
+ fprintf(stderr, _("Found an invalid UUID: %s\n"), s);
+ return NULL;
+}
+
+static char *get_spec_by_volume_label(const char *s)
+{
+ return get_spec_by_x(VOL, s);
+}
+
+const char *get_device_name(const char *item)
+{
+ const char *rc;
+
+ if (!strncmp(item, "UUID=", 5))
+ rc = get_spec_by_uuid(item + 5);
+ else if (!strncmp(item, "LABEL=", 6))
+ rc = get_spec_by_volume_label(item + 6);
+ else
+ rc = sstrdup(item);
+ if (!rc)
+ fprintf(stderr, _("Error checking device name: %s\n"), item);
+ return rc;
+}
diff --git a/bylabel.h b/bylabel.h
new file mode 100644
index 0000000..271c5cb
--- /dev/null
+++ b/bylabel.h
@@ -0,0 +1,4 @@
+#ifndef _BYLABEL_H_
+#define _BYLABEL_H_
+const char *get_device_name(const char *item);
+#endif /* _BYLABEL_H_ */
diff --git a/common.c b/common.c
new file mode 100644
index 0000000..f77f2e5
--- /dev/null
+++ b/common.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * Common things for all utilities
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "pot.h"
+#include "common.h"
+
+void die(int ret, char *fmtstr, ...)
+{
+ va_list args;
+
+ va_start(args, fmtstr);
+ vfprintf(stderr, fmtstr, args);
+ va_end(args);
+ exit(ret);
+}
+
+void *smalloc(size_t size)
+{
+ void *ret = malloc(size);
+
+ if (!ret) {
+ puts("Not enough memory.\n");
+ exit(3);
+ }
+ return ret;
+}
+
+void sstrncpy(char *d, const char *s, int len)
+{
+ strncpy(d, s, len);
+ d[len - 1] = 0;
+}
+
+void sstrncat(char *d, const char *s, int len)
+{
+ strncat(d, s, len);
+ d[len - 1] = 0;
+}
+
+char *sstrdup(const char *s)
+{
+ char *r = strdup(s);
+
+ if (!r) {
+ puts("Not enough memory.");
+ exit(3);
+ }
+ return r;
+}
+
+void version(void)
+{
+ printf(_("Quota utilities version %s.\n"), QUOTA_VERSION);
+#if defined(RPC) || defined(EXT2_DIRECT)
+ printf(_("Compiled with "));
+#if defined(RPC) && defined(EXT2_DIRECT)
+ puts(_("RPC and EXT2_DIRECT"));
+#elif defined(RPC)
+ puts(_("RPC"));
+#else
+ puts(_("EXT2_DIRECT"));
+#endif /* defined RPC && EXT2_DIRECT */
+#endif /* defined RPC || EXT2_DIRECT */
+}
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..8da6df9
--- /dev/null
+++ b/common.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * Various things common for all utilities
+ *
+ */
+
+#ifndef _COMMON_H
+#define _COMMON_H
+
+#define MY_EMAIL "mvw@planets.elm.net, jack@atrey.karlin.mff.cuni.cz"
+
+/* Finish programs being */
+void die(int, char *, ...);
+
+/* malloc() with error check */
+void *smalloc(size_t);
+
+/* Safe strncpy - always finishes string */
+void sstrncpy(char *, const char *, int);
+
+/* Safe strncat - always finishes string */
+void sstrncat(char *, const char *, int);
+
+/* Safe version of strdup() */
+char *sstrdup(const char *s);
+
+/* Print version string */
+void version(void);
+
+#endif /* _COMMON_H */
diff --git a/configure b/configure
new file mode 100755
index 0000000..e329c8f
--- /dev/null
+++ b/configure
@@ -0,0 +1,1721 @@
+#! /bin/sh
+
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.13
+# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+ --enable-altformat=[yes/no] Enable alternative format used by edquota [default=yes]."
+ac_help="$ac_help
+ --enable-rpc=[yes/no] Enable RPC support [default=yes]."
+ac_help="$ac_help
+ --enable-rpcsetquota=[yes/no] Use RPC for setting quotas [default=yes]."
+ac_help="$ac_help
+ --enable-libefence=[yes/no] Use Electric Fence memory checks [default=no]."
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+# Initialize some other variables.
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
+
+ac_prev=
+for ac_option
+do
+
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ case "$ac_option" in
+ -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) ac_optarg= ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case "$ac_option" in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir="$ac_optarg" ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build="$ac_optarg" ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file="$ac_optarg" ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir="$ac_optarg" ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ eval "enable_${ac_feature}=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+ fi
+ ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix="$ac_optarg" ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he)
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+ --cache-file=FILE cache test results in FILE
+ --help print this message
+ --no-create do not create output files
+ --quiet, --silent do not print \`checking...' messages
+ --version print the version of autoconf that created configure
+Directory and file names:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [same as prefix]
+ --bindir=DIR user executables in DIR [EPREFIX/bin]
+ --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
+ --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data in DIR
+ [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data in DIR
+ [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
+ --libdir=DIR object code libraries in DIR [EPREFIX/lib]
+ --includedir=DIR C header files in DIR [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
+ --infodir=DIR info documentation in DIR [PREFIX/info]
+ --mandir=DIR man documentation in DIR [PREFIX/man]
+ --srcdir=DIR find the sources in DIR [configure dir or ..]
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM
+ run sed PROGRAM on installed program names
+EOF
+ cat << EOF
+Host type:
+ --build=BUILD configure for building on BUILD [BUILD=HOST]
+ --host=HOST configure for HOST [guessed]
+ --target=TARGET configure for TARGET [TARGET=HOST]
+Features and packages:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --x-includes=DIR X include files are in DIR
+ --x-libraries=DIR X library files are in DIR
+EOF
+ if test -n "$ac_help"; then
+ echo "--enable and --with options recognized:$ac_help"
+ fi
+ exit 0 ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host="$ac_optarg" ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir="$ac_optarg" ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir="$ac_optarg" ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir="$ac_optarg" ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir="$ac_optarg" ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir="$ac_optarg" ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir="$ac_optarg" ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir="$ac_optarg" ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix="$ac_optarg" ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix="$ac_optarg" ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix="$ac_optarg" ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name="$ac_optarg" ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir="$ac_optarg" ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir="$ac_optarg" ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site="$ac_optarg" ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir="$ac_optarg" ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir="$ac_optarg" ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target="$ac_optarg" ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers)
+ echo "configure generated by autoconf version 2.13"
+ exit 0 ;;
+
+ -with-* | --with-*)
+ ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case "$ac_option" in
+ *=*) ;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_${ac_package}='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ # Reject names that are not valid shell variable names.
+ if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+ { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+ fi
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ eval "with_${ac_package}=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes="$ac_optarg" ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries="$ac_optarg" ;;
+
+ -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ ;;
+
+ *)
+ if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+ echo "configure: warning: $ac_option: invalid host type" 1>&2
+ fi
+ if test "x$nonopt" != xNONE; then
+ { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+ fi
+ nonopt="$ac_option"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+ exec 6>/dev/null
+else
+ exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+ case "$ac_arg" in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+ ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ esac
+done
+
+# NLS nuisances.
+# Only set these to C if already set. These must not be set unconditionally
+# because not all systems understand e.g. LANG=C (notably SCO).
+# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
+# Non-C LC_CTYPE values break the ctype check.
+if test "${LANG+set}" = set; then LANG=C; export LANG; fi
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
+if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=quota.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_prog=$0
+ ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ else
+ { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ echo "loading site script $ac_site_file"
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ echo "loading cache $cache_file"
+ . $cache_file
+else
+ echo "creating cache $cache_file"
+ > $cache_file
+fi
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+ac_exeext=
+ac_objext=o
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+ # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+ if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+ ac_n= ac_c='
+' ac_t=' '
+ else
+ ac_n=-n ac_c= ac_t=
+ fi
+else
+ ac_n= ac_c='\c' ac_t=
+fi
+
+
+
+# Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:537: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="gcc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:567: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_prog_rejected=no
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# -gt 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ set dummy "$ac_dir/$ac_word" "$@"
+ shift
+ ac_cv_prog_CC="$@"
+ fi
+fi
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+ if test -z "$CC"; then
+ case "`uname -s`" in
+ *win32* | *WIN32*)
+ # Extract the first word of "cl", so it can be a program name with args.
+set dummy cl; ac_word=$2
+echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
+echo "configure:618: checking for $ac_word" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -f $ac_dir/$ac_word; then
+ ac_cv_prog_CC="cl"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+ echo "$ac_t""$CC" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
+ ;;
+ esac
+ fi
+ test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+fi
+
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:650: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+cat > conftest.$ac_ext << EOF
+
+#line 661 "configure"
+#include "confdefs.h"
+
+main(){return(0);}
+EOF
+if { (eval echo configure:666: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ ac_cv_prog_cc_works=yes
+ # If we can't run a trivial program, we are probably using a cross compiler.
+ if (./conftest; exit) 2>/dev/null; then
+ ac_cv_prog_cc_cross=no
+ else
+ ac_cv_prog_cc_cross=yes
+ fi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ ac_cv_prog_cc_works=no
+fi
+rm -fr conftest*
+ac_ext=c
+# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+ { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
+echo "configure:692: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
+cross_compiling=$ac_cv_prog_cc_cross
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:697: checking whether we are using GNU C" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.c <<EOF
+#ifdef __GNUC__
+ yes;
+#endif
+EOF
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:706: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+ ac_cv_prog_gcc=yes
+else
+ ac_cv_prog_gcc=no
+fi
+fi
+
+echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
+if test $ac_cv_prog_gcc = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+
+ac_test_CFLAGS="${CFLAGS+set}"
+ac_save_CFLAGS="$CFLAGS"
+CFLAGS=
+echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:725: checking whether ${CC-cc} accepts -g" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ ac_cv_prog_cc_g=yes
+else
+ ac_cv_prog_cc_g=no
+fi
+rm -f conftest*
+
+fi
+
+echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS="$ac_save_CFLAGS"
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:757: checking how to run the C preprocessor" >&5
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ # This must be in double quotes, not single quotes, because CPP may get
+ # substituted into the Makefile and "${CC-cc}" will confuse make.
+ CPP="${CC-cc} -E"
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp.
+ cat > conftest.$ac_ext <<EOF
+#line 772 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:778: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -E -traditional-cpp"
+ cat > conftest.$ac_ext <<EOF
+#line 789 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:795: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP="${CC-cc} -nologo -E"
+ cat > conftest.$ac_ext <<EOF
+#line 806 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:812: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ :
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+ ac_cv_prog_CPP="$CPP"
+fi
+ CPP="$ac_cv_prog_CPP"
+else
+ ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:837: checking for ANSI C header files" >&5
+if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 842 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:850: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ ac_cv_header_stdc=yes
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 867 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "memchr" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+cat > conftest.$ac_ext <<EOF
+#line 885 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ egrep "free" >/dev/null 2>&1; then
+ :
+else
+ rm -rf conftest*
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+ :
+else
+ cat > conftest.$ac_ext <<EOF
+#line 906 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+if { (eval echo configure:917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ :
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_header_stdc=no
+fi
+rm -fr conftest*
+fi
+
+fi
+fi
+
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+ cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+ac_aux_dir=
+for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
+ if test -f $ac_dir/install-sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f $ac_dir/install.sh; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+fi
+ac_config_guess=$ac_aux_dir/config.guess
+ac_config_sub=$ac_aux_dir/config.sub
+ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# ./install, which can be erroneously created by make from ./install.sh.
+echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
+echo "configure:971: checking for a BSD compatible install" >&5
+if test -z "$INSTALL"; then
+if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ for ac_dir in $PATH; do
+ # Account for people who put trailing slashes in PATH elements.
+ case "$ac_dir/" in
+ /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ if test -f $ac_dir/$ac_prog; then
+ if test $ac_prog = install &&
+ grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ else
+ ac_cv_path_install="$ac_dir/$ac_prog -c"
+ break 2
+ fi
+ fi
+ done
+ ;;
+ esac
+ done
+ IFS="$ac_save_IFS"
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL="$ac_cv_path_install"
+ else
+ # As a last resort, use the slow shell script. We don't cache a
+ # path for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the path is relative.
+ INSTALL="$ac_install_sh"
+ fi
+fi
+echo "$ac_t""$INSTALL" 1>&6
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+echo $ac_n "checking for com_err in -lcom_err""... $ac_c" 1>&6
+echo "configure:1025: checking for com_err in -lcom_err" >&5
+ac_lib_var=`echo com_err'_'com_err | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lcom_err $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1033 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char com_err();
+
+int main() {
+com_err()
+; return 0; }
+EOF
+if { (eval echo configure:1044: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo com_err | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lcom_err $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for ext2fs_initialize in -lext2fs""... $ac_c" 1>&6
+echo "configure:1072: checking for ext2fs_initialize in -lext2fs" >&5
+ac_lib_var=`echo ext2fs'_'ext2fs_initialize | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lext2fs $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1080 "configure"
+#include "confdefs.h"
+/* Override any gcc2 internal prototype to avoid an error. */
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char ext2fs_initialize();
+
+int main() {
+ext2fs_initialize()
+; return 0; }
+EOF
+if { (eval echo configure:1091: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo ext2fs | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lext2fs $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+EXT2LIBS=${LIBS}
+
+LIBS=""
+
+echo $ac_n "checking for main in -lnsl""... $ac_c" 1>&6
+echo "configure:1123: checking for main in -lnsl" >&5
+ac_lib_var=`echo nsl'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lnsl $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1131 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1138: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo nsl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lnsl $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+echo $ac_n "checking for main in -lwrap""... $ac_c" 1>&6
+echo "configure:1166: checking for main in -lwrap" >&5
+ac_lib_var=`echo wrap'_'main | sed 'y%./+-%__p_%'`
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_save_LIBS="$LIBS"
+LIBS="-lwrap $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1174 "configure"
+#include "confdefs.h"
+
+int main() {
+main()
+; return 0; }
+EOF
+if { (eval echo configure:1181: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=yes"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ ac_tr_lib=HAVE_LIB`echo wrap | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+ cat >> confdefs.h <<EOF
+#define $ac_tr_lib 1
+EOF
+
+ LIBS="-lwrap $LIBS"
+
+else
+ echo "$ac_t""no" 1>&6
+fi
+
+
+if test ${ac_cv_lib_com_err_com_err} = yes &&
+ test ${ac_cv_lib_ext2fs_ext2fs_initialize} = yes; then
+ ac_safe=`echo "ext2fs/ext2fs.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for ext2fs/ext2fs.h""... $ac_c" 1>&6
+echo "configure:1213: checking for ext2fs/ext2fs.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1218 "configure"
+#include "confdefs.h"
+#include <ext2fs/ext2fs.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1223: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+ echo 'ERROR: could not find ext2fs/ext2fs.h - missing ext2 package'
+ exit 1
+
+fi
+
+ EXT2_DIRECT="-DEXT2_DIRECT"
+
+fi
+
+if test ${ac_cv_lib_wrap_main} = yes; then
+ ac_safe=`echo "tcpd.h" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for tcpd.h""... $ac_c" 1>&6
+echo "configure:1255: checking for tcpd.h" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1260 "configure"
+#include "confdefs.h"
+#include <tcpd.h>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:1265: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=yes"
+else
+ echo "$ac_err" >&5
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+ echo "$ac_t""yes" 1>&6
+ :
+else
+ echo "$ac_t""no" 1>&6
+
+ echo 'ERROR: could not find tcpd.h - missing TCP wrappers package'
+ exit 1
+
+fi
+
+ HOSTS_ACCESS="-DHOSTS_ACCESS"
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:1295: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1300 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:1349: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
+echo $ac_n "checking for inline""... $ac_c" 1>&6
+echo "configure:1370: checking for inline" >&5
+if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+ cat > conftest.$ac_ext <<EOF
+#line 1377 "configure"
+#include "confdefs.h"
+
+int main() {
+} $ac_kw foo() {
+; return 0; }
+EOF
+if { (eval echo configure:1384: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_inline=$ac_kw; break
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+fi
+rm -f conftest*
+done
+
+fi
+
+echo "$ac_t""$ac_cv_c_inline" 1>&6
+case "$ac_cv_c_inline" in
+ inline | yes) ;;
+ no) cat >> confdefs.h <<\EOF
+#define inline
+EOF
+ ;;
+ *) cat >> confdefs.h <<EOF
+#define inline $ac_cv_c_inline
+EOF
+ ;;
+esac
+
+
+# Check whether --enable-altformat or --disable-altformat was given.
+if test "${enable_altformat+set}" = set; then
+ enableval="$enable_altformat"
+ :
+else
+ enable_altformat="yes"
+fi
+
+# Check whether --enable-rpc or --disable-rpc was given.
+if test "${enable_rpc+set}" = set; then
+ enableval="$enable_rpc"
+ :
+else
+ enable_rpc="yes"
+fi
+
+# Check whether --enable-rpcsetquota or --disable-rpcsetquota was given.
+if test "${enable_rpcsetquota+set}" = set; then
+ enableval="$enable_rpcsetquota"
+ :
+else
+ enable_rpcsetquota="yes"
+fi
+
+# Check whether --enable-libefence or --disable-libefence was given.
+if test "${enable_libefence+set}" = set; then
+ enableval="$enable_libefence"
+ :
+else
+ enable_libefence="no"
+fi
+
+
+if test "$enable_altformat" = "yes" ; then
+ CFLAGS="-DALT_FORMAT $CFLAGS";
+fi
+if test "$enable_rpc" = "yes" ; then
+ CFLAGS="-DRPC $CFLAGS";
+fi
+if test "$enable_rpcsetquota" = "yes" ; then
+ CFLAGS="-DRPC_SETQUOTA $CFLAGS"
+fi
+if test "$enable_libefence" = "yes" ; then
+ LIBMALLOC="/usr/lib/libefence.a"
+fi
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs. It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already. You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+EOF
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote substitution
+ # turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ -e "s/'/'\\\\''/g" \
+ -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
+ ;;
+ esac >> confcache
+if cmp -s $cache_file confcache; then
+ :
+else
+ if test -w $cache_file; then
+ echo "updating cache $cache_file"
+ cat confcache > $cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+cat > conftest.defs <<\EOF
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
+s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
+s%\[%\\&%g
+s%\]%\\&%g
+s%\$%$$%g
+EOF
+DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
+rm -f conftest.defs
+
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+ case "\$ac_option" in
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
+ exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
+ -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
+ exit 0 ;;
+ -help | --help | --hel | --he | --h)
+ echo "\$ac_cs_usage"; exit 0 ;;
+ *) echo "\$ac_cs_usage"; exit 1 ;;
+ esac
+done
+
+ac_given_srcdir=$srcdir
+ac_given_INSTALL="$INSTALL"
+
+trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+# Protect against being on the right side of a sed subst in config.status.
+sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
+ s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
+$ac_vpsub
+$extrasub
+s%@SHELL@%$SHELL%g
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@FFLAGS@%$FFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@bindir@%$bindir%g
+s%@sbindir@%$sbindir%g
+s%@libexecdir@%$libexecdir%g
+s%@datadir@%$datadir%g
+s%@sysconfdir@%$sysconfdir%g
+s%@sharedstatedir@%$sharedstatedir%g
+s%@localstatedir@%$localstatedir%g
+s%@libdir@%$libdir%g
+s%@includedir@%$includedir%g
+s%@oldincludedir@%$oldincludedir%g
+s%@infodir@%$infodir%g
+s%@mandir@%$mandir%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
+s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
+s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@EXT2LIBS@%$EXT2LIBS%g
+s%@EXT2_DIRECT@%$EXT2_DIRECT%g
+s%@HOSTS_ACCESS@%$HOSTS_ACCESS%g
+s%@LIBMALLOC@%$LIBMALLOC%g
+
+CEOF
+EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+ else
+ sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+ fi
+ if test ! -s conftest.s$ac_file; then
+ ac_more_lines=false
+ rm -f conftest.s$ac_file
+ else
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f conftest.s$ac_file"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ fi
+ ac_file=`expr $ac_file + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ fi
+done
+if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+fi
+EOF
+
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"Makefile"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case "$ac_file" in
+ *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
+ ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+ *) ac_file_in="${ac_file}.in" ;;
+ esac
+
+ # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
+
+ # Remove last slash and all that follows it. Not all systems have dirname.
+ ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ # The file is in a subdirectory.
+ test ! -d "$ac_dir" && mkdir "$ac_dir"
+ ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ else
+ ac_dir_suffix= ac_dots=
+ fi
+
+ case "$ac_given_srcdir" in
+ .) srcdir=.
+ if test -z "$ac_dots"; then top_srcdir=.
+ else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+ /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ *) # Relative path.
+ srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+ top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ esac
+
+ case "$ac_given_INSTALL" in
+ [/$]*) INSTALL="$ac_given_INSTALL" ;;
+ *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ esac
+
+ echo creating "$ac_file"
+ rm -f "$ac_file"
+ configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+ case "$ac_file" in
+ *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+ *) ac_comsub= ;;
+ esac
+
+ ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
+ sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+s%@INSTALL@%$INSTALL%g
+" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
+fi; done
+rm -f conftest.s*
+
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..bcabb3a
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,73 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(quota.c)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_HEADER_STDC
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+AC_CHECK_LIB(com_err, com_err)
+AC_CHECK_LIB(ext2fs, ext2fs_initialize)
+EXT2LIBS=${LIBS}
+AC_SUBST(EXT2LIBS)
+LIBS=""
+
+AC_CHECK_LIB(nsl, main)
+AC_CHECK_LIB(wrap, main)
+
+if test ${ac_cv_lib_com_err_com_err} = yes &&
+ test ${ac_cv_lib_ext2fs_ext2fs_initialize} = yes; then
+ AC_CHECK_HEADER(ext2fs/ext2fs.h,, [
+ echo 'ERROR: could not find ext2fs/ext2fs.h - missing ext2 package'
+ exit 1
+ ])
+ EXT2_DIRECT="-DEXT2_DIRECT"
+ AC_SUBST(EXT2_DIRECT)
+fi
+
+if test ${ac_cv_lib_wrap_main} = yes; then
+ AC_CHECK_HEADER(tcpd.h,, [
+ echo 'ERROR: could not find tcpd.h - missing TCP wrappers package'
+ exit 1
+ ])
+ HOSTS_ACCESS="-DHOSTS_ACCESS"
+ AC_SUBST(HOSTS_ACCESS)
+fi
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+
+AC_ARG_ENABLE(altformat,
+ [ --enable-altformat=[yes/no] Enable alternative format used by edquota [default=yes].],
+ ,
+ enable_altformat="yes")
+AC_ARG_ENABLE(rpc,
+ [ --enable-rpc=[yes/no] Enable RPC support [default=yes].],
+ ,
+ enable_rpc="yes")
+AC_ARG_ENABLE(rpcsetquota,
+ [ --enable-rpcsetquota=[yes/no] Use RPC for setting quotas [default=yes].],
+ ,
+ enable_rpcsetquota="yes")
+AC_ARG_ENABLE(libefence,
+ [ --enable-libefence=[yes/no] Use Electric Fence memory checks [default=no].],
+ ,
+ enable_libefence="no")
+
+if test "$enable_altformat" = "yes" ; then
+ CFLAGS="-DALT_FORMAT $CFLAGS";
+fi
+if test "$enable_rpc" = "yes" ; then
+ CFLAGS="-DRPC $CFLAGS";
+fi
+if test "$enable_rpcsetquota" = "yes" ; then
+ CFLAGS="-DRPC_SETQUOTA $CFLAGS"
+fi
+if test "$enable_libefence" = "yes" ; then
+ LIBMALLOC="/usr/lib/libefence.a"
+fi
+AC_SUBST(LIBMALLOC)
+
+AC_OUTPUT(Makefile)
diff --git a/convertquota.8 b/convertquota.8
new file mode 100644
index 0000000..de0d76e
--- /dev/null
+++ b/convertquota.8
@@ -0,0 +1,51 @@
+.TH CONVERTQUOTA 8 "Fri Aug 20 1999"
+.UC 4
+.SH NAME
+convertquota \- convert quota from old file format to new one
+.SH SYNOPSIS
+.B convertquota
+[
+.B -ug
+]
+.I filesystem
+.SH DESCRIPTION
+.B convertquota
+converts old quota files
+.BR quota.user
+and
+.BR quota.group
+to files
+.BR aquota.user
+and
+.BR aquota.group
+in new format currently used by kernels 2.4.0-ac? and newer on
+.IR filesystem .
+.PP
+New file format allows using quotas for 32-bit uids / gids, setting quotas for root,
+accounting used space in bytes (and so allowing use of quotas in ReiserFS) and it
+is also architecture independent. This format introduces radix trie (a simple form of tree
+structure) to quota file.
+.SH OPTIONS
+.TP
+.B -u
+convert user quota file. This is default.
+.TP
+.B -g
+convert group quota file.
+.SH FILES
+.TP 20
+.B aquota.user
+user quota file
+.TP
+.B aquota.group
+group quota file
+.SH "SEE ALSO"
+.BR quota (1),
+.BR setquota (8),
+.BR edquota (8),
+.BR quotacheck (8),
+.BR quotaon (8),
+.BR repquota (8)
+.SH AUTHOR
+Jan Kara \<jack@atrey.karlin.mff.cuni.cz\>
+
diff --git a/convertquota.c b/convertquota.c
new file mode 100644
index 0000000..26f34e9
--- /dev/null
+++ b/convertquota.c
@@ -0,0 +1,136 @@
+/*
+ *
+ * Utility for converting quota file from old to new format
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <asm/byteorder.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quotaio.h"
+#include "quotasys.h"
+#include "quota.h"
+#include "bylabel.h"
+
+char *mntpoint;
+int ucv, gcv;
+struct quota_handle *qn; /* Handle of new file */
+
+void parse_options(int argcnt, char **argstr)
+{
+ int ret;
+ char *slash = strrchr(argstr[0], '/'), cmdname[PATH_MAX];
+
+ if (!slash)
+ slash = argstr[0];
+ else
+ slash++;
+ sstrncpy(cmdname, slash, sizeof(cmdname));
+ while ((ret = getopt(argcnt, argstr, "Vugh:")) != EOF) {
+ switch (ret) {
+ case '?':
+ case 'h':
+usage:
+ printf(_("Utility for converting quota files.\nUsage:\n%s [-u] [-g] mountpoint\n"), cmdname);
+ printf(_("Bugs to %s\n"), MY_EMAIL);
+ exit(1);
+ case 'V':
+ version();
+ exit(0);
+ case 'u':
+ ucv = 1;
+ break;
+ case 'g':
+ gcv = 1;
+ break;
+ }
+ }
+ if (optind + 1 != argcnt) {
+ puts(_("Bad number of arguments."));
+ goto usage;
+ }
+ if (!(ucv | gcv))
+ ucv = 1;
+ mntpoint = argstr[optind];
+}
+
+int convert_dquot(struct dquot *dquot)
+{
+ struct dquot newdquot;
+
+ memset(&newdquot, 0, sizeof(newdquot));
+ newdquot.dq_id = dquot->dq_id;
+ newdquot.dq_h = qn;
+ newdquot.dq_dqb.dqb_ihardlimit = dquot->dq_dqb.dqb_ihardlimit;
+ newdquot.dq_dqb.dqb_isoftlimit = dquot->dq_dqb.dqb_isoftlimit;
+ newdquot.dq_dqb.dqb_curinodes = dquot->dq_dqb.dqb_curinodes;
+ newdquot.dq_dqb.dqb_bhardlimit = dquot->dq_dqb.dqb_bhardlimit;
+ newdquot.dq_dqb.dqb_bsoftlimit = dquot->dq_dqb.dqb_bsoftlimit;
+ newdquot.dq_dqb.dqb_curspace = dquot->dq_dqb.dqb_curspace;
+ newdquot.dq_dqb.dqb_btime = dquot->dq_dqb.dqb_btime;
+ newdquot.dq_dqb.dqb_itime = dquot->dq_dqb.dqb_itime;
+ if (qn->qh_ops->commit_dquot(&newdquot) < 0) {
+ fprintf(stderr, _("Can't commit dquot for id %u: %s\n"), (uint)dquot->dq_id, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+void convert_file(int type)
+{
+ struct quota_handle *qo;
+ char *qfname, namebuf[PATH_MAX];
+ FILE *mntf;
+ struct mntent *mnt;
+ const char *dev;
+
+ if (!(mntf = setmntent(MOUNTED, "r")))
+ die(2, _("Can't open %s: %s\n"), MOUNTED, strerror(errno));
+ while ((mnt = getmntent(mntf))) {
+ if (!(dev = get_device_name(mnt->mnt_fsname)))
+ continue;
+ if (!strcmp(dev, mntpoint) || !strcmp(mnt->mnt_dir, mntpoint))
+ break;
+ }
+ if (!mnt)
+ die(1, _("Can't find given mountpoint %s\n"), mntpoint);
+ if (!(qo = init_io(mnt, type, QF_VFSOLD))) {
+ fprintf(stderr, _("Can't open old format file for %ss on %s\n"), type2name(type), mntpoint);
+ return;
+ }
+ if (!(qn = new_io(mnt, type, QF_VFSV0))) {
+ fprintf(stderr, _("Can't create file for %ss for new format on %s: %s\n"), type2name(type), mntpoint, strerror(errno));
+ end_io(qo);
+ return;
+ }
+ if (qo->qh_ops->scan_dquots(qo, convert_dquot) >= 0) { /* Conversion succeeded? */
+ qfname = get_qf_name(mnt, type, QF_VFSV0);
+ strcpy(namebuf, qfname);
+ sstrncat(namebuf, ".new", sizeof(namebuf));
+ if (rename(namebuf, qfname) < 0)
+ fprintf(stderr, _("Can't rename new quotafile %s to name %s: %s\n"), namebuf, qfname, strerror(errno));
+ free(qfname);
+ }
+ endmntent(mntf);
+ end_io(qo);
+ end_io(qn);
+}
+
+int main(int argcnt, char **argstr)
+{
+ parse_options(argcnt, argstr);
+ if (ucv)
+ convert_file(USRQUOTA);
+ if (ucv)
+ convert_file(GRPQUOTA);
+ return 0;
+}
+
diff --git a/doc/edquota(8).html b/doc/edquota(8).html
new file mode 100644
index 0000000..201f443
--- /dev/null
+++ b/doc/edquota(8).html
@@ -0,0 +1,96 @@
+<HTML>
+<HEAD>
+<TITLE>edquota(8) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+edquota - edit user quotas
+<H1>SYNOPSIS</H1>
+<B>edquota</B>
+[
+<B>-p</B>
+<B>proto-user</B>
+] [
+<B>-ug</B>
+]
+<B>name</B>
+<BR>
+<B>edquota</B>
+[
+<B>-ug</B>
+]
+<B>-t</B>
+<H1>DESCRIPTION</H1>
+<B>edquota</B>
+is a quota editor. One or more users or groups may be specified on the command
+line. For each user or group a temporary file is created with an
+<B>ASCII</B>
+representation of the current disk quotas for that user or group and an editor
+is then invoked on the file. The quotas may then be modified, new
+quotas added, etc. Upon leaving the editor,
+<B>edquota</B>
+reads the temporary file and modifies the binary quota files to reflect
+the changes made.
+<P>
+The editor invoked is
+<B>vi (1)</B>
+unless the
+<B>EDITOR</B>
+environment variable specifies otherwise.
+<P>
+Only the super-user may edit quotas. (In order for quotas to be
+established on a file system, the root directory of the file system must
+contain a file, owned by root, called
+<B>quota.user</B>
+or
+<B>quota.group</B>
+. See
+<A HREF="quotaon(8).html">quotaon (8)</A>
+for details.)
+<H1>OPTIONS</H1>
+<UL>
+<LI>
+<B>-u</B>
+<BR>
+Edit the userquota. This is the default.
+<LI>
+<B>-g</B>
+<BR>
+Edit the groupquota.
+<LI>
+<B>-p</B>
+<BR>
+Duplicate the quotas of the prototypical user specified for each user specified.
+This is the normal mechanism used to initialize quotas for groups of users.
+<LI>
+<B>-t</B>
+<BR>
+Edit the soft time limits for each file system. If the time limits are zero,
+the default time limits in &ltlinux/quota.h&gt are used. Time units of sec(onds),
+min(utes), hour(s), day(s), week(s), and month(s) are understood. Time limits
+are printed in the greatest possible time unit such that the value is greater
+than or equal to one.
+</UL>
+<H1>FILES</H1>
+<B>quota.user</B>
+ : located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+ : located at the filesystem root with group quotas
+<BR>
+<B>/etc/fstab</B>
+ : to find filesystem names and locations
+<H1>SEE ALSO</H1>
+<A HREF="quota(1).html">quota (1)</A>,
+<A HREF="quotactl(2).html">quotactl (2)</A>,
+<A HREF="fstab(5).html">fstab (5)</A>,
+<A HREF="quotacheck(8).html">quotacheck (8)</A>,
+<A HREF="quotaon(8).html">quotaon (8)</A>,
+<A HREF="repquota(8).html">repquota (8)</A>
+<H1>BUGS</H1>
+The format of the temporary file is inscrutable.
+</BODY>
+</HTML>
diff --git a/doc/fstab(5).html b/doc/fstab(5).html
new file mode 100644
index 0000000..e627015
--- /dev/null
+++ b/doc/fstab(5).html
@@ -0,0 +1,127 @@
+<HTML>
+<HEAD>
+<TITLE>fstab(5) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+fstab - static information about the filesystems
+<H1>SYNOPSIS</H1>
+#include <fstab.h>
+<H1>DESCRIPTION</H1>
+The file
+<B>fstab</B>
+contains descriptive information about the various file systems.
+<B>fstab</B>
+is only read by programs, and not written; it is the duty of the system
+administrator to properly create and maintain this file. Each filesystem
+is described on a separate line; fields on each line are separated by tabs
+or spaces. The order of records in
+<B>fstab</B>
+is important because fsck (8), mount (8), and umount (8) sequentially iterate through
+<B>fstab</B>
+doing their thing.
+<P>
+The first field,
+<B>fs_spec</B>
+describes the block special device or remote filesystem to be mounted.
+<P>
+The second field,
+<B>fs_file</B>
+describes the mount point for the filesystem. For swap partitions, this
+field should be specified as ``none''.
+<P>
+The third field,
+<B>fs_vfstype</B>
+describes the type of the filesystem. The system currently supports three
+types of filesystems:
+<UL>
+<LI>
+<B>minix</B>
+<BR>
+a local filesystem, supporting filenames of length 14 or 30 characters.
+<LI>
+<B>ext</B>
+<BR>
+a local filesystem with longer filenames and larger inodes. This
+filesystem has been replaced by the
+<B>ext2</B>
+file system, and should no longer be used.
+<LI>
+<B>ext2</B>
+<BR>
+a local filesystem with longer filenames, larger inodes, and lots of other
+features.
+<LI>
+<B>xiafs</B>
+<BR>
+a local filesystem with longer filenames, larger inodes, and lots of other
+features.
+<LI>
+<B>msdos</B>
+<BR>
+a local filesystem for MS-DOS partitions.
+<LI>
+<B>hpfs</B>
+<BR>
+a local filesystem for HPFS partitions.
+<LI>
+<B>iso9660</B>
+<BR>
+a local filesystem used for CD-ROM drives.
+<LI>
+<B>nfs</B>
+<BR>
+a filesystem for mounting partitions from remote systems.
+<LI>
+<B>swap</B>
+<BR>
+a disk partition to be used for swapping.
+</UL>
+<P>
+If
+<B>vfs_fstype</B>
+is specified as ``ignore'' the entry is ignored. This is useful to show
+disk partitions which are currently unused.
+<P>
+The fourth field,
+<B>fs_mntops</B>
+describes the mount options associated with the filesystem.
+It is formatted as a comma separated list of options. It contains at least
+the type of mount plus any additional options appropriate to the filesystem
+type. For documentation on all of the available options, see mount (8).
+<P>
+The fifth field,
+<B>fs_freq</B>
+is used for these filesystems by the dump (8) command to determine which
+filesystems need to be dumped. If the fifth field is not present, a value
+of zero is returned and dump will assume that the filesystem does not need
+to be dumped.
+<P>
+The sixth field,
+<B>fs_passno</B>
+is used by the fsck (8) program to determine the order in which filesystem
+checks are done at reboot time. The root filesystem should be specified
+with a
+<B>fs_passno</B>
+of 1, and other filesystems should have a
+<B>fs_passno</B>
+of 2. Filesystems within a drive will be checked sequentially, but
+filesystems on different drives will be checked at the same time to utilize
+parallelism available in the hardware. If the sixth field is not present
+or zero, a value of zero is returned and fsck will assume that the filesystem
+does not need to be checked.
+<P>
+The proper way to read records from
+<B>fstab</B>
+is to use the routines getmntent (3).
+<H1>FILES</H1>
+<B>/etc/fstab</B>
+resides in
+<B>/etc</B>
+<H1>SEE ALSO</H1>
+getmntent (3), mount (8), swapon (8)
+</BODY>
+</HTML>
diff --git a/doc/quota(1).html b/doc/quota(1).html
new file mode 100644
index 0000000..77f8242
--- /dev/null
+++ b/doc/quota(1).html
@@ -0,0 +1,92 @@
+<HTML>
+<HEAD>
+<TITLE>quota(1) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+quota - display disk usage and limits
+<H1>SYNOPSIS</H1>
+quota [
+<B>-guv | q</B>
+]
+<BR>
+quota [
+<B>-uv | q</B>
+] user
+<BR>
+quota [
+<B>-gv | q</B>
+] group
+<H1>DESCRIPTION</H1>
+<B>Quota</B>
+displays users' disk usage and limits.
+By default only the user quotas are printed.
+<UL>
+<LI>
+<B>-g</B>
+<BR>
+Print group quotas for the group of which the user is a member. The optional
+<LI>
+<B>-u</B>
+<BR>
+flag is equivalent to the default.
+<LI>
+<B>-v</B>
+<BR>
+will display quotas on filesystems where no storage is allocated.
+<LI>
+<B>-q</B>
+<BR>
+Print a more terse message, containing only information
+on filesystems where usage is over quota.
+</UL>
+Specifying both
+<B>-g</B>
+and
+<B>-u</B>
+displays both the user quotas and the group quotas (for the user).
+<P>
+Only the super-user may use the
+<B>-u</B>
+flag and the optional
+<B>user</B>
+argument to view the limits of other users. Non-super-users can use the the
+<B>-g</B>
+flag and optional
+<B>group</B>
+argument to view only the limits of groups of which they are members.
+<P>
+The
+<B>-q</B>
+flag takes precedence over the
+<B>-v</B>
+flag.
+<P>
+<B>Quota</B>
+reports the quotas of all the filesystems listed in
+<B>/etc/fstab.</B>
+For filesystems that are NFS-mounted a call to the rpc.rquotad on
+the server machine is performed to get the information. If
+<B>quota</B>
+exits with a non-zero status, one or more filesystems are over quota.
+<H1>FILES</H1>
+<B>quota.user</B>
+ : located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+ : located at the filesystem root with group quotas
+<BR>
+<B>/etc/fstab</B>
+ : to find filesystem names and locations
+<H1>SEE ALSO</H1>
+<A HREF="quotactl(2).html">quotactl (2)</A>,
+<A HREF="fstab(5).html">fstab (5)</A>,
+<A HREF="edquota(8).html">edquota (8)</A>,
+<A HREF="quotacheck(8).html">quotacheck (8)</A>,
+<A HREF="quotaon(8).html">quotaon (8)</A>,
+<A HREF="repquota(8).html">repquota (8)</A>
+</BODY>
+</HTML>
diff --git a/doc/quota.html b/doc/quota.html
new file mode 100644
index 0000000..2e86b5c
--- /dev/null
+++ b/doc/quota.html
@@ -0,0 +1,288 @@
+<HTML>
+<HEAD>
+<TITLE>Linux DiskQuota system</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>General</H1>
+<P>
+In most computing environments, disc space is not infinite. The
+diskquota system provides a mechanism to control usage of disc space,
+on an individual basis. Quotas may be set for each individual user, on
+any, or all filesystems. The quota system will warn users when they
+exceed their allotted limit, but allow some extra space for current work.
+Repeatedly remaining over quota at logout, will cause a fatal over quota
+condition eventually. The quota system is an optional part of LINUX that
+may be included when the system is configured. This document will describe
+from what view the
+<A HREF="#USERVIEW">Users</A>
+will see the quota-system and the way the quota-system can be configured
+by the
+<A HREF="#ADMINISTERING">System Administator</A>
+.
+<P>
+<A NAME="USERVIEW"><H1>Users' view of diskquotas</H1></A>
+<H2>General</H2>
+To most users, diskquotas will either be of no concern, or a fact of life
+that cannot be avoided. The
+<A HREF="quota(1).html">quota(1)</A>
+command will provide information on
+any disc quotas that may have been imposed upon a user.
+<P>
+There are two individual possible quotas that may be imposed, usually if
+one is, both will be. 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.
+Quota provides information on the quotas that have been set by the system
+administrators, in each of these areas, and current usage. The inode limit and
+block limit are impossed both on uid and on gid. So if there are group quotas
+you can be limited because the group can't allocate any more space even if you
+as user still can allocate the space.
+<P>
+There are four numbers for each limit, the current usage, soft limit (quota),
+hard limit, and time remaining bfore the softlimit is intepretted as a hard
+limit. The soft limit is the number of 1K blocks (or files) that the user is
+expected to remain below. Each time the user's usage goes past this limit, he
+will be warned. The hard limit cannot be exceeded. If a user's usage reaches
+this number, further requests for space (or attempts to create a file) will
+fail with an EDQUOT error, and the first time this occurs, a message will
+be written to the user's terminal. Only one message will be output, until space
+occupied is reduced below the limit, and reaches it again, in order to avoid
+continual noise from those programs that ignore write errors.
+<P>
+When a use exeeds his softlimit a timer is set that normaly expires wuthin
+7 days (1 week). The user can remove files in this period to make sure he is
+under the softlimit again before the timer expires. When the timer expires the
+particular limit that has been exceeded will be treated as if the hard limit
+has been reached, and no more resources will be allocated to the user. The only
+way to reset this condition is to reduce usage below the softlimit.
+<P>
+<H2>Surviving when quota limit is reached</H2>
+In most cases, the only way to recover from over quota conditions, is to abort
+whatever activity was 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.
+<P>
+However, if you are in the editor and a write fails because of an over quota
+situation, that is not a suitable course of action, as it is most likely that
+initially attempting to write the file will have truncated its previous
+contents, so should the editor be aborted without correctly writing the file
+not only will the recent changes be lost, but possibly much, or even all, of
+the data that previously existed.
+<P>
+There are several possible safe exits for a user caught in this situation.
+He may use the editor ! shell escape command to examine his file space, and
+remove surplus files. Alternatively, using csh, he may 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.
+<A NAME="ADMINISTERING"><H1>Administering the quota system</H1></A>
+To set up and establish the diskquota system, there are several steps necessary
+to be performed by the system administrator. The following steps must be taken:
+<UL>
+<LI>
+<A HREF="#KERNEL">Kernel configuration</A>
+<LI>
+<A HREF="#ELECTING">Electing filesystems</A>
+<LI>
+<A HREF="#ENABLING">Enabling quotas</A>
+<LI>
+<A HREF="#CHECKING">Checking a filesystem for quotas</A>
+<LI>
+<A HREF="#SPECIFYING">Specifing a quota for a user or group</A>
+<LI>
+<A HREF="#CHECKING">Checking quotas for a user or group</A>
+<LI>
+<A HREF="#DISABLING">Disabling quota for a user or group</A>
+<LI>
+<A HREF="#NFS">Quotas on NFS-mounted disks</A>
+</UL>
+<A NAME="KERNEL"><H2>Kernel configuration</H2></A>
+Before you can use the quota-system you must compile a kernel
+with the quota-system enabled. This is done by answering yes
+to the Disk QUOTA support question when running <make config>. Then
+run <make> and install the new kernel images as the one that is booted
+at boottime.
+<A NAME="ELECTING"><H2>Electing filesystems</H2></A>
+When you have a kernel that supports quota you need to make a decision as to what
+filesystems need to have quotas applied. Usually, only filesystems that house
+users' home directories, or other user files, will need to be subjected to the
+quota system, though it may also prove useful to also include /usr if its writable
+by normal users.
+<P>
+To enable quotas on a certain filesystem one should edit the /etc/fstab
+file and add entries for usrquota and grpquota. Mine looks like :
+<PRE>
+# device directory type options
+/dev/hda1 / ext2 defaults
+/dev/hda2 none swap sw
+/dev/hda3 /usr ext2 defaults
+/dev/hdb1 /usr/users ext2 defaults,usrquota,grpquota
+/dev/hdb2 /usr/src ext2 defaults,usrquota
+none /proc proc defaults
+</PRE>
+The keyword "usrquota" in the options field of each fstab-entry turns on
+userquota for this device. The keyword "grpquota" in the options field turns
+on groupquota for the device. When you use the usrquota and grpquota options
+without the "=" option you quotafiles are located in the rootdir of each
+filesystem. A file called "quota.user" is used for userquota and a file called
+"quota.group" is used for groupquota.
+<P>
+You can also define your quotafile yourself. Something like
+"usrquota=/usr/adm/quotasrc.user" puts the quotafile in /usr/adm with the
+name quotasrc.user. Please be aware of the maximum lenght a line can have
+in your fstab, see
+<B>mntent.h</B>
+for a definition.
+<P>
+<A NAME="ENABLING"><H2>Enabling quotas</H2></A>
+Periodically (certainly after each unclean 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
+<A HREF="quotacheck(8).html">quotacheck(8)</A>
+command can be used to accomplish this. It is
+not necessary to dismount 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 will certainly correct any inaccuracy.
+<P>
+To check the filesystem for the actual number of blocks used by a user run
+<KBD>quotacheck -avug</KBD>
+to install or update all the quotafiles.
+<P>
+The quotacheck program takes some time on large filesystems, but whith the
+new version it is quite acceptable on my machine. But when you are hacking
+the kernel, I recommend not to use it because it takes some time every time
+you have to reboot your machine. You also can also put it in you rc script
+and run it like you run fsck on your filesystems only when the fastreboot
+flag is not set. There is no support for parallel checking of filesystems.
+<P>
+Ok now one should have all the quotafiles one needs.
+Now you can add a line like:
+<KBD>/usr/etc/quotaon -avug</KBD>
+<P>
+to your /etc/rc. This is to turn the quotas on when you boot your machine.
+This is they way to go and not turn it on yourself any time when you boot
+your machine.
+<A NAME="CHECKING"><H2>Checking a filesystem for quotas</H2></A>
+The super-user may use the
+<A HREF="quota(1).html">quota (1)</A>
+command to examine the usage and quotas
+of any user, and the
+<A HREF="repquota(8).html">repquota (8)</A>
+command may be used to check the usages and
+limits for all users on a filesystem. Just run
+<KBD>quotacheck -avug</KBD>
+and the quotafiles are updated automagicaly and also the tables that are
+currently used by the kernel. Watch for the "updating in core quotas" message
+of the
+<A HREF="quotacheck(8).html">quotacheck (8)</A>
+program this says if it updates the in core quotas in the kernel.
+<P>
+I cannot state this enough the quotafile is build as (uid || gid *
+sizeof(struct dquot)) so when you have nobody as uid 65535 and nobody owns a
+file you get big quota files, lets say of about 2 Mb all filed with zero's
+for users that don't have quota. So please be aware of that and don't mail
+me about that. It isn't much of a problem because the file isn't that big
+really all 0 blocks are not allocated on the disk.
+<A NAME="SPECIFYING"><H2>Specifing a quota for a user or group</H2></A>
+To edit the quotas for various users we use the
+<A HREF="edquota(8).html">edquota (8)</A> program. Now use
+<KBD>edquota -u <username | uid></KBD>
+to edit user quotas and
+<KBD>edquota -g <groupname | gid></KBD>
+to edit group quotas.
+<P>
+Edit only the numbers behind the soft and hard keywords. There are two lines
+for each filesystem that has quota turned on. Soft means the softlimit, if
+people or groups go over there softlimit they have some grace period to make
+sure they go under there softlimit.
+<P>
+The graceperiod can be changed with
+<KBD>edquota -t</KBD>
+and enter the number of days there. If they don't remove it within there graceperiod
+it is counted as a hardlimit. The hardlimit is the absolute maximum they can allocate,
+if they want more the files are truncated.
+<P>
+The one line that says blocks is the number of blocks one can allocate,
+the line that says inodes is the number of inodes
+(files/named pipes/devices/etc.) one can allocate.
+<P>
+Most of the time you have groups of users with the same quota. A quick way of editing
+the quota for all those users is change to the dir where there homedirs reside. Do a
+edquota for one of the users and change the quotas to the approriate values. This user
+becomes the so called prototype user or group for all the others. Then execute
+<KBD>edquota -p prototypeusername *</KBD>
+this should do the trick, all users now have the quota they need, now
+you could edit the ones that still need other values.
+<A NAME="CHECKING"><H2>Checking quotas for a user or group</H2></A>
+Run the quota program. The syntax for this program is :
+<PRE>
+quota [-guqv]
+quota [-qv] -u username ...
+quota [-qv] -g groupname ...
+</PRE>
+Use -v to see the quotas on
+<UL>
+<LI>
+filesystems you don't have quotas on
+<LI>
+filesystems on which you do have quota but haven't allocated any blocks yet
+</UL>
+Use -q to only see filesystems on which you are over your softlimit or
+have reached your hardlimit.
+<P>
+The -g flags give you all quotas for the groups you are in (also
+additional groups).
+<A NAME="DISABLING"><H2>Disabling quota for a user or group</H2></A>
+When you want to disable quotas for a certain user use the quota editor
+edquota. Type
+<KBD>edquota username | uid</KBD>
+or
+<KBD>edquota -g groupname | gid</KBD>
+and set block softlimit and hardlimit, and the inode soft- and hardlimit to 0.
+This should disable the quota for that user an the user can allocate as many
+blocks and inodes as he/she wants.
+<A NAME="NFS"><H2>Quotas on NFS-mounted disks</H2></A>
+To have quotas on NFS filesystems, you need to install quotas on the
+fileserver and not on the client. Clients can obtain quota information
+with the quota command which does a query to the
+<A HREF="rquotad(8).html">rquotad (8)</A>
+running on the fileserver from which you mount your NFS disks. So don't put any
+usrquota or grpquota flags in the flags for mounting NFS disks. Instead install
+quotas on your fileserver. And start the rpc.rquotad from your network rc-file.
+<H1>Some implementation details</H2>
+Diskquota usage and information is stored in a file on the filesystem that the
+quotas are to be applied to. Conventionally, this file is quota.user or quota.group
+in the root of the filesystem.
+<P>
+The data in the file comprises an array of structures, indexed by uid or gid, one
+structure for each user or group on the system (whether the user or group has a
+quota on this filesystem or not). If the uid or gid space is sparse, then the
+file may have holes in it, which would be lost by copying, so it is best to avoid
+this.
+<P>
+The system is informed of the existence of the quota file by the
+<A HREF="quotactl(2).html">quotactl (2)</A>
+system call. It then reads the quota entries for each user or group currently
+active, then for any files open owned by users who are not currently active.
+Each subsequent open of a file on the filesystem, will be accompanied by a
+pairing with its quota information. In most cases this information will be
+retained in core, either because the user who owns the file is running some
+process, because other files are open owned by the same user, or because
+some file (perhaps this one) was recently accessed. In memory, the quota
+information is kept hashed by uid or group and filesystem, and retained in
+an LRU chain so recently released data can be easily reclaimed. Information
+about those users whose last process has recently terminated is also retained
+in this way.
+<P>
+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 object. Measurements have shown that the quota code
+uses a very small percentage of the system cpu time consumed in writing a new
+block to disk.
+</BODY>
+</HTML>
diff --git a/doc/quota4th.fig b/doc/quota4th.fig
new file mode 100644
index 0000000..cd4fc9b
--- /dev/null
+++ b/doc/quota4th.fig
@@ -0,0 +1,62 @@
+#FIG 2.1
+80 2
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 199 119 199 79 79 79 79 119 199 119 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 759 119 759 79 639 79 639 119 759 119 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 759 199 759 159 639 159 639 199 759 199 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 199 199 199 159 79 159 79 199 199 199 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 139 159 139 119 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 699 159 699 119 9999 9999
+2 1 0 4 -1 0 0 0 0.000 -1 0 0
+ 39 259 854 259 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 379 119 379 79 259 79 259 119 379 119 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 379 199 379 159 259 159 259 199 379 199 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 579 199 579 159 459 159 459 199 579 199 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 579 119 579 79 459 79 459 119 579 119 9999 9999
+2 2 0 1 -1 0 0 0 0.000 0 0 0
+ 519 359 359 359 359 319 519 319 519 359 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 359 339 139 339 139 199 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 519 339 699 339 699 199 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 379 319 379 299 219 299 219 99 259 99 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 419 319 419 279 239 279 239 179 259 179 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 499 319 499 299 619 299 619 99 579 99 9999 9999
+2 1 0 1 -1 0 0 0 0.000 -1 1 0
+ 0 0 1.000 4.000 8.000
+ 459 319 459 279 599 279 599 179 579 179 9999 9999
+4 0 2 14 0 -1 0 0.00000 4 18 115 259 99 DQUOT_ALLOC_
+4 0 2 14 0 -1 0 0.00000 4 18 48 259 114 INODE
+4 0 2 14 0 -1 0 0.00000 4 18 115 259 179 DQUOT_ALLOC_
+4 0 2 14 0 -1 0 0.00000 4 18 51 259 194 BLOCK
+4 0 2 14 0 -1 0 0.00000 4 18 107 464 99 DQUOT_FREE_
+4 0 2 14 0 -1 0 0.00000 4 18 48 464 114 INODE
+4 0 2 14 0 -1 0 0.00000 4 18 111 459 174 DQUOT_FREE_
+4 0 2 14 0 -1 0 0.00000 4 18 51 459 196 BLOCK
+4 0 2 14 0 -1 0 0.00000 4 18 88 19 59 VFS-LAYER
+4 0 2 14 0 -1 0 0.00000 4 18 96 19 299 FILESYSTEM
+4 0 2 14 0 -1 0 0.00000 4 18 141 374 339 FILESYSTEM OPER
+4 0 2 14 0 -1 0 0.00000 4 18 52 104 99 DQGET
+4 0 2 14 0 -1 0 0.00000 4 18 36 99 179 IGET
+4 0 2 14 0 -1 0 0.00000 4 18 34 659 179 IPUT
+4 0 2 14 0 -1 0 0.00000 4 18 50 659 99 DQPUT
+4 0 2 14 0 -1 0 0.00000 4 18 317 319 39 DISKQUOTAS FOR LINUX (4th GENERATION)
diff --git a/doc/quotacheck(8).html b/doc/quotacheck(8).html
new file mode 100644
index 0000000..2a3cf66
--- /dev/null
+++ b/doc/quotacheck(8).html
@@ -0,0 +1,94 @@
+<HTML>
+<HEAD>
+<TITLE>quotacheck(8) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+quotacheck - scan a file system for disk usages
+<H1>SYNOPSIS</H1>
+<B>quotacheck</B>
+[-g] [-u] [-v] -a
+<BR>
+<B>quotacheck</B>
+[-g] [-u] [-v] filesys ...
+<H1>DESCRIPTION</H1>
+<B>Quotacheck</B>
+performs a filesystems scan for usage of files and directories, used
+by either user or group. The output is the quota file for the
+corresponding filesystem. By default the names for these files are:
+<UL>
+<LI>
+A user scan:
+<B>quota.user</B>
+<LI>
+A group scan:
+<B>quota.group</B>
+</UL>
+<P>
+The resulting file consist of a
+<B>struct dqblk</B>
+for each possible id up to the highest existing uid or gid and contains the
+values for the disk file and block usage and possibly excess time for these
+values. ( for definitions of
+<B>struct dqblk</B>
+see
+<B>&ltlinux/quota.h&gt</B>
+)
+<P>
+<B>Quotacheck</B>
+should be run each time the system boots and mounts non-valid file systems.
+This is most likely to happen after a system crash.
+<P>
+The speed of the scan decrease with the amount of directories increasing.
+The time needed doubles when disk usage is doubled as well. A 100 MB partition
+used for 94% is scanned in 1 minute, the same partition used for 50% is
+done in 25 seconds.
+<H1>OPTIONS</H1>
+<UL>
+<LI>
+<B>-v</B>
+<BR>
+This way the program will give some usefull information about what it is
+doing, plus some fancy stuff.
+<LI>
+<B>-d</B>
+<BR>
+This means debug. It will result in a lot of information which can be used
+in debugging the program. The output is very verbose and the scan
+will not be fast.
+<LI>
+<B>-u</B>
+<BR>
+This flag tells the program to scan the disk and to count the files and
+directories used by a certain uid. This is the default action.
+<LI>
+<B>-g</B>
+<BR>
+This flag forces the program to count the the files and directories
+used by a certain gid.
+</UL>
+<H1>NOTE</H1>
+<B>Quotacheck</B>
+should only be run as Super User. Non-privilidged users are presumably not allowed
+to read all the directories on the given file system.
+<H1>FILES</H1>
+<B>quota.user</B>
+located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+located at the filesystem root with group quotas
+<BR>
+<B>/etc/fstab</B>
+to find filesystem names and locations
+<H1>SEE ALSO</H1>
+<A HREF="quota(1).html">quota (1)</A>,
+<A HREF="quotactl(2).html">quotactl (2)</A>,
+<A HREF="fstab(5).html">fstab (5)</A>,
+<A HREF="edquota(8).html">edquota (8)</A>,
+<A HREF="quotaon(8).html">quotaon (8)</A>,
+<A HREF="repquota(8).html">repquota (8)</A>
+</BODY>
+</HTML>
diff --git a/doc/quotactl(2).html b/doc/quotactl(2).html
new file mode 100644
index 0000000..63dc934
--- /dev/null
+++ b/doc/quotactl(2).html
@@ -0,0 +1,197 @@
+<HTML>
+<HEAD>
+<TITLE>quotactl(2) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+quotactl - manipulate disk quotas
+<H1>SYNOPSIS</H1>
+<B>#include &ltlinux/quota.h&gt</B>
+<P>
+<B>int quotactl(cmd, special, uid, addr)
+<BR>
+int cmd;
+<BR>
+char **special;
+<BR>
+int id;
+<BR>
+caddr_t addr;</B>
+<H1>DESCRIPTION</H1>
+The
+<B>quotactl</B>
+call manipulates disk quotas.
+<B>cmd</B>
+indicates a command to be applied to
+<B>UID id</B>
+or
+<B>GID id</B>
+. To set the type of quota use the
+<B>QCMD(cmd, type)</B>
+macro.
+<P>
+<B>Special</B>
+is a pointer to a null-terminated string containing the path
+name of the block special device for the file system being manipulated.
+<P>
+<B>Addr</B>
+is the address of an optional, command specific, data structure
+which is copied in or out of the system. The interpretation of
+<B>addr</B>
+is given with each command below.
+<UL>
+<LI>
+<B>Q_QUOTAON</B>
+<BR>
+Turn on quotas for a file system.
+<B>addr</B>
+points to the path name of file containing the quotas for the file system.
+The quota file must exist; it is normally created with the
+<A HREF="quotacheck(8).html">quotacheck (8)</A>
+program. This call is restricted to the super-user.
+<LI>
+<B>Q_QUOTAOFF</B>
+<BR>
+Turn off quotas for a file system.
+<B>addr</B>
+and
+<B>id</B>
+are ignored.
+This call is restricted to the super-user.
+<LI>
+<B>Q_GETQUOTA</B>
+<BR>
+Get disk quota limits and current usage for user or group
+<B>id</B>
+.
+<B>Addr</B>
+is a pointer to a
+<B>dqblk</B>
+structure (defined in
+<B>&ltlinux/quota.h&gt</B>
+).
+Only the super-user may get the quotas of a user other than himself.
+<LI>
+<B>Q_SETQUOTA</B>
+<BR>
+Set disk quota limits and current usage for user or group
+<B>id</B>
+.
+<B>Addr</B>
+is a pointer to a
+<B>dqblk</B>
+structure (defined in
+<B>&ltlinux/quota.h&gt</B>
+).
+This call is restricted to the super-user.
+<LI>
+<B>Q_SETQLIM</B>
+<BR>
+Set disk quota limits for user or group
+<B>id</B>
+.
+<B>Addr</B>
+is a pointer to a
+<B>dqblk</B>
+structure (defined in
+<B>&ltlinux/quota.h&gt</B>
+).
+This call is restricted to the super-user.
+<LI>
+<B>Q_SYNC</B>
+<BR>
+Update the on-disk copy of quota usages for a file system.
+If
+<B>special</B>
+is null then all file systems with active quotas are sync'ed.
+<B>Addr</B>
+and
+<B>id</B>
+are ignored.
+</UL>
+<H1>RETURN VALUES</H1>
+<B>quotactl</B>
+returns:
+<UL>
+<LI>
+0 on success.
+<LI>
+-1 on failure and sets
+<B>errno</B>
+to indicate the error.
+</UL>
+<H1>ERRORS</H1>
+<UL>
+<LI>
+<B>EFAULT</B>
+<BR>
+<B>addr</B>
+or
+<B>special</B>
+are invalid.
+<LI>
+<B>EINVAL</B>
+<BR>
+The kernel has not been compiled with the
+<B>QUOTA</B>
+option or
+<B>cmd</B>
+is invalid.
+<LI>
+<B>ENOENT</B>
+<BR>
+The file specified by
+<B>special</B>
+or
+<B>addr</B>
+does not exist.
+<LI>
+<B>ENOTBLK</B>
+<BR>
+<B>special</B>
+is not a block device.
+<LI>
+<B>EPERM</B>
+<BR>
+The call is privileged and the caller was not the super-user.
+<LI>
+<B>ESRCH</B>
+<BR>
+No disc quota is found for the indicated user.
+<BR>
+Quotas have not been turned on for this file system.
+<LI>
+<B>EUSERS</B>
+<BR>
+The quota table is full.
+</UL>
+<P>
+If
+<B>cmd</B>
+is
+<B>Q_QUOTAON quotactl</B>
+may set errno to:
+<UL>
+<LI>
+<B>EACCES</B>
+<BR>
+The quota file pointed to by
+<B>addr</B>
+exists but is not a regular file.
+<LI>
+<B>EBUSY</B>
+<BR>
+<B>Q_QUOTAON</B>
+attempted while another
+<B>Q_QUOTAON</B>
+has already taken place.
+</UL>
+<H1>SEE ALSO</H1>
+<A HREF="quota(1).html">quota (1)</A>,
+<A HREF="quotacheck(8).html">quotacheck (8)</A>,
+<A HREF="quotaon(8).html">quotaon (8)</A>,
+</BODY>
+</HTML>
diff --git a/doc/quotaon(8).html b/doc/quotaon(8).html
new file mode 100644
index 0000000..f384c24
--- /dev/null
+++ b/doc/quotaon(8).html
@@ -0,0 +1,80 @@
+<HTML>
+<HEAD>
+<TITLE>quotaon(8) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+quotaon, quotaoff - turn file system quotas on and off
+<H1>SYNOPSIS</H1>
+<B>quotaon</B>
+[
+<B>-vug</B>
+]
+<B>filesystem</B>
+<BR>
+<B>quotaon</B>
+[
+<B>-avug</B>
+]
+<P>
+<B>quotaoff</B>
+[
+<B>-vug</B>
+]
+<B>filesystem</B>
+<BR>
+<B>quotaoff</B>
+[
+<B>-avug</B>
+]
+<H1>DESCRIPTION</H1>
+<B>quotaon</B>
+announces to the system that disk quotas should be enabled on one or
+more file systems. The file system quota files must be present in the root
+directory of the specified file system and be named
+<B>quota.user</B>
+for userquota or
+<B>quota.group</B>
+for groupquota.
+<P>
+<B>quotaoff</B>
+announces to the system that file systems specified should have any disk quotas turned off.
+<H1>OPTIONS</H1>
+<UL>
+<LI>
+<B>-a</B>
+<BR>
+All file systems in
+<B>/etc/fstab</B>
+marked read-write with quotas will have their quotas turned on. This is normally used at
+boot time to enable quotas.
+<LI>
+<B>-v</B>
+<BR>
+Display a message for each file system where quotas are turned on.
+<LI>
+<B>-u</B>
+<BR>
+Manupulate user quotas. This is the default.
+<LI>
+<B>-g</B>
+<BR>
+Manupulate group quotas.
+</UL>
+<H1>FILES</H1>
+<B>quota.user</B>
+ : located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+ : located at the filesystem root with group quotas
+<BR>
+<B>/etc/fstab</B>
+ : to find filesystem names and locations
+<H1>SEE ALSO</H1>
+<A HREF="quotactl(2).html">quotactl (2)</A>,
+<A HREF="fstab(5).html">fstab (5)</A>
+</BODY>
+</HTML>
diff --git a/doc/quotas-1.eps b/doc/quotas-1.eps
new file mode 100644
index 0000000..84a858d
--- /dev/null
+++ b/doc/quotas-1.eps
@@ -0,0 +1,3716 @@
+%!PS-Adobe-3.0 EPSF-2.0
+%%Creator: Windows PSCRIPT
+%%Title: PowerPoint - QUOTAS.PPT
+%%DocumentNeededResources: (atend)
+%%DocumentSuppliedResources: (atend)
+%%Pages: 0
+%%BeginResource: procset Win35Dict 3 1
+%%BoundingBox: 10 13 832 577
+%%EndComments
+%%BeginProcSet: epsffit 1 0
+gsave
+842.000 0.000 translate
+90 rotate
+1.000 1.000 scale
+%%EndProcSet
+/Win35Dict 290 dict def Win35Dict begin/bd{bind def}bind def/in{72
+mul}bd/ed{exch def}bd/ld{load def}bd/tr/translate ld/gs/gsave ld/gr
+/grestore ld/M/moveto ld/L/lineto ld/rmt/rmoveto ld/rlt/rlineto ld
+/rct/rcurveto ld/st/stroke ld/n/newpath ld/sm/setmatrix ld/cm/currentmatrix
+ld/cp/closepath ld/ARC/arcn ld/TR{65536 div}bd/lj/setlinejoin ld/lc
+/setlinecap ld/ml/setmiterlimit ld/sl/setlinewidth ld/scignore false
+def/sc{scignore{pop pop pop}{0 index 2 index eq 2 index 4 index eq
+and{pop pop 255 div setgray}{3{255 div 3 1 roll}repeat setrgbcolor}ifelse}ifelse}bd
+/FC{bR bG bB sc}bd/fC{/bB ed/bG ed/bR ed}bd/HC{hR hG hB sc}bd/hC{
+/hB ed/hG ed/hR ed}bd/PC{pR pG pB sc}bd/pC{/pB ed/pG ed/pR ed}bd/sM
+matrix def/PenW 1 def/iPen 5 def/mxF matrix def/mxE matrix def/mxUE
+matrix def/mxUF matrix def/fBE false def/iDevRes 72 0 matrix defaultmatrix
+dtransform dup mul exch dup mul add sqrt def/fPP false def/SS{fPP{
+/SV save def}{gs}ifelse}bd/RS{fPP{SV restore}{gr}ifelse}bd/EJ{gsave
+showpage grestore}bd/#C{userdict begin/#copies ed end}bd/FEbuf 2 string
+def/FEglyph(G )def/FE{1 exch{dup 16 FEbuf cvrs FEglyph exch 1 exch
+putinterval 1 index exch FEglyph cvn put}for}bd/SM{/iRes ed/cyP ed
+/cxPg ed/cyM ed/cxM ed 72 100 div dup scale dup 0 ne{90 eq{cyM exch
+0 eq{cxM exch tr -90 rotate -1 1 scale}{cxM cxPg add exch tr +90 rotate}ifelse}{cyP
+cyM sub exch 0 ne{cxM exch tr -90 rotate}{cxM cxPg add exch tr -90
+rotate 1 -1 scale}ifelse}ifelse}{pop cyP cyM sub exch 0 ne{cxM cxPg
+add exch tr 180 rotate}{cxM exch tr 1 -1 scale}ifelse}ifelse 100 iRes
+div dup scale 0 0 transform .25 add round .25 sub exch .25 add round
+.25 sub exch itransform translate}bd/SJ{1 index 0 eq{pop pop/fBE false
+def}{1 index/Break ed div/dxBreak ed/fBE true def}ifelse}bd/ANSIVec[
+16#0/grave 16#1/acute 16#2/circumflex 16#3/tilde 16#4/macron 16#5/breve
+16#6/dotaccent 16#7/dieresis 16#8/ring 16#9/cedilla 16#A/hungarumlaut
+16#B/ogonek 16#C/caron 16#D/dotlessi 16#27/quotesingle 16#60/grave
+16#7C/bar 16#82/quotesinglbase 16#83/florin 16#84/quotedblbase 16#85
+/ellipsis 16#86/dagger 16#87/daggerdbl 16#88/circumflex 16#89/perthousand
+16#8A/Scaron 16#8B/guilsinglleft 16#8C/OE 16#91/quoteleft 16#92/quoteright
+16#93/quotedblleft 16#94/quotedblright 16#95/bullet 16#96/endash 16#97
+/emdash 16#98/tilde 16#99/trademark 16#9A/scaron 16#9B/guilsinglright
+16#9C/oe 16#9F/Ydieresis 16#A0/space 16#A1/exclamdown 16#A4/currency
+16#A5/yen 16#A6/brokenbar 16#A7/section 16#A8/dieresis 16#A9/copyright
+16#AA/ordfeminine 16#AB/guillemotleft 16#AC/logicalnot 16#AD/hyphen
+16#AE/registered 16#AF/macron 16#B0/degree 16#B1/plusminus 16#B2/twosuperior
+16#B3/threesuperior 16#B4/acute 16#B5/mu 16#B6/paragraph 16#B7/periodcentered
+16#B8/cedilla 16#B9/onesuperior 16#BA/ordmasculine 16#BB/guillemotright
+16#BC/onequarter 16#BD/onehalf 16#BE/threequarters 16#BF/questiondown
+16#C0/Agrave 16#C1/Aacute 16#C2/Acircumflex 16#C3/Atilde 16#C4/Adieresis
+16#C5/Aring 16#C6/AE 16#C7/Ccedilla 16#C8/Egrave 16#C9/Eacute 16#CA
+/Ecircumflex 16#CB/Edieresis 16#CC/Igrave 16#CD/Iacute 16#CE/Icircumflex
+16#CF/Idieresis 16#D0/Eth 16#D1/Ntilde 16#D2/Ograve 16#D3/Oacute 16#D4
+/Ocircumflex 16#D5/Otilde 16#D6/Odieresis 16#D7/multiply 16#D8/Oslash
+16#D9/Ugrave 16#DA/Uacute 16#DB/Ucircumflex 16#DC/Udieresis 16#DD/Yacute
+16#DE/Thorn 16#DF/germandbls 16#E0/agrave 16#E1/aacute 16#E2/acircumflex
+16#E3/atilde 16#E4/adieresis 16#E5/aring 16#E6/ae 16#E7/ccedilla 16#E8
+/egrave 16#E9/eacute 16#EA/ecircumflex 16#EB/edieresis 16#EC/igrave
+16#ED/iacute 16#EE/icircumflex 16#EF/idieresis 16#F0/eth 16#F1/ntilde
+16#F2/ograve 16#F3/oacute 16#F4/ocircumflex 16#F5/otilde 16#F6/odieresis
+16#F7/divide 16#F8/oslash 16#F9/ugrave 16#FA/uacute 16#FB/ucircumflex
+16#FC/udieresis 16#FD/yacute 16#FE/thorn 16#FF/ydieresis ] def/reencdict
+12 dict def/IsChar{basefontdict/CharStrings get exch known}bd/MapCh{dup
+IsChar not{pop/bullet}if newfont/Encoding get 3 1 roll put}bd/MapDegree{16#b0
+/degree IsChar{/degree}{/ring}ifelse MapCh}bd/MapBB{16#a6/brokenbar
+IsChar{/brokenbar}{/bar}ifelse MapCh}bd/ANSIFont{reencdict begin/newfontname
+ed/basefontname ed FontDirectory newfontname known not{/basefontdict
+basefontname findfont def/newfont basefontdict maxlength dict def basefontdict{exch
+dup/FID ne{dup/Encoding eq{exch dup length array copy newfont 3 1 roll
+put}{exch newfont 3 1 roll put}ifelse}{pop pop}ifelse}forall newfont
+/FontName newfontname put 127 1 159{newfont/Encoding get exch/bullet
+put}for ANSIVec aload pop ANSIVec length 2 idiv{MapCh}repeat MapDegree
+MapBB newfontname newfont definefont pop}if newfontname end}bd/SB{FC
+/ULlen ed/str ed str length fBE not{dup 1 gt{1 sub}if}if/cbStr ed
+/dxGdi ed/y0 ed/x0 ed str stringwidth dup 0 ne{/y1 ed/x1 ed y1 y1
+mul x1 x1 mul add sqrt dxGdi exch div 1 sub dup x1 mul cbStr div exch
+y1 mul cbStr div}{exch abs neg dxGdi add cbStr div exch}ifelse/dyExtra
+ed/dxExtra ed x0 y0 M fBE{dxBreak 0 BCh dxExtra dyExtra str awidthshow}{dxExtra
+dyExtra str ashow}ifelse fUL{x0 y0 M dxUL dyUL rmt ULlen fBE{Break
+add}if 0 mxUE transform gs rlt cyUL sl [] 0 setdash st gr}if fSO{x0
+y0 M dxSO dySO rmt ULlen fBE{Break add}if 0 mxUE transform gs rlt cyUL
+sl [] 0 setdash st gr}if n/fBE false def}bd/font{/name ed/Ascent ed
+0 ne/fT3 ed 0 ne/fSO ed 0 ne/fUL ed/Sy ed/Sx ed 10.0 div/ori ed -10.0
+div/esc ed/BCh ed name findfont/xAscent 0 def/yAscent Ascent def/ULesc
+esc def ULesc mxUE rotate pop fT3{/esc 0 def xAscent yAscent mxUE transform
+/yAscent ed/xAscent ed}if [Sx 0 0 Sy neg xAscent yAscent] esc mxE
+rotate mxF concatmatrix makefont setfont [Sx 0 0 Sy neg 0 Ascent] mxUE
+mxUF concatmatrix pop fUL{currentfont dup/FontInfo get/UnderlinePosition
+known not{pop/Courier findfont}if/FontInfo get/UnderlinePosition get
+1000 div 0 exch mxUF transform/dyUL ed/dxUL ed}if fSO{0 .3 mxUF transform
+/dySO ed/dxSO ed}if fUL fSO or{currentfont dup/FontInfo get/UnderlineThickness
+known not{pop/Courier findfont}if/FontInfo get/UnderlineThickness get
+1000 div Sy mul/cyUL ed}if}bd/min{2 copy gt{exch}if pop}bd/max{2 copy
+lt{exch}if pop}bd/CP{/ft ed{{ft 0 eq{clip}{eoclip}ifelse}stopped{currentflat
+1 add setflat}{exit}ifelse}loop}bd/patfont 10 dict def patfont begin
+/FontType 3 def/FontMatrix [1 0 0 -1 0 0] def/FontBBox [0 0 16 16]
+def/Encoding StandardEncoding def/BuildChar{pop pop 16 0 0 0 16 16
+setcachedevice 16 16 false [1 0 0 1 .25 .25]{pat}imagemask}bd end/p{
+/pat 32 string def{}forall 0 1 7{dup 2 mul pat exch 3 index put dup
+2 mul 1 add pat exch 3 index put dup 2 mul 16 add pat exch 3 index
+put 2 mul 17 add pat exch 2 index put pop}for}bd/pfill{/PatFont patfont
+definefont setfont/ch(AAAA)def X0 64 X1{Y1 -16 Y0{1 index exch M ch
+show}for pop}for}bd/vert{X0 w X1{dup Y0 M Y1 L st}for}bd/horz{Y0 w
+Y1{dup X0 exch M X1 exch L st}for}bd/fdiag{X0 w X1{Y0 M X1 X0 sub dup
+rlt st}for Y0 w Y1{X0 exch M Y1 Y0 sub dup rlt st}for}bd/bdiag{X0 w
+X1{Y1 M X1 X0 sub dup neg rlt st}for Y0 w Y1{X0 exch M Y1 Y0 sub dup
+neg rlt st}for}bd/AU{1 add cvi 15 or}bd/AD{1 sub cvi -16 and}bd/SHR{pathbbox
+AU/Y1 ed AU/X1 ed AD/Y0 ed AD/X0 ed}bd/hfill{/w iRes 37.5 div round
+def 0.1 sl [] 0 setdash n dup 0 eq{horz}if dup 1 eq{vert}if dup 2 eq{fdiag}if
+dup 3 eq{bdiag}if dup 4 eq{horz vert}if 5 eq{fdiag bdiag}if}bd/F{/ft
+ed fm 256 and 0 ne{gs FC ft 0 eq{fill}{eofill}ifelse gr}if fm 1536
+and 0 ne{SHR gs HC ft CP fm 1024 and 0 ne{/Tmp save def pfill Tmp restore}{fm
+15 and hfill}ifelse gr}if}bd/S{PenW sl PC st}bd/m matrix def/GW{iRes
+12 div PenW add cvi}bd/DoW{iRes 50 div PenW add cvi}bd/DW{iRes 8 div
+PenW add cvi}bd/SP{/PenW ed/iPen ed iPen 0 eq iPen 6 eq or{[] 0 setdash}if
+iPen 1 eq{[DW GW] 0 setdash}if iPen 2 eq{[DoW GW] 0 setdash}if iPen
+3 eq{[DW GW DoW GW] 0 setdash}if iPen 4 eq{[DW GW DoW GW DoW GW] 0
+setdash}if}bd/E{m cm pop tr scale 1 0 moveto 0 0 1 0 360 arc cp m sm}bd
+/AG{/sy ed/sx ed sx div 4 1 roll sy div 4 1 roll sx div 4 1 roll sy
+div 4 1 roll atan/a2 ed atan/a1 ed sx sy scale a1 a2 ARC}def/A{m cm
+pop tr AG m sm}def/P{m cm pop tr 0 0 M AG cp m sm}def/RRect{n 4 copy
+M 3 1 roll exch L 4 2 roll L L cp}bd/RRCC{/r ed/y1 ed/x1 ed/y0 ed/x0
+ed x0 x1 add 2 div y0 M x1 y0 x1 y1 r arcto 4{pop}repeat x1 y1 x0 y1
+r arcto 4{pop}repeat x0 y1 x0 y0 r arcto 4{pop}repeat x0 y0 x1 y0 r
+arcto 4{pop}repeat cp}bd/RR{2 copy 0 eq exch 0 eq or{pop pop RRect}{2
+copy eq{pop RRCC}{m cm pop/y2 ed/x2 ed/ys y2 x2 div 1 max def/xs x2
+y2 div 1 max def/y1 exch ys div def/x1 exch xs div def/y0 exch ys div
+def/x0 exch xs div def/r2 x2 y2 min def xs ys scale x0 x1 add 2 div
+y0 M x1 y0 x1 y1 r2 arcto 4{pop}repeat x1 y1 x0 y1 r2 arcto 4{pop}repeat
+x0 y1 x0 y0 r2 arcto 4{pop}repeat x0 y0 x1 y0 r2 arcto 4{pop}repeat
+m sm cp}ifelse}ifelse}bd/PP{{rlt}repeat}bd/OB{gs 0 ne{7 3 roll/y ed
+/x ed x y translate ULesc rotate x neg y neg translate x y 7 -3 roll}if
+sc B fill gr}bd/B{M/dy ed/dx ed dx 0 rlt 0 dy rlt dx neg 0 rlt cp}bd
+/CB{B clip n}bd/ErrHandler{errordict dup maxlength exch length gt
+dup{errordict begin}if/errhelpdict 12 dict def errhelpdict begin/stackunderflow(operand stack underflow)def
+/undefined(this name is not defined in a dictionary)def/VMerror(you have used up all the printer's memory)def
+/typecheck(operator was expecting a different type of operand)def
+/ioerror(input/output error occured)def end{end}if errordict begin
+/handleerror{$error begin newerror{/newerror false def showpage 72
+72 scale/x .25 def/y 9.6 def/Helvetica findfont .2 scalefont setfont
+x y moveto(Offending Command = )show/command load{dup type/stringtype
+ne{(max err string)cvs}if show}exec/y y .2 sub def x y moveto(Error = )show
+errorname{dup type dup( max err string )cvs show( : )show/stringtype
+ne{( max err string )cvs}if show}exec errordict begin errhelpdict errorname
+known{x 1 add y .2 sub moveto errhelpdict errorname get show}if end
+/y y .4 sub def x y moveto(Stack =)show ostack{/y y .2 sub def x 1
+add y moveto dup type/stringtype ne{( max err string )cvs}if show}forall
+showpage}if end}def end}bd end
+%%EndResource
+/SVDoc save def
+%%EndProlog
+%%BeginSetup
+Win35Dict begin
+ErrHandler
+%%EndSetup
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+
+%%BeginResource: font MSTT31c1bc
+/GreNewFont{10 dict dup 3 1 roll def dup begin 6 1 roll/FontType 3
+def/FontMatrix exch def/FontBBox exch def/FontInfo 2 dict def FontInfo
+/UnderlinePosition 3 -1 roll put FontInfo/UnderlineThickness 3 -1
+roll put/Encoding 256 array def 0 1 255{Encoding exch/.notdef put}for
+/CharProcs 256 dict def CharProcs/.notdef{}put/Metrics 256 dict def
+Metrics/.notdef 3 -1 roll put/BuildChar{/char exch def/fontdict exch
+def/charname fontdict/Encoding get char get def fontdict/Metrics get
+charname get aload pop setcachedevice fontdict begin Encoding char
+get CharProcs exch get end exec}def end definefont pop}def/AddChar{begin
+Encoding 3 1 roll put CharProcs 3 1 roll put Metrics 3 1 roll put end}def
+/MSTT31c1bc [58.0 0 0 0 0 0] 51 -102 [-58.0 -58.0 58.0 58.0] [1 58 div 0 0 1 58 div 0 0] /MSTT31c1bc GreNewFont
+%%EndResource
+
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+
+%%BeginResource: font MSTT31c1bc
+/G54 [35.0 0.0 2.0 0.0 33.0 39.0]
+/G54 {
+ 31 39 true [1 0 0 -1 -2.0 39.0] {<fffffffefffffffef807c03ee007c00ec007c006c007c0068007c0028007c0028007c0020007c000
+0007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c000
+0007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c0000007c000
+0007c0000007c0000007c0000007c0000007c0000007c000000fe000001ff00001ffff00>} imagemask
+ }
+ 84 /G54 MSTT31c1bc AddChar
+/G68 [28.0 0.0 0.0 0.0 28.0 41.0]
+/G68 {
+ 28 41 true [1 0 0 -1 0.0 41.0] {<038000000f8000007f800000ff8000000f8000000f8000000f8000000f8000000f8000000f800000
+0f8000000f8000000f8000000f8000000f81f0000f87f8000f8ffc000f987e000fa03e000fc03f00
+0f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f00
+0f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f001fc03f80
+fff9fff0>} imagemask
+ }
+ 104 /G68 MSTT31c1bc AddChar
+/G69 [15.0 0.0 1.0 0.0 14.0 41.0]
+/G69 {
+ 13 41 true [1 0 0 -1 -1.0 41.0] {<038007c007c007c0038000000000000000000000000000000000000003800f807f80ff800f800f80
+0f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f801fc0
+fff8>} imagemask
+ }
+ 105 /G69 MSTT31c1bc AddChar
+/G72 [19.0 0.0 0.0 0.0 19.0 27.0]
+/G72 {
+ 19 27 true [1 0 0 -1 0.0 27.0] {<0187c00f8fe07f9fe0ffb3e00fe1c00fc0000fc0000f80000f80000f80000f80000f80000f80000f
+80000f80000f80000f80000f80000f80000f80000f80000f80000f80000f80000fc0001fe000fff8
+00>} imagemask
+ }
+ 114 /G72 MSTT31c1bc AddChar
+/G64 [29.0 0.0 2.0 -1.0 29.0 41.0]
+/G64 {
+ 27 42 true [1 0 0 -1 -2.0 41.0] {<00000e0000003e000001fe000003fe0000003e0000003e0000003e0000003e0000003e0000003e00
+00003e0000003e0000003e0000003e00007e3e0001ffbe0003c3fe000f00fe000e007e001e007e00
+3c007e003c003e007c003e0078003e0078003e00f8003e00f8003e00f8003e00f8003e00f8003e00
+f8003e00f8003e00fc003e007c003e007e003e007e003e003f007e003f80fe001fe1bfe00fffbfc0
+03fe3e0000f83800>} imagemask
+ }
+ 100 /G64 MSTT31c1bc AddChar
+/G20 [15.0 0.0 0.0 0.0 0.0 0.0]
+/G20 {
+}
+ 32 /G20 MSTT31c1bc AddChar
+/G49 [19.0 0.0 1.0 0.0 18.0 39.0]
+/G49 {
+ 17 39 true [1 0 0 -1 -1.0 39.0] {<ffff800ff80007f00003e00003e00003e00003e00003e00003e00003e00003e00003e00003e00003
+e00003e00003e00003e00003e00003e00003e00003e00003e00003e00003e00003e00003e00003e0
+0003e00003e00003e00003e00003e00003e00003e00003e00003e00007f0000ff800ffff80>} imagemask
+ }
+ 73 /G49 MSTT31c1bc AddChar
+/G6e [28.0 0.0 0.0 0.0 28.0 27.0]
+/G6e {
+ 28 27 true [1 0 0 -1 0.0 27.0] {<0381f0000f87fc007f8ffc00ff987e000fa03e000fc03f000f801f000f801f000f801f000f801f00
+0f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f00
+0f801f000f801f000f801f000f801f000f801f001fc03f80fff9fff0>} imagemask
+ }
+ 110 /G6e MSTT31c1bc AddChar
+/G74 [16.0 0.0 0.0 -1.0 16.0 35.0]
+/G74 {
+ 16 36 true [1 0 0 -1 0.0 35.0] {<0080018001800380038007800f801f803f807ffefffe0f800f800f800f800f800f800f800f800f80
+0f800f800f800f800f800f800f800f800f800f800f800f810fc207fc03f801f0>} imagemask
+ }
+ 116 /G74 MSTT31c1bc AddChar
+/G65 [26.0 0.0 2.0 -1.0 24.0 27.0]
+/G65 {
+ 22 28 true [1 0 0 -1 -2.0 27.0] {<00fe0003ff80070fe00e03f01c01f03801f83800f87000fc7000fc7ffffcfffffcf00000f00000f0
+0000f00000f80000f80000f80004fc000c7e000c7f00187f80383fe0f01ffff00fffe007ffc003ff
+8000fc00>} imagemask
+ }
+ 101 /G65 MSTT31c1bc AddChar
+/G61 [26.0 0.0 2.0 -1.0 26.0 27.0]
+/G61 {
+ 24 28 true [1 0 0 -1 -2.0 27.0] {<01fe000fff801f0fc03c03e07c03f07c01f07c01f07c01f03801f00001f00003f0001ff0007df003
+e1f00781f01f01f03e01f07c01f07801f0f801f0f801f0f801f0fc03f0fc07f17e1df37ff9fe3fe1
+fc0f80f0>} imagemask
+ }
+ 97 /G61 MSTT31c1bc AddChar
+/G6f [29.0 0.0 2.0 -1.0 27.0 27.0]
+/G6f {
+ 25 28 true [1 0 0 -1 -2.0 27.0] {<007f000001ffc0000783f0000f00f8001e007c001c007e003c003e003c003f0078001f0078001f00
+f8001f80f8000f80f8000f80f8000f80f8000f80f8000f80f8000f80fc000f007c000f007c000f00
+7e000e003e001e003f001c001f003c000f80780007e0f00003ffc000007f0000>} imagemask
+ }
+ 111 /G6f MSTT31c1bc AddChar
+/G6c [15.0 0.0 1.0 0.0 14.0 41.0]
+/G6c {
+ 13 41 true [1 0 0 -1 -1.0 41.0] {<03800f807f80ff800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f80
+0f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f800f801fc0
+fff8>} imagemask
+ }
+ 108 /G6c MSTT31c1bc AddChar
+/G4c [34.0 0.0 0.0 0.0 33.0 39.0]
+/G4c {
+ 33 39 true [1 0 0 -1 0.0 39.0] {<ffff8000000ff800000007f000000003e000000003e000000003e000000003e000000003e0000000
+03e000000003e000000003e000000003e000000003e000000003e000000003e000000003e0000000
+03e000000003e000000003e000000003e000000003e000000003e000000003e000000003e0000000
+03e000000003e000000003e000000003e000000003e000008003e000018003e000010003e0000300
+03e000030003e000070003e0000e0003e0001e0007f0007e000ffffffc00fffffffc00>} imagemask
+ }
+ 76 /G4c MSTT31c1bc AddChar
+/G75 [28.0 0.0 0.0 -1.0 28.0 26.0]
+/G75 {
+ 28 27 true [1 0 0 -1 0.0 26.0] {<ff81ff001f803f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f00
+0f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f000f801f00
+0f801f000f803f0007c05f0007e19ff003ff1fe001fe1f0000f81c00>} imagemask
+ }
+ 117 /G75 MSTT31c1bc AddChar
+/G78 [28.0 0.0 0.0 0.0 28.0 26.0]
+/G78 {
+ 28 26 true [1 0 0 -1 0.0 26.0] {<fff07fc03fc01f000fc01e000fc01c0007e0380003f0300001f8600001f8c00000fd8000007f8000
+007f0000003f0000001f8000001f8000001fc0000037e0000063f00000c3f0000181f8000300fc00
+0300fc0006007e000c003f001c003f803e007fc07f81fff0>} imagemask
+ }
+ 120 /G78 MSTT31c1bc AddChar
+/G43 [39.0 0.0 2.0 -1.0 37.0 40.0]
+/G43 {
+ 35 41 true [1 0 0 -1 -2.0 40.0] {<0001ff0080000ffff180003f00ff80007c003f8001f0000f8003e000078007c00003c00f800001c0
+0f800001c01f000000c01f000000c03e000000c03e000000407e000000007e000000007c00000000
+fc00000000fc00000000fc00000000fc00000000fc00000000fc00000000fc00000000fc00000000
+fc00000000fc000000007e000000007e000000007e000000003f000000003f000000201f80000040
+1f800000c00fc000018007e000030007f000060003fc001c0000ff807800007ffff000001fffc000
+0003fe0000>} imagemask
+ }
+ 67 /G43 MSTT31c1bc AddChar
+/G66 [18.0 0.0 1.0 0.0 24.0 41.0]
+/G66 {
+ 23 41 true [1 0 0 -1 -1.0 41.0] {<0007e0003ff80070fc00e07e01e03e01c03e03c01c03c00003c00007c00007c00007c00007c00007
+c00007c000ffff80ffff8007c00007c00007c00007c00007c00007c00007c00007c00007c00007c0
+0007c00007c00007c00007c00007c00007c00007c00007c00007c00007c00007c0000fe0001ff000
+ffff00>} imagemask
+ }
+ 102 /G66 MSTT31c1bc AddChar
+/G63 [26.0 0.0 2.0 -1.0 24.0 27.0]
+/G63 {
+ 22 28 true [1 0 0 -1 -2.0 27.0] {<007f0001ffc00783e00f01f01e01f03c01f83c00f87c00f8780070780000f80000f80000f80000f8
+0000f80000fc0000fc0004fc000cfe000c7e00087f00183f80383fe0f01fffe00fffe007ffc003ff
+0000fc00>} imagemask
+ }
+ 99 /G63 MSTT31c1bc AddChar
+/G2d [19.0 0.0 2.0 11.0 17.0 16.0]
+/G2d {
+ 15 5 true [1 0 0 -1 -2.0 16.0] {<fffefffefffefffefffe>} imagemask
+ }
+ 45 /G2d MSTT31c1bc AddChar
+/G42 [38.0 0.0 0.0 0.0 35.0 39.0]
+/G42 {
+ 35 39 true [1 0 0 -1 0.0 39.0] {<fffffe00000fffffe00007f00ff80003e001fc0003e000fe0003e0007f0003e0003f0003e0003f80
+03e0001f8003e0001f8003e0001f8003e0001f8003e0001f8003e0003f0003e0003f0003e0007e00
+03e000fe0003e003f80003fffff00003ffffe00003e007fc0003e000ff0003e0007f8003e0001fc0
+03e0001fc003e0000fe003e00007e003e00007e003e00007e003e00007e003e00007e003e0000fc0
+03e0000fc003e0001f8003e0003f8003e0007f0007f803fe000ffffff800ffffff8000>} imagemask
+ }
+ 66 /G42 MSTT31c1bc AddChar
+/G4d [52.0 0.0 0.0 0.0 52.0 39.0]
+/G4d {
+ 52 39 true [1 0 0 -1 0.0 39.0] {<fff00000007ff00ff0000000ff0007f8000000fe0003f8000001fc0003fc000001fc0003fc000003
+fc0003fe000003fc0003be0000077c0003bf0000077c00039f00000e7c00039f80000e7c00038f80
+000e7c00038fc0001c7c000387c0001c7c000387e000387c000383e000387c000383e000707c0003
+81f000707c000381f000e07c000381f800e07c000380f801c07c000380fc01c07c0003807c01c07c
+0003807e03807c0003803e03807c0003803f07007c0003801f07007c0003801f8e007c0003800f8e
+007c0003800fdc007c00038007dc007c00038007f8007c00038003f8007c00038003f8007c000380
+01f0007c00038001f0007c0007c000e000fe000fe000e001ff00fffe00401ffff0>} imagemask
+ }
+ 77 /G4d MSTT31c1bc AddChar
+/G79 [28.0 0.0 0.0 -12.0 28.0 26.0]
+/G79 {
+ 28 38 true [1 0 0 -1 0.0 26.0] {<fff00ff07fc003c03f8003801f8003800f8003000fc0030007c0060007e0060003e0060003f00c00
+01f00c0001f8180000f8180000fc1800007c3000007c3000003e6000003e6000003f6000001fc000
+001fc000000f8000000f8000000780000007000000030000000600000006000000060000000c0000
+000c000000180000001800003c3000007ff000007fe000007f8000001e000000>} imagemask
+ }
+ 121 /G79 MSTT31c1bc AddChar
+/G39 [29.0 0.0 2.0 0.0 26.0 40.0]
+/G39 {
+ 24 40 true [1 0 0 -1 -2.0 40.0] {<007e0003ff800783c00f01f01e00f03c00783c007c78003c78003e78003ef8001ef8001ff8001ff8
+001ff8001ff8001ffc001f7c001f7c001f7e003f3e003f1f007e0fc3fe07ff7e01f87c00007c0000
+fc0000f80001f00001f00003e00007c00007c0000f80001f00003c0000780001e00007c0007e0000
+>} imagemask
+ }
+ 57 /G39 MSTT31c1bc AddChar
+/G36 [29.0 0.0 2.0 0.0 26.0 40.0]
+/G36 {
+ 24 40 true [1 0 0 -1 -2.0 40.0] {<00003e0003f0000f80001e00003c0000f80001f00001e00003c00007c0000f80000f80001f00003f
+00003e00003e1f807effe07f83f07e00f8fc00fcfc007efc003ef8003ef8003ff8001ff8001ff800
+1ff8001ff8001f78001f7c001e7c001e3c001e3e003c1e003c0f00780f80f007c1e001ffc0007e00
+>} imagemask
+ }
+ 54 /G36 MSTT31c1bc AddChar
+%%EndResource
+
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G31 [29.0 0.0 6.0 0.0 22.0 40.0]
+/G31 {
+ 16 40 true [1 0 0 -1 -6.0 40.0] {<006003e00fe07fe0c7e003e003e003e003e003e003e003e003e003e003e003e003e003e003e003e0
+03e003e003e003e003e003e003e003e003e003e003e003e003e003e003e003e003e003e007f07fff
+>} imagemask
+ }
+ 49 /G31 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (1) 29 SB
+
+%%BeginResource: font MSTT31c1c9
+11 dict begin
+/FontInfo 8 dict dup begin
+/FullName (MSTT31c1c9) def
+/FamilyName (MSTT31c1c9) def
+/Weight (Normal) def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -109 def
+/UnderlineThickness 49 def
+end def
+/FontName /MSTT31c1c9 def
+/PaintType 0 def
+/FontType 1 def
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+/Encoding 256 array
+0 1 255 { 1 index exch /.notdef put } for
+30 255 FE
+def
+/FontBBox { 0 0 0 0 } def
+currentdict end
+currentfile eexec
+9e67edc6f3ddb54d987dfb0ad4392351758038a4ddcd7496126caebf3c4b776a9348fe88419c70c199dfed3be58c5559d44f85ed1b3b2d48c178aedfd3de0022
+1e04c6d4d0f48db1093382653d5c4a389b722bcd118482d76f60847858ee2b7fec8602e8fe84654d4a23e6e5b0a6a07705c6bdece2812668fa8d0c1c49883c1f
+ed5ef1fdceb49b11bd5c332ead97409150c8af0e5e03714ae6a229de223eb4d5df5f7ab0118978c08a67ebecb1283fb8e39fb2db8e5600d202b2909bfbdaa269
+abe5b36800302965c990a082835f3ac6efc9d64fe188cac4bb439c5f84ad8b5731ddb08c0b1aace01863a3d07f18d467b74f78e9d59d6f8dbb3c02ff1f33e752
+fcafa6b90648c821a1c6a6996ce5ab2f5507fbd175bf3a4b32a289ea31054444a2d44fcbaf008e1127661229de7dc37108848f4e9d4faf147cc1e00ac8048f85
+d0c3563f9385d8e93c91dc7fc9631ce01da924ff3d51539c2e089feace7a3708e9d2522cd0c4d5cdce2bbeccd30fdee2b9e98a6f99b1f22257b7
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d07d79b775d66db7f06b827e8ff4a2eb8a86a8433f9bba3a08ac51527ba66676ba5e87a8c35863c1d300d30244be0d12343c25ffa
+9f4d05d39ff23460fb3d423dc49c437f6bb9da6732dfcaf8d49f73ecfd0a2cea4b81f4830b5a5141dba90708e5b839ec4995bd45e8afeb94764a0f8aa57ef193
+428bbd3ae615cf958f6d9d734c885a4f29abf4504548ac5a355cb17006a16fdb9408bc90b2dfd2fc1387d824f1debaaa3987bd287feff105b69d7fe93ef6883b
+e0af2d2940ca07eb27030f4c14a8450cb52a98ce2500efd110cd8b3ea886053ead9bd5cacec38b807b3fbc94030f664f10b682be9a44509ba251515def870572
+1d26ca3aad2c32bebc5ccee3d18d95267bb565a655cd5ed0ab3a9e405c3eea95f233c357933db74f3a38eee1d08bf0b21ffe1aeacb490e977f4f7584539a1e19
+4c07b8d2e7dbfda90a5904ba54699c108acf1ba19892f8355e4d24639459b4518615fbee2122d9da66f42615386f5ee7925da010effed50b528057fd8f814b55
+b0de7c96c8b2ba89688fc49900ed140cf762bcaab025e4c5238166ea7ee7dac63774dcd1273a5519476b9de552f327588cbd15028562b1f2865acfa2f4ebe964
+15a7797feebc4a244649f27c987a80aac7dfdcb83ded53f98f579846d252ed9ca464e3e02d4d2ca61e0d7ac74b4d21c7b8e8dea84c3190c121b9120a9db2c539
+870be51291b34f801213611c24aa6f704d5c7aa827802af2fede4901f3a5e40c50ee8995745bd2a1fab16b1c3968bfa2454a9f8990036151d9464cddcefe41a1
+9b8bff464e2cf751d3968de0bba7336103fa2be945c74230c360d195a77173fe9e8c90e89ff0908f11381f5ccc9913be734b95d922dfd7a24cce2c2dfee3c400
+eefe54dfe3c5262449debb38fe06d6356cbdc79a707677a9ee854c5fa7a372def6fe9a1fd6fce94f3c73bff36a3e9886953c29dad84b51a55fb29e4aee39bb61
+aa4ee7727b9be20c1dd95828f1e7beb4c63ce43c5c4b5857c8abe1ed4cea10208d1a8bc832e19d32f8ebf5717ac9ba4c99d4607754d5d16229304ba1efa37632
+e6733c0bb38d5b9bac4cda3d111425156fb5da060eef679fd02e5db0aa3ebd42e68485b3835fb33095460cb3d7d33379c65fff26a3972f4eada94b1ccb8b0c53
+9b1a1ed9af028bb2e4aa9a9bbf4eac5ef0ef30c99a07766731df7a7d2cbc2aeba8e813d13f1806b733882dde18d76be093cc4127073081b7f3df1a8b6e40ec83
+506bb12716c247508084301940a874e192125fae70e15e423796cb9e35d45660ddc4e87a78ca22970105b6bb49ccb7e0f25ebd728af622d7298a0816dc6b6767
+3bd4c6c11960cc1a258149bc8bf078c023a283f1479157b66365c4adc8cf9521e696a13ae71466faa926191c6005bcd33075dd7c6cb07c0b822b1262c5cf767e
+1b296056976de0d0b744b6f540de9901670a590010ab28d5b2ee9f3c667bb1b76e4ba590daf4029f6829e146ac4293464b19833a2cf1a7c794c73e64f7c82ad1
+a5c1a0fb6f29d70df2201744772878fede649d7a444d479c786009b0b3221fe4c62665daf8ad8b7a160ecd05eeaed8bf1532c13a01467fcd2d95a05e681e1e52
+469bab6485b3d5b2d069d189f051c76a04b3ceed83b0a0f37ffdd8e92698e24ddd12a5b2dd3c9a6fd8db0d5a47629dbb5279a611383b087c971638aec6aa56e0
+84a83ef5589a664941c82ccafaa198c874e85892e67fc685e2a939485e57df8473b7e53cf97f03f2b666dac319895f02b1f167b74f12fcb7104eae01b10c1320
+de826cd4dc760ee59113ec742a7d74ce5c4f9741d3cb13fedadcb71067ad820f92e2b4aa5539707fe3cd6060993ab0d9c95ea8d8349e2fbfde8a05ac7e6fe34c
+1dadb4a14df7166de443467a39c7741ae9e1a59cbdf8733cfd5b64bfbf12d37ef50f4a9a765c7bf87079b046828793a5792193fd8985393a9db373c0650306e8
+4ef33c82937580b036eee02ebeea82c84c58552f7c52cf0ef43814cc1b1e9e8908d1150e5d7bbf2ce0e8ac497b04bd310ffdeb76b2d94e3c0a797cab4a992de6
+5858c95ceee596507da6b0896517a13778d028831e02b3059ae80a479f8e0d6a3763b402ed8286329f95ab006611b5fc7502f32e093751cd6bfe3e564078ca23
+504db2e91efa9dee56ac9c1a17a682e99ee9e36221d506fb0a1fc3fb5fb0521cc99b2d4c2d22f284d9cc0aea65a937b7424cc62e4e3815722400a3b8cb0058e6
+695fe0bca7b6d947c89570772e9367bbed7bd86c1c819cfc45d76fe8a6d39edc9d70dd1ffe266ac48c1ea72be9d36850b07cd1ddbedac72d40440cd40808ef58
+cf76954afc94cb71c25297234464c94eed023e49e3f6613f506fab97213a3281cb6a0b58157c6077edf84624eb9c79526ace10116d095e349a71f249d2559c8b
+a3b9377d49adc86e27abc0b12c70b8c962ae344c791241359e09504dbe3948b70f5a3e4874b9f0c7824d7fa22db2b93877b31cb9f71df8472fcd23ac7dc46e21
+4aafcfd8d41b80a9d027553a457199ff15ac580547d4db485c7750bddffad0d26fe90668afc59c612d9f4e388c676628118a1d2f977c70a6cb046c710437ce20
+b06af40524ad07e6b40d324e8d6964ab15ea9d6e745f1db5b7b194bfe0f08bc7310a9c41d79e8a34279f5c84988ccd53ad2aa17d82b8c1162e250ec3dadd48b4
+cabb848b84a64d587304eccc885e417a751a3bacdecd49e24163025611497d8734737194a45846f47fbaefe6be519819ba35a562d99808821ced8fc5f8870a03
+22d2015aafcb05ef5c0218cc61802c75cffef07165b98f9c72c0b8c2c09e6302f20465501c66cec8588351b7ebda0309015ef4bcbb1ec92ff2e76cb4a7615ab1
+6495f73631dbfb0c2c4bcd7a0d391cadb9d395e5b9d05a60f16b13317778c03dbd5e9549351f9544ce546f4fe065fe1293fbda5107f133552c0deba970cd47da
+9add288cdc884129e8c2f41c96b86955072370a13739df1d8571fde3d2841319c711ad53724cd1f8c5fb5f310d03ac8d8d68e98069a6792f9abf33c32a45dc0f
+83c4e02542af6b57ac09d4af238e63458802a95a462241c14139a475335bbe2bde73af860d7dbcf475ff6f35a3e1899a4a4d5085c590c05c84dcf4f35df534a0
+8d1736481a0d22a4408c3ca996e127547352788a7a8b4059fb4f22c8c215c64ac947d46fcc1ab3f87fd3f77040e93630a48ff52ea5c4687d7ab4afb6974a4b3e
+d53004e6584a3c3d0a5521180ecebd0f3eceabd76cc46136e7ced8aef737a883422e8e2557c67d46acb63ca2dfc0a9772cbc9f5a6472d2a1395b587b8859ee4e
+a41566f7709a78c314e257cf06b1f0d8dffa2116727132af174ea3cbfe255f0ccae43b587f9d9274b4e62d060253327df4ca4f12acaf7e5c7ad603aa44563b1c
+2d1073112be1696a9e3bc20d1b06a80dec85b944dc2992cc1e069ee2488f720fa1eaca5e5be9b13870b5a139fdfe917672c78c320594d9a38ef66f00458d5b70
+fad00e5cd296b83df525bc52c14ae625c68cdf9e446ff9ec912b3861d0e6ad408342785b3990afa28877887739420cc3414b0ffbf53e444add20541b0e6e1e86
+32e8cf6ebf640ff1152d1d1bc42df59e4deeee02be60841901a9ca18e811e29c0105034aa87d9359342d6cd08240fbca3ff1ba7e79a70d64c8af8fbb29346a62
+15fa6beab840a28b746462a12e2ea63683079e1ae67db3dd20f55543706eb784875a308ab44ad82eb34dda904501ba6e6798030941545b7515a9457ee6bf926f
+247d11735f995c242801c480afd57d7b79ae00c159613807e6280f7f370b3929de9d
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-3 1 SJ
+851 796 1387 (Quotas Management) 1387 SB
+
+%%BeginResource: font MSTT31c1d6
+11 dict begin
+/FontInfo 8 dict dup begin
+/FullName (MSTT31c1d6) def
+/FamilyName (MSTT31c1d6) def
+/Weight (Normal) def
+/ItalicAngle 0 def
+/isFixedPitch false def
+/UnderlinePosition -109 def
+/UnderlineThickness 49 def
+end def
+/FontName /MSTT31c1d6 def
+/PaintType 0 def
+/FontType 1 def
+/FontMatrix [1 2048 div 0 0 1 2048 div 0 0] def
+/Encoding 256 array
+0 1 255 { 1 index exch /.notdef put } for
+30 255 FE
+def
+/FontBBox { 0 0 0 0 } def
+currentdict end
+currentfile eexec
+9e67edc6f3ddb54d987dfb0ad4392351758038a4ddcd7496126caebf3c4b776a9348fe88419c70c199dfed3be58c5559d44f85ed1b3b2d48c178aedfd3de0022
+1e04c6d4d0f48db1093382653d5c4a389b722bcd118482d76f60847858ee2b7fec8602e8fe84654d4a23e6e5b0a6a07705c6bdece2812668fa8d0c1c49883c1f
+ed5ef1fdceb49b11bd5c332ead97409150c8af0e5e03714ae6a229de223eb4d5df5f7ab0118978c08a67ebecb1283fb8e39fb2db8e5600d202b2909bfbdaa269
+abe5b36800302965c990a082835f3ac6efc9d64fe188cac4bb439c5f84ad8b5731ddb08c0b1aace01863a3d07f18d467b74f78e9d59d6f8dbb3c02ff1f33e752
+fcafa6b90648c821a1c6a6996ce5ab2f5507fbd175bf3a4b32a289ea31054444a2d44fcbaf008e1127661229de7dc37108848f4e9d4faf147cc1e00ac8048f85
+d0c3563f9385d8e93c91dc7fc9631ce01da924ff3d51539c2e089feace7a3708e9d2522cd0c4d5cdce2bbeccd30fdee2b9e98a6f99b1f22257b7
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+
+32 0 0 150 150 0 0 0 134 /MSTT31c1d6 font
+%%BeginResource: font MSTT31c1d6
+currentfile eexec
+9e67edc6b858a3e762244b628fb01cf58f07fd3c01ea854585188a66a8f12aa17a95328b3ac7a563452355cdf678c51a4bd3287a046903abe9db4db7daee86d4
+aee44d97fdc85665066b373c0792e435f219551d1b381c469ea92e4ab34b9cf795f06a025e57d038642fbb46bf3d97ce665b4953318c1a4d0b1e84550ff76556
+5e97303458a9a8c72b9c1c85a1f761b3fafb37f172c6d3e4df174826bc2941e412e5cb3ed4d0ac348381fe6d1c11d07f669981e211812e3ebeffb1906914748d
+fbeae9ad08622df9c8908991684159d0842814d75741ba962c8dad83e6181fd23644266c2302745f433b949d1695beda980a6c47e997fcf53026e9b40af29b0d
+3ea5f5d4a6e9f971d4418b4055584386c498cafe2148f3ac9ae0c79b7fba7e0959e48e2c6a8383995003ec2b90f602f46626f3374925d020c0405bf51ce9eec5
+ce9343477b8c2736bd6894ce1bbbbe9beb6101d80b1f4f63d63334c4045c2426596e994ffe3c36fa7f3adaa39b3ef93106dd774c7f270779a898aa66754f5c52
+690bdae6a204aa4f61efef8f2bb9a72584fc8fc81ee62e3e42378e83753bea564c275fb3662ad1e72ca1623d304c711c7aacc6cea03d6cc24827b0f37dcf82e9
+67362aa9fdd3c5cde7b4ab202acf0a05decf30ab4a5fa2edee73e0e2848351e6e06eeb9bba82744b1a47738896af84b6bf490c479c601f2e6d3abf792667ec4d
+17218121218e67ce24323878a663fba773d8460438b0331f727aed6fb7582efafaabebb282ea590ea3af5e1ad02738272586c5de9f881a56b61942fee714f11e
+bae04cb115f5f2f69c0ab4ff07faae9d4e7b4ddc6c97cbe0a93c1650f2bd05b6f7363fc395fa7dce160c201534acb0b0c3a5a144d3971aea6a854aba5a70086d
+30f20e07a2b7e06e26183c04d88a5de3bca7b245dc79481e693fe24a0d2fc1b5157d9be970905cac9b3cb683f12795e54110b3f8af334b3e2d43689e87a43879
+a0ec0140016e5bf0b954f785adf177e1ddaee7154bd37c9c7814c5d75fde747357e83de8384d06323a2d39654585e6e914bc35b5ecb1fd8c7ab08174de73c86c
+5f809a35103df8eddee503cd9d93729ce4cde2e7f70da6bf42f74762ac997262e15bcc4de700145c8950ee8b6a191a6f11b58431edbbe9e6a553ae4c18151cc7
+3137547830daa00df1c47932e85eb2f047e0d26494711f2b3c2069038ce66c1b83fe2e78dacc09599e1d2e6a403b3638a44661461595f7d39486a0c580781dbd
+edca70b836e6c4a8003ca70bf2e0528bfa27930c6e54aa458f670ee710ac0e6e06e66dd45c2e6de096ab627509091c5366773a42041bebdeac5fc8e187097288
+1fd06cbb241c402036a5b1604286ba94e61194312ce573b2f97e7ec8e869839bece474f34f158336df468f557cd7b6826f9cc1b05425228a8ca35b7c2075a463
+ef3fde8f1b210a0068a23de1531043ee3ad3916dcc2809ed2c2792bf7b7b28a9a9eb4373f313239573ebb81bcf59ce04525a437f04bacb25d11b10da0d8b2792
+3caffa9f1ed84c3747cf515a8dcd1389a2b01675fe31e21ec54cb395a29b532ca8c51d8002ed87d8b3386de94c7006b6eab7d7093106047ec358e45914918e53
+7786252cd87ce758393ab6101b6da3baaad98db8ea61db22c6d0083646bc00e55b481f91391ef371d6f56fee94350a9d77f45ca5c3315120ceb0873529e463fe
+c9236c31fe3fb5866b79d4cd79a52eb6fa9a52cd609e5ca13b1486fd0f05c34cc7cbd139653324ab3eb05081e5abb5b3e1813374a97e8f0a73c0168a2635d5e5
+14de857d3bb39fb208389cffd99ceb7318fd110e543fb58595825c87f0234d97b649f568cdfd32cce2e8f3c6436edd8366193c0a6046b5b19ea6e703fc681fe0
+c1a1edc98389f8f56bf31a0a70149bc5c0618576798edea239fd9baeacb4973a0edfa947ed3934876fd8663deb6164a180b0a19ad1bc268f0084648c4ca2a1e9
+848cb645ab16be2cacc42ae81b22aade1267f4b46a5fef5839a4419457256730d8ab39acc12540d748a49a823731632d452b8ffc10e7c0ce9ca6687cdb5d399d
+60fa214693f775f82c7901172520e8bce058193b4e60ac7d656cd7a46973732f329bd6bc2ab5e84a57957eb1aa661c4cafc8566b84b20b988999f664b4a27327
+80f33e0d7c4d418ebe9c9cf09e8c6bf517cbb6bf0b2f70f7efbb81108e59fd17aa1d0428c65988928c03c1ecfb42fb3d02b450651bdc0711e530ee2db6557918
+07fbbd7229ec3b54a0f994f88a410e0fc15544832e7b2324e89e7583069d405eac6dde1898789fd56871bdb8ef6af1103c94a6f9dad0274486a0b4fef6544a9c
+8a5a5a8efcdb26569518af945c2819559ae3a1d3e9f0a551e8ea33f3596ebcc11841a811e89034d7ce5621b360f37144e8324d195f3d831b143a28642485ca31
+50e75a876356fec8fb67759efae1bc320162ef7c0431a331a2604a841539010380f7d1a0119a5ac540bbbe04191e7d2097120e124f92916a90d097e325760bc1
+bbdd3978d40787dea9fb014ac2f38a4f85ceff87ff1742908f68633b66b8238bc957c9260d60d8797ba59e4ceaa35417d0cae12261929adcf93cdccbee80f3d7
+b41e2dd5cae13a7a23dcf7e078d19d201f935c64f4309a6d93780da46677fc138a5c1d0ec924cc7cca1efe8c0febbaea1dcd75881f5ad600bc8e3bbcf8362596
+97bad5ae3b15df0ef9e526541f5cae399f26fcc51898fe034a23cb377e7182ed68780450ca3dd264b308e8414be3c306ad83370182e900d46f9acf5ff8339c43
+37d49d9249ccefeafe185fcfeabfbe6bc37bfd717fd5c9cec5d27852a45ce7835ca0691887935114be9cbfa2bfe4058cb06c0bf01810c1fae466284233438a2e
+85ef0b276e04bb2c014c51b7e41e07490cf1bde5aade06c2ec1724db884b4a1bcc16b9356872c11fd1d68d0ce070a44ac4769afb6addfb03c2fb1bdbffa86e14
+7f66f7303715b68460bc6f16346543a64fd502ba34eb6849e32bd4466a3e72792d6b7fdffd08ebc11c291286196e49112c05904894aabf9f4e65241605d96d68
+36f3f88cea29b18c07dfe391a17c7d9846eb3d56bb79d08788f4ba52f110058ae2e8ca05a36a5fbdebc60f8372dec37f4fa69ebea445db249511e890b924189d
+64f63e0a4ef68acab678ac1dd02499458a63ac9cd933301ac4021cbbfb561da87239312a0f0e54581d952f5e13d2ddb1b5129198eb0e5b180ac5ec495e4dd937
+299002257bb65fc6beac7c58cda87d285e1ad077d2f4ac5de141448d876a97e745fb30fb30a1739e447640962d7586e5fca87e326758fc08cca0e33fe35fc28f
+4b1fc6743df8410c4f56d5a621678f5d1aaea549142c900a5bc16000b9409a3100b88a6a2dda20de4d3748433a0bedebff9a457811fe10b47aa459e165c94dfd
+9aef1a03128fe57c534119a318251bf8dbdfe096129a81a817f2da16be22fd08e20deae0ca528ce847a0654a40d662572f75650c441527ec864e74e386cef6a4
+572e4678e7a27fc6012d7998d242242e9c5025c5ccd236f5ee9c26682dd476b3f4cdd67e1029f66f100a9c453cee95882a787000ad50313cbeffb728821a8803
+77c5ef67bbd05cf84b5d0a174c321fe523f2838959f21b9b887eaed8194a13df6ed58925d3644787355009950b3cc923c4005588eb72b1948c95634dae8cada2
+a1546a85e4f9ba9e23a85d3448ca1d44f4a960ba33e70c7e5ff991118af2ab4867e86ccbc2c1d377cdc447e4eba65c7e3b353b0f1976a1f45dbe366d9db79c0d
+3c77d2f9dad803d120cadd32a5693bee656f5103df4a1b7d9acf67a025603211238d594f5002a1c3f77b12a23dc88d9e6188e2b080d9be48c59eb2d84ed45c51
+cdb0e7041e0221625332d32004df7218d16b1ac59ce8a3d67a6142be7a4d6ac36354b83327b2d0b13c692fda4a440e6d25d78a7787336f64a69b697a4ff4eb56
+d117a877ca60403b49141fd8804e71a8cc050e111ebb03adac4a9232f61ce5e8b6c3ef6acdbb4b85a2023b914c6cd9874531c0633b7fce488a2c54dff63e32b5
+00fa11accac7ef454f4c37b802f315f356fef1f9e81236b70a838e3f737e98c9105ece262566ff77ba49d385d7502c493c0df5af28590fc31f89e4b13456187d
+6c1b13bdad9808ca54425b3ca7b909dcfd2efd8f85eae95da7aafb51b2c9a7873665ff14a3c435e1a0d5760b4572ec7a4b7fb1d657cfeb0206e2d9dd84e0a918
+9f40b8510afe50e376b6e19f9ab26e8cc3d078e448ed2d9b7577d9385012a623c687c2d3fd4ccb61ccccda1bd706b7d1ab69790ee7c62010633890ddb8c51ce5
+9997acf6c27052fe3ff554293279290194ae4dec105ed66f0cc8a28409b6f031579ee147574967e7839bbec5a1d5cecdb7152d672a85c85923042d4e6453b0b0
+2b528e31a7820996715aada0af88a73382525d11e3bbcd30a90bb91de040042f694b83ec58b625ede1d1cd7d5d3f34ab287155cc9ed25fbe4597ebb3fba7e1c6
+311d4a51603880fb0700f7f7d7af34776d11b0509fb392d47062b97a20f4a2d0a7882783eb1b1b474f0b5b5c38bbe0ab2a6273326c5b7a434042a2e9cf757067
+ae4a7ab78d9452f8d1695c2beaad2ede70eb76deefb0b4e06dda99d787dc62fb6f6b4e216d5594a8886cdf010b6b9ef4399ddab645a423ce8522ca392983dbcd
+e9cf950838daa0fc96301eb7fd82f000c614ab8d977b5569582f4a07432ff9ed0afe2d02b1d4aa400dfa20f552e3f2e56e4ebb4762841a8d5fa13b5218e4b702
+6b07df026de2bf55a00052445468924dd022f9154820a9b8f025f3b7447f6705ccf4b8f70e6a35209bf7d3bb325409154508ae26a51b460ce53fa16b7e0a3a7d
+818f8aa445abf2f117cfc0c77c12aafdcd7f3bd30342fea51d4708c0dfec89af089ca8ee924b4669c870562e76c61ccc75de41038bfb27fcde0d1f2d5fc3e0a7
+5516941e7dfd5c48b4fde5b9fe1306714a78a42efde303ed37f55e60a8f40eb43a85655c8da893d267d4808ed8b68c615b3399fcd41e20aaf2eabdec02f400ed
+a615940ebf0a01c196b06ed1afb8f18b016362cf4ceeac6a4aaa69824a93577a73c51cdcc74593aaeab758efaedd7d1b68fe185c2ab45fdedf2e1bd7d6335a18
+ff074a447ea06d098c17fd14e03f9cc2d2303c3d57c389880529b0d0177de9871ef27564d1dea98b2369f827f1e810677303c5a7d88a73edcf5ab4834f18d23e
+b55e8dd5d6899e7309cb8c425caee5843894f691a80cfb0f2ffa3675f17fcb3dbdde0c44c5a15282a5069471f9658c816258dfcd5a77fc68170d51bdf2bc2225
+f3e012d1a5a70b3d3bc79998656a81a262809bafc4037a3d07a78773d8b0f01266d8438ba0325ccdd02ba692282ec66a4ce4f4773abb43b00566351cd50623d5
+76876a3978017d40e5e5ef536974d6c8dbd7cf9e9d7e00bc8b89179d0cd9948f8b02c9e4eab5d8be491ebb66dce1b8a9fb4fba6a11c1c0dd211428d7db28239a
+eb31796198e525ae3bb1cbe28d0d3ee9680610c0e97569207ae5d03042494a83cd4fe924dad70b3e85eb24f02ff529968f7735fef9a9f8c2ae3e3bcdcbf14fa9
+de29d6807d6f5937534c93744863e38b59e4f122abe50700148187b8211576097195d82bedddfa5bc61bc9bcca3fa498fe8a9f6966ce63c044f5c9e2c1ff4fd9
+5ad124ef9fbd324ec5f11eb1f3c882c25487a95f8e84d9b8fc579837136f7ea5400d9c900f77bdffe4ab148d20a8ae6d6668c9021495a800c4e53ecbf8e3fc5b
+7f2f57daec9304fb648ab8e05ba9e6566f9dcf552092a73e06d644ac32a445a46ad67d250a2b05e28c6d9395701b563edf11d205c62bdda805e8b7521ff39f7f
+515235c13f28f92df2cc2715bfbc3e749baa6bebe253a6d591fcfa35a81ef542b8a662a3130611f331826b1960c1376f716ac214dc9d093399189f8801b4e3d8
+a54c4b38b96a6b681316709ecb90c2187b021323978d1fe6e2cdd99d0cbc2709ea767d26bdb7ede04add2b158fc881ee2900575cf2e1c1519c67fd3174c01474
+977f55e41272a1fa952f96bae267d1fffeecd3083027f6c9df0fdcbaed5b58a2f33f9de42d995b54429e396cdb5950fafb3ff988526ae6dba5985085e868302c
+eb553c63daeeef9a08d58f724f51fbad4b1bf53c6b17d59afb92a869b705538590f4b9ca0c1392146122a7c53f76f06d8a7c4b6d55761ee0de89afa6848da5a0
+600a083b2155ff6e2f340dee71e3e9e996db0805075a311d0a7f19c8c7dc24245ad9561c6329aa6315ef611f78c7958d18775e110bf8fd0710a935
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+610 998 1870 (\(Big Brother finally hits Linux\)) 1870 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d07d46fc97f64034f7316f286161df977422c4d4c0134696d3bc14d42a5196465b793903cbaef39f544b1ad2677617c3d7e7c7411
+44760ec4c558100f8d5150125bff221a8d8da1c78d036ae5d0ae1e5b46f2648b1738778da432f2e0a79098c0ab9bc73558835ae1fef4f1844107ef1919c93b0c
+b64aae6608a9fc951cd895a6b3f3e90b8e89304f12a55c7de79fe0bc6eceb3abda8db51431b753678b3817f478d9f366b7750a607d8c079f73d8c5e56e068fba
+5c63518263c5958057e03a4ba68be49c1abbbc6adc111544551d33c27152a5671bd06bd87987c94f41546459ad4f67e540d8cec6c2662fa09a888fcadff5763a
+ddc06e460f56a44cf58f036f265c29ff21007faeb386dc99302fb0c75ec3af2d623b6a9ee8fdc0930d2900a8a0b9485c95943acc8b7144032f285865e89eaf54
+f9489a0aec81c7baff9c82a84b4d36f53c63e16a1b0ba314c92122139d3f1a30663a99febda776f3a5b09f58f3d737c4f97231796513983e74b04468f5e52254
+f96a494e30e009344faadbf40da0a3df5894c843e2c62eb2ed15ba09c643f590ea45c08441ad235a12bc9c8396b5c431b942a496a1135d09cd0f97df836419fd
+3262b756126f193819ea64caf51a91c848562fde8e35f695218a75506a7bad9918eec09b13c0b5b50403eec5da0b3e58feed5202207d7224d199f5e6a4ed96b5
+e7f1b4fd4e7346d8d51d4ad11f6001b58242aed085deca4241fad480c8575b56fdef53291f0d4452328374c7a58e5b6caafbc80ec9623be7c85438cea66dda08
+fd1aa589af6b29384796377df9a3bbfbe204f740c572bb1074305a774dd30656a2aa2e1d9b1c0ba7454e81fc0d8a76f20dcfd29525365d5ce4165a7738a4cd6c
+0075f2074f3d69ffa948d84e7707e13055c4b9a98a131e7fc595008a6d27350694b44ff7638da1adf4af8a800034b6a67227eba2bfd5365057eb8bba15dc362a
+38b23966b57fd5a0d9b85b17910d13f78b357b14380ab23f50e621689bd4fa7c22956258469740feb8b58ffefebc8ace84fd883c822292033f12a2d16aabb3ae
+f236023254fefdf6cdf01fcbc61dafd6a55ae23ca0b4ff4cce608f3081b122c411afa788634f11968afaaa7a773d7175da7907d308714ce8e3c39a17920b52e1
+e27fcbba78e824072b162bd0ab6d0826cb0e5d51f2d7437535726aa2b48c6658b4ae98d35e45c285f60cfe4885e5f54b36b4a9f9a740d2203b44cfabebfdbd24
+76fe5d6ed793306e4a9afbda3812514148b680a5c8b96a0499082f5edb83c3a44be7a8c2343f9abeab596d6d07fb252a9d5c1fbce4a9b9404e64ebeb153f89b7
+cdbded7e60aaf93a93bdb0fd19b7f97a4bcf8fdc10be826f733efd9b54af79ed02588e5922c92b79db886d5f68ebaf69e3ec25a0ee3e463ad2d68d3906831ccd
+fea8ccc36fdd81934ff30689dc4dc2ceba3566a902aa9b6b2c841ee21c4026fb6cb91abe9d7c17c004ab60eedf8ceba17fb1e7b6df34261f180c1b7be2e6615f
+91eb33d8516566c788082983b544b47f94395145b17fc7ce6027029e9111c577c52be631dcef1f6539d76acb3887c258eb017070133424e2ff9433d1738b2d0e
+5a98d4eaa9d2f59f5bff8dc52be413ee31f2d9d5f2b8dbcb948b8483eb5b2310b4ddb742920d7466a6c76ad24ffea84db6a7c23de1f5db442e64f715de5d0f34
+2215a008e93426cf76a68e891a542178a9ae7a56bd5e268306a3f96fb2b2a4998c69edb1636255affffe4c65e47626a004a355ad5c1e42cc0dbdac265b27922c
+492efb97a21591b0ed96c00148b52390da02edbfe77d173aa2499b4b2a58c7898aaf75ed363330456ae71fe8204c445bd0d12406410ef1c9a935dfbb68
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-1 1 SJ
+1351 1340 535 (R\351my Card) 535 SB
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d0448bcdaf2881ea6472bde411d75ff8378c7389b65a1c39cec9312676c8e2b3872d24b1120f81ccbcfaa1a021ebd657347ad9b3a
+25a5feba0fed91bf6050489e080e699eac3ff41fd0001afe42e9ff70df6702e91b80c1177cd67f0a885c54b0c6b4eb135acfcd7d8692bafe81b24b78debbb0ce
+f5abdb21d9f47ba04d95f4fc9d6d2b0954c04a3fefb6c62aa930b483a5c25c7f0dd61a16733c26008660fec0e413fd51a21264ffd0d6937b113fd314ee1017fc
+5dbb10aa8ae6c448992468de3166ddf2ddebe662beed4ccf3c4b905db473fae6e98e56570a34e453ae7e96551b5ce6fecc9892c8f6ab0f30ac94b3f9ac13572e
+643c39532c61e72c55fc424a0eaefbcc008eacb07e46f31eada1364a19b316a613c3b59e43c75416d474a8fe4a2355e91a3c9d138c49b3c648aa29d1de834b36
+05f9b104ee2d15a150bed4e0692b562bf866d4a92f3e29ee75608fa3708c799d664220409ee157de6f9830cedaa4ff9a53a0681e55a1b5243b14362ba104143c
+d8013ca0ccbb8dc6b3eeecf6bd5d46c3b570ad8fa27a5d0955419b7712941e8677e54fec3580e56d24501b7994395fe19d09230d576918b3ba1763710d0b5e79
+a22a5e73385df5d0a49bdd5537c66520da770173078f784181e3d5d78d5a96f3669cebe588fd60d47bbbf49b30883362e10c4cfd18f30c1283741776f510a394
+89db102e681f8922908cce16341b00c6f7ff3cc48b721f329c2fc45485b235c3c3f97ab6521682eaff9d41fb397c028408615a36ad0f4ea2a638b75a7aacdb5f
+7e4fab5e62934289a76dcd109b2bc76fa249996d8cd664e1ece142e04a4b30799e6eb469328dfff6f2e5d73f24e3f8748b3b5370e060bb45ab41c0ae1058c4aa
+2cc86efc1bc74d8bdad4e963814ee168ac31af24d74fbb319ad078e08c1cb6b8b4a20c34b3db418f4854bd8a9975dc252a718890ecd206b81c11068887994f8c
+fcc12cab7d1d6e7f2ac0b5eb22d5bf57dc4a95877baa293f59815372747501b696f789c1b9a73b30a0a6c0a9406587d35ff5ba009e88a6474acbe8f8fae479fa
+9818551348de2f0ac7fe08adbdb5b7fb93e1e101f0ce440b93c035287ff328580520407d2d69a613fc29386a5a3acf42d0ce61315b7caacbce1502158c738641
+a99cf38a32ec1b7daeb408044b3f96c4c9819bc2ea25885b6384bf3420c93d26b31a713a7aa5e5ae66651e96675818982849892b4b2e36b3225e95832285e45e
+64474235c0f8f22952804c33581f456c8c75c6f4b3cde3bc7124fbd6f8e0d5afd0afdf95c7a30acdc3f418d9b8ee456ecdcf732fd17c4e7b51720342ac6115d2
+7ec7ef7a1b289f7455d28c1b67ffb8c4e0098ba829bc9b98f6fa4d4f4e1f422d2c2695b2a0583a4d73cd7b9195d284336e275aeecfd0b946f12832341c270ebc
+82dcf74e3bb39f384db6563524a0673dd89bd980087543228309d43570e573ef4517496a8f55a1551df3c274fb8ed76e4d7f7e60ab84a7be265f1a72ea11adb3
+183c94f15c27da85467ab0a82e6853116cfb513cef1d4ff13c69b2bca8c14dacd849457d5c477599e297aa882141aa5810366aaf21df11a2da129bfc9012b86b
+b04970b544660af9f14d58469aaa4e9dafd128903407546d326095dffaf59898f42c6149ff89f3ba7f51b0783324efef4cee3bfadc43261b7ebac69841c203b5
+98ca01488501df66639fad874d4a65497f77855f36d801e6a04eebd15da373bb79d1c3f94e9b5ea0436db50dd9f7d2c0ccba41aa97ef92c1ec3d4ddc67569197
+050e70236832839b79eab2e9dbfa1e14f46d86d88cccc549070b6a49e429837bb9716f91b09149b52132752507e4f3730c42faa725574b54b0322252729280f7
+76eb7cc1338d6b783249b2b0fc16aff94c6ee02835ad14897576c4d550e5cd871d805d9a86451270ce1cd07b86e5c49f9857af5623260d99860130762948e357
+d8c12871c526705394732e0f497a01c2bb8d12e10620741653a5a3a2c45c847ec86befc0c20ec653fb0b052e85a7c119a8fdc64b21070738c445b4934ef838af
+b3fb7e772fb842ef97f1f58d21c226cd31bfe040f39053f1883f9918242e4ea610349ccbd940ab10c957c56ea5b139e22c69864e7cd0e58c6f48d9c6ce56ed52
+519f32cde31069201b2aaf86a7b1e2dd9b7f1484e18989cdaf60b39df3d56058218177229d749332108017ed803b0e0ea1a442f8f858a8c4fad02e8d9f2f0aad
+d881e0fde6b0667c277b6d08fd2e9f19decd3359956d5a2177b3d1b49eb5a89a0cecc34bb3d927e988b4f851f92135ccbbaf1c1cef76799e051d745eee9ae5d0
+10599510376287bcbb255661713ed444199b5551b95596c307b8da70cc304fec8f6668e3c8ddf212ecfe12d0e0f6a625ec3301a90c78992cca3937538327d7e5
+6427bbe4704706763c563ba520a468bf6b18533f68ee5593f52d602e216412cab9b3e91a1d6bf2b4d6a39fe07d7df3b75d1cd58ec23d90e88b36539cd199116a
+adb476387999b1014549b62fe175a349dcef6a6f105f7fd8fb70923f2d77de2427f3eb4db383f35bc8aec742fb5732e7879dc7ae90e53c0d21b1ba7fd0d04a72
+05e8834226d06a386bbddc257a6f576b94ac7fba2eb353d71041944503aebed5b43c1d1bd1d481009bbb903bf114a6e93ee6d65f974d2146ce3d305d2043aea4
+42b6dbdf556a5c62c6e2912969dd46efd9db94acd1b39d0d000db989d4d4ace46072b658c1a1c1eb0a0c14693616f3d0560c8dfe861da170d4c935b182b47d37
+7f8e693e87ab147a1ee48edbe91c7917d84aa2fecd97ed787174286d9647d8624955683f1d2f9fda1e92c2ff0996ea4cf3d16b
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+1104 1509 143 (car) 142 SB
+1246 1509 167 (d@) 166 SB
+1412 1509 111 (ex) 110 SB
+1522 1509 137 (cal) 136 SB
+1658 1509 33 (i) 32 SB
+1690 1509 118 (bu) 117 SB
+1807 1509 160 (r.ib) 159 SB
+1966 1509 59 (p) 58 SB
+2024 1509 68 (.f) 69 SB
+2093 1509 39 (r) 38 SB
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d062efa8542d7e1727190148f267200f4b0f0b312c62fcf16c9bb3a1ed1ca5003235e108bace76f8cd465fb73141b6671457bfe24
+d3087a80e96a143127f065efd5a70426d02c648a5b6713f0ef8b187b09d22d417b6ec735e018df5521efb68bb7945d3b436b5504e18950cdc524c91cdfbaa538
+ff53cd9c5b23847e32038edcbbcfe0020d30c34229eacea8dceedcdb57e1bd2059b524307421fd01f6e08138e547f0f548bb5753c08a4ce11186ab148affe57d
+f211a4012da0db12a069f6d3965954caace909c813406571df2dbee0d1a866fb218c8f0ad696e67512cf4ac2fa5bd89767b80b9c03b44be00729814896ee417a
+79b0fd3cdb52a01cde8f32c4270ccb5fd17d506867be5d8851fd986beea38a00770f89ae5f25f4e05a074afc5861e07d3e15c7d8aea289157f8052a04aa74ee8
+3db9f8fa655ca2485e12dc74b08c4b67b131babf237a5b7606839c2dc79b5e57f5bc0fa459a94fca2bb520c6e0906f98f047d163787827c957ad081d640f998e
+6ee4374d20b63638a61791971bc7678c8aaeb7fcfdf3b39743047a113562ec98cc58bfd3438b8ab84bdb5d15bd0752135bae7d3baf2837b986bb0d86357e262b
+1fb3ccebf477f1b9c92b09a4aa8da142c4cb98800ba8fb79bd201fd60e169056c5e4970ef0d0de7e89456ff11ce40bd20e7075a6786465e0d11327d736480c67
+128c4b87c9fa3fd047d7a4941889822bf4400fe4f65f8ccdc71bff70e6b882ddcbc34c36c06340f9ed5f977141ba4471747fac0d0ab4ea50def3e9561d933230
+36dc2ca89bdbe6cd831bcf9f9376f10210d80be8d0728ab562fb79f92d20774cfc020a8b1c58b8aefbebae453224ce042076267c159a0321913c7432001ae486
+895a6127b493200e04ede57a8d700f22567eac
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-8 2 SJ
+1128 1677 987 (Institut Blaise Pascal) 987 SB
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d07d3a1806c63b82e1b0b6863860613ea7c0c2019c973386b8303b2b57a3f751027c7e560901b4a11ecebb6fe5e635fc9cd65b36a
+4824b23b464204a5a4e29f389c8782be9a0cc48546e8ff276eb1572e8040eebc12bec610990c830312fc89edd1773d6d686d3f1bc4d6425e4aae6a205c14e756
+ea8ed91a68fafeaa1789dfd79db78443d34fe0725a574387554d4b289736e90d30096822f8efb359ea3b7fed82e0f52581b661100703d0df3898fdf4a901c1c1
+c4607acf54796e8c1e1ef17999d7e6711cac0e56f68eb1d7440d4dea08a4890db7bc1a2becd33a6a398c390129a6a7c36a1e80f10929a8348d9c8c1c88ec2711
+8582773e34254a453ba45989289e36f29d62a9c6dff3b47589a15f9f0d2a761b214e710ca70c124c45b1b84d3c14bec2d979a7ff3fda0dac0cad0de30ed6d15b
+0e6f30ed55c4bd7dd45ba7eb7cc447d23c380473efaf740f3290e20609e88fb8f7d237e49ac14a03c9c459683c8acf3bbde20bdd1982eada1b226115528b995b
+f886f2f612fa9e7f97a06ae9dbc6beb350f8801f33bba0024c4bf80b11d8fd3e1433157c962b85cab7bd26d3d16c88076246a5e4bc8dbc147282c9a57bc60c1a
+9ffe52d1ce9ecde0d29bc4e87aceeb157e452421c33e35fd06e5d752fbb1be789515c546f58f949b9df8b5e49e2dab0710c06a5278e9f5f9b08c19d934c0f50b
+a36cda7d90da9c09c983bf49906c97f0cb5c7c499393ba1b0e582fee7093bee4e5013dc3ab78554c1a4af4a0b80237ae22117f28cc652d21191681db064d2c40
+5cc5fed5a1e6fe7bd2cd3abd612c08501d4528cd59769cebb478fc107360517360e288958c74da5cb92a0d922f2e3b70f6bbbf4817c0390b7dcd4f22aebe8259
+8a9d20aaf21d0027b6549d854a4464d4839b0103cc49294e1bd647c7176ee6236908a4011c12dfc3a76121bf1f35e4a3bbebf94fb8be94d8b2c82fcea2dee861
+d01ffe47264ba069a35f17a67ad5aaf697f1962189f8f3522c22918259e3b179e20f6546b183611bae6a3a74cdc9ff0b104275dc74950d6450bcc94e968bf7b8
+cdf0614ed7dc490a1d6c79e9e55adbf20e55ddc515f9af27e448a89577081e7f73fc88316a8dc7bdc93482da7e0c0035d4312467579bc3f4e833b1d39fcfb422
+73df4a6aafafc00f19352cf0ff6cfa34addfbac1d9ceaf9942
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-6 6 SJ
+620 1845 2006 (Universit\351 Pierre et Marie Curie \(Paris VI\)) 2006 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G32 [29.0 0.0 1.0 0.0 26.0 40.0]
+/G32 {
+ 25 40 true [1 0 0 -1 -1.0 40.0] {<007e000003ffc00007ffe0000ffff0001e07f8003801fc003000fc002000fc0060007e0040007e00
+00003e0000003e0000003e0000003e0000003c0000003c0000003c00000078000000780000007000
+0000e0000000e0000001c000000380000003800000070000000e0000001c00000038000000300000
+0060000000c000000180000003000080060001000c0007001fffff003ffffe007ffffe00fffffe00
+>} imagemask
+ }
+ 50 /G32 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (2) 29 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d065133686e273aea657ad4eeb667942355bbf44e5b3127dd61797055dbc6ed38d13c364ca31df6a437b2bf27d1c5ce57b92472fd
+0567e62f9d7879b144ad348a752c6f7184215c65c061058bd12a587f902784eb4707535b56e1e47bd57dca41ec9fc95977b30f7236b89bcec1494ae659e38595
+c723fd50fafd771309d4a66d686ddb4ff76f707d181c2ac6702ce5f87481cf81d8bc400f3ab2da3db762d0e5be70030f6d87b568891a899af8427f17634ed0d3
+98a8df688b1d9b939e9e2e34819b1802edc1c2a594a13ab439c605efe344e7186cff66259b040b6e47bb55554272bc496f41bde84e
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+256 284 121 (O) 120 SB
+376 284 222 (utli) 223 SB
+599 284 84 (n) 83 SB
+682 284 74 (e) 74 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 648 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d0578cb0186d4620ef95432fd6faeca0fca7737f96247536631e5e6575a357bcc6c8b4d0c3576fcdf4cf885af2848d87a8abae2eb
+7f3f61e803ddbf80caa5712c69691e95d423c96c736ba2cf6a4c589d8afbc9b67365a82aa1e7bd7932238a52abd053e77ca9f2bb3e3af59955ec981c48f64f6b
+ef6b6bad5cb0045916060c29795a6a926a9c36958eed0f5e8447dad65a8b2ccbc3a3331eb99c2b4583fbbca75e26226faec4986c28b27517922f6938c3213d95
+4aba452879ee9dafb095476c97deeecfa06d2267046077586fdbcdeabf034fab3472ab8e3d18461c4dffafb40e1f7cfb2334599ec32505654c69dc5d25a82323
+eb5cef1487d3946135a2ac75c70f4c758679017c8a8ec2
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-8 2 SJ
+586 615 935 (Principles of quotas) 935 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 817 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d0443b441567658a6856e7adbc62baedf12261c9875c4762d5f6b143a52c4aa4ce21dbb4ff936839757b4a3c065a07fe502a0354a
+8ce25f6c10920e15983484eb48cfc7a939fda22bc4a6ec91fbb4b0916edba2f6a514b086eb443fb3eb38b361d95d5feaa9e01aaa83e5d9b36d92e37e0aa4672a
+89deaae53dcf2e752fa2ebdbc2e862110838defe717b3c44128d33f2928ece139ecc87804fb5ff9fe84675bea7d752a54cfa1400fd4977c2964b88944a337035
+5e729793e549c5d06a7bfc35000ef31d552db250a6ebc2350ea3429c390fa173091de36f683677c2966043917abad1efb0d0647a850d23f51849151115030860
+e072a1c992b8665630f1bc48dd3f1d2c61d3586e21db6c44ad5816dc55ba1e1b11a17ab27cc66220f2899c6c4a7df9656ec21641de780ffdd7137b6db97e666e
+25cd3864ff63039b0f60df920af85299b29c
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-15 3 SJ
+586 784 1645 (Configuration of the quota-support) 1645 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 985 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d062647bb1263d8c25299774bfe585fa96223d906032043f9df53b5ea93f1d9c8fe6050ea78c741e63c84b69a755949e25da8285d
+1dbcc8d56b993b784ee792db023d6f938f8c3704820cc30539a588b5c33a9da56c2ee373f843867ab024e73d847b9cfe7c27c0baed1952d3f0c7bccca7c01bab
+3fbbf1afe64aaaf40492500433a866ee9c4c101976c667778e555af1ace42c5bcf80221cc89566b89aae50c40422326c935dd6998f7048f941418f6c2a7fd903
+284d3b582fe90315
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-12 4 SJ
+586 952 1821 (Administration of the quota subsystem) 1821 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1153 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-2 1 SJ
+586 1120 504 (Quota API) 504 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1321 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-12 4 SJ
+586 1288 1717 (Implementation of the quota support) 1717 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1489 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+586 1456 137 (Co) 136 SB
+722 1456 59 (n) 58 SB
+780 1456 144 (clu) 143 SB
+923 1456 46 (s) 45 SB
+968 1456 92 (io) 91 SB
+1059 1456 59 (n) 58 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G33 [29.0 0.0 2.0 0.0 24.0 40.0]
+/G33 {
+ 22 40 true [1 0 0 -1 -2.0 40.0] {<00fe0003ff8007ffc00fffe01e0fe03803f03001f06001f00000f00000f00000e00000e00000c000
+01c0000180000300000600001f80007fc003ffe0003ff00007f80001f80000fc0000fc00007c0000
+7c00003c00003c00003c0000380000380000380000700000607000e0fc01c0ff07007ffc003fe000
+>} imagemask
+ }
+ 51 /G33 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (3) 29 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+256 284 140 (In) 139 SB
+395 284 186 (tro) 185 SB
+580 284 84 (d) 83 SB
+663 284 418 (uction) 417 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+
+%%BeginResource: font MSTT31c1f0
+/MSTT31c1f0 [100.0 0 0 0 0 0] 50 -110 [-100.0 -100.0 100.0 100.0] [1 100 div 0 0 1 100 div 0 0] /MSTT31c1f0 GreNewFont
+%%EndResource
+
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G44 [72.0 0.0 2.0 0.0 68.0 67.0]
+/G44 {
+ 66 67 true [1 0 0 -1 -2.0 67.0] {<fffffffff800000000ffffffffffe000000007fffffffffe00000001fffe003fff80000000ffc000
+07ffe0000000ffc00000fff80000007fc000003ffc0000007fc000001ffe0000007fc0000007ff00
+00007fc0000003ff8000007fc0000001ffc000007fc0000000ffe000007fc00000007ff000007fc0
+0000007ff800007fc00000003ff800007fc00000001ffc00007fc00000001ffc00007fc00000000f
+fe00007fc00000000ffe00007fc000000007ff00007fc000000007ff00007fc000000007ff00007f
+c000000003ff80007fc000000003ff80007fc000000003ff80007fc000000003ff80007fc0000000
+03ff80007fc000000001ffc0007fc000000001ffc0007fc000000001ffc0007fc000000001ffc000
+7fc000000001ffc0007fc000000001ffc0007fc000000001ffc0007fc000000001ffc0007fc00000
+0001ffc0007fc000000001ffc0007fc000000001ffc0007fc000000001ffc0007fc000000001ffc0
+007fc000000003ff80007fc000000003ff80007fc000000003ff80007fc000000003ff80007fc000
+000003ff00007fc000000007ff00007fc000000007ff00007fc000000007fe00007fc00000000ffe
+00007fc00000000ffc00007fc00000001ffc00007fc00000001ff800007fc00000003ff800007fc0
+0000007ff000007fc00000007fe000007fc0000000ffe000007fc0000001ffc000007fc0000003ff
+8000007fc0000007ff0000007fc000001ffe0000007fc000003ff8000000ffc00000fff0000000ff
+c00007ffc0000001fffe003fff00000007fffffffffc000000ffffffffffc0000000fffffffff800
+000000>} imagemask
+ }
+ 68 /G44 MSTT31c1f0 AddChar
+/G69 [28.0 0.0 3.0 0.0 25.0 70.0]
+/G69 {
+ 22 70 true [1 0 0 -1 -3.0 70.0] {<00f80001fc0003fe0007ff0007ff0007ff0007ff0007ff0003fe0001fc0000f80000000000000000
+0000000000000000000000000000000000000000000000000000000000000000000e00007e0003fe
+000ffe007ffe00fffe00c7fe0003fe0003fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe00
+01fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001
+fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0003ff0003ff
+000fffc0fffffcfffffc>} imagemask
+ }
+ 105 /G69 MSTT31c1f0 AddChar
+/G73 [39.0 0.0 5.0 -1.0 36.0 46.0]
+/G73 {
+ 31 47 true [1 0 0 -1 -5.0 46.0] {<003fc03001fff87007fffff00fc07ff01f800ff03e0007f03e0003f07c0001f07c0001f0fc0000f0
+fc0000f0fc000070fe000070ff000030ff800030ffc000007ff000007ffc00003fff00001fffc000
+0ffff00007fffc0003ffff0000ffff80003fffe0000ffff00003fff80000fff800003ffc00001ffc
+000007fe000003fec00001fec00001fee00000fee00000fef00000fef00000fcf80000fcfc0000fc
+fe0001f8ff0003f0ffc007e0fff81fc0ffffff80e3fffe00c01ff000>} imagemask
+ }
+ 115 /G73 MSTT31c1f0 AddChar
+/G6b [50.0 0.0 1.0 0.0 50.0 70.0]
+/G6b {
+ 49 70 true [1 0 0 -1 -1.0 70.0] {<000e0000000000007e000000000003fe00000000000ffe00000000007ffe0000000000fffe000000
+000047fe000000000003fe000000000001fe000000000001fe000000000001fe000000000001fe00
+0000000001fe000000000001fe000000000001fe000000000001fe000000000001fe000000000001
+fe000000000001fe000000000001fe000000000001fe000000000001fe000000000001fe00000000
+0001fe000000000001fe000000000001fe000ffffe0001fe000fffe00001fe0003ff000001fe0001
+fc000001fe0001f8000001fe0001e0000001fe0003c0000001fe000780000001fe000f00000001fe
+001e00000001fe003c00000001fe00f800000001fe01e000000001fe03c000000001fe0780000000
+01fe0f0000000001fe1e0000000001fe3e0000000001fe7f0000000001feff8000000001ffff8000
+000001feffc000000001fe7fe000000001fe3ff000000001fe1ff800000001fe1ff800000001fe0f
+fc00000001fe07fe00000001fe03ff00000001fe01ff80000001fe01ff80000001fe00ffc0000001
+fe007fe0000001fe003ff0000001fe001ff8000001fe001ff8000001fe000ffc000001fe0007fe00
+0001fe0003ff000001fe0003ff800003ff0001ffc00003ff0001ffe0000fffc003fff800fffffc0f
+ffff80fffffc0fffff80>} imagemask
+ }
+ 107 /G6b MSTT31c1f0 AddChar
+/G20 [25.0 0.0 0.0 0.0 0.0 0.0]
+/G20 {
+}
+ 32 /G20 MSTT31c1f0 AddChar
+/G70 [50.0 0.0 0.0 -21.0 47.0 46.0]
+/G70 {
+ 47 67 true [1 0 0 -1 0.0 46.0] {<0007001fc000003f00fff80000ff01fffc0007ff07ffff003fff0fffff807fff0fffffc063ff1fff
+ffc001ff3f03ffe000ff7800fff000ff70007ff000ffe0003ff800ffc0001ff800ff80000ffc00ff
+00000ffc00ff000007fc00ff000007fc00ff000003fe00ff000003fe00ff000003fe00ff000003fe
+00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff0000
+01fe00ff000001fe00ff000001fc00ff000001fc00ff000001fc00ff000001fc00ff000003f800ff
+000003f800ff000003f000ff000003f000ff000007e000ff800007e000ff80000fc000ffc0001f80
+00ffc0001f8000ffe0003f0000fff800fe0000ff7e03fc0000ff3ffff00000ff1fffc00000ff03fe
+000000ff0000000000ff0000000000ff0000000000ff0000000000ff0000000000ff0000000000ff
+0000000000ff0000000000ff0000000000ff0000000000ff0000000000ff0000000000ff00000000
+00ff0000000000ff0000000001ff8000000001ff8000000007ffe0000000fffffe000000fffffe00
+0000>} imagemask
+ }
+ 112 /G70 MSTT31c1f0 AddChar
+/G61 [44.0 0.0 3.0 -1.0 45.0 46.0]
+/G61 {
+ 42 47 true [1 0 0 -1 -3.0 46.0] {<0007ff000000003ffff0000000fffffc000003fc07fe000007f001ff00000fe000ff00000fc0007f
+80001fc0007f80001fc0007fc0003fc0003fc0003fc0003fc0003fc0003fc0003fc0003fc0003fc0
+003fc0001f80003fc0000f00003fc0000000007fc000000003ffc00000001fffc00000007fbfc000
+0003fc3fc000000fe03fc000003f803fc00000fe003fc00001f8003fc00007f0003fc0000fe0003f
+c0001fc0003fc0003f80003fc0003f80003fc0007f00003fc0007f00003fc000ff00003fc000ff00
+003fc000ff00003fc000ff00003fc000ff80007fc000ff8000ffc000ffc003ffc0407fe007ffe0c0
+7ff83f3fe3c07ffffe3fff803ffffc3fff001ffff01ffe000fffe01ffc0007ff800ff00000fe0007
+c000>} imagemask
+ }
+ 97 /G61 MSTT31c1f0 AddChar
+/G63 [44.0 0.0 3.0 -1.0 41.0 46.0]
+/G63 {
+ 38 47 true [1 0 0 -1 -3.0 46.0] {<00007fc0000007fff800001ffffc00003f01ff0000fc00ff8001f8007fc003f0003fe007e0003fe0
+07e0003ff00fc0003ff01fc0003ff01f80001ff03f80001ff03f80000fe07f000007c07f00000000
+7f000000007f00000000ff00000000ff00000000ff00000000ff00000000ff00000000ff00000000
+ff80000000ff80000000ff80000000ff80000000ffc00000047fc000000c7fe000000c7fe0000018
+7ff00000183ff00000383ff80000703ffc0000701ffe0001e01fff8003e00fffe01fc007ffffffc0
+03ffffff8001ffffff0000fffffe00007ffffc00003ffff000000fffc0000001fe0000>} imagemask
+ }
+ 99 /G63 MSTT31c1f0 AddChar
+/G65 [44.0 0.0 3.0 -1.0 41.0 46.0]
+/G65 {
+ 38 47 true [1 0 0 -1 -3.0 46.0] {<0000ff80000007fff000001ffffc00007e07ff0000f801ff8001f000ffc003e0007fe007c0003fe0
+0f80001ff00f00001ff01f00001ff83f00000ff83e00000ff83e00000ffc7e00000ffc7ffffffffc
+7ffffffffc7ffffffffcfe00000000fe00000000fe00000000fe00000000fe00000000fe00000000
+ff00000000ff00000000ff00000000ff00000000ff80000000ff800000047fc000000c7fc000000c
+7fe00000187ff00000183ff80000383ffc0000701ffe0000f01fff8003e00ffff00fe007ffffffc0
+03ffffff8003ffffff0000fffffe00007ffffc00003ffff800000fffe0000001ff0000>} imagemask
+ }
+ 101 /G65 MSTT31c1f0 AddChar
+/G6e [50.0 0.0 1.0 0.0 50.0 46.0]
+/G6e {
+ 49 46 true [1 0 0 -1 -1.0 46.0] {<000e001fc00000007e00fff0000003fe01fff800000ffe07fffc00007ffe0ffffe0000fffe1fffff
+000047fe3f03ff000003fe7801ff800001fee000ff800001ffc0007f800001ff80007fc00001ff00
+007fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001
+fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc0
+0001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe0000
+3fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe
+00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc000
+01fe00003fc00003ff00007fe00003ff00007fe0000fffc001fff800fffffc1fffff80fffffc1fff
+ff80>} imagemask
+ }
+ 110 /G6e MSTT31c1f0 AddChar
+/G6f [50.0 0.0 3.0 -1.0 46.0 46.0]
+/G6f {
+ 43 47 true [1 0 0 -1 -3.0 46.0] {<00007fc000000003fffc0000000fffff0000003f81ff8000007e003fe00000f8001ff00001f8000f
+f80003f00007fc0007e00007fc000fe00003fe000fc00001ff001fc00001ff001fc00000ff803f80
+0000ff803f800000ffc07f8000007fc07f8000007fc07f8000007fc07f8000007fe0ff8000003fe0
+ff8000003fe0ff8000003fe0ff8000003fe0ff8000003fe0ff8000003fe0ff8000003fe0ff800000
+3fe0ffc000003fc0ffc000003fc07fc000003fc07fc000003fc07fe000003f807fe000003f803fe0
+00003f803ff000007f001ff000007f001ff800007e000ff80000fe0007fc0000fc0007fe0001f800
+03fe0001f00001ff0003e00000ffc00fc000003ff03f8000001ffffe00000007fff800000000ffc0
+0000>} imagemask
+ }
+ 111 /G6f MSTT31c1f0 AddChar
+/G74 [28.0 0.0 0.0 -1.0 28.0 60.0]
+/G74 {
+ 28 61 true [1 0 0 -1 0.0 60.0] {<0001000000030000000300000007000000070000000f0000000f0000001f0000001f0000003f0000
+007f000000ff000001ff000003ff00000fff00003fffffc0ffffffc0ffffffc000ff000000ff0000
+00ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff0000
+00ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff0000
+00ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff000000ff0000
+00ff000000ff000000ff803000ff8060007fe1e0007fffc0007fff80003fff80001ffe00000ffc00
+0003f000>} imagemask
+ }
+ 116 /G74 MSTT31c1f0 AddChar
+/G66 [33.0 0.0 3.0 0.0 43.0 70.0]
+/G66 {
+ 40 70 true [1 0 0 -1 -3.0 70.0] {<000000fe0000000fffc000003ffff00000783ff80000f00ffe0001e007fe0003c003ff0007c003ff
+000fc001ff000f8000ff001f80007e001f80003c003f800000003f800000003f800000003f800000
+007f800000007f800000007f800000007f800000007f800000007f800000007f800000007f800000
+007f800000fffffff800fffffff800fffffff800007f800000007f800000007f800000007f800000
+007f800000007f800000007f800000007f800000007f800000007f800000007f800000007f800000
+007f800000007f800000007f800000007f800000007f800000007f800000007f800000007f800000
+007f800000007f800000007f800000007f800000007f800000007f800000007f800000007f800000
+007f800000007f800000007f800000007f800000007f800000007f800000007f800000007f800000
+00ffc0000000ffc0000001ffe0000007fff00000ffffffe000ffffffe000>} imagemask
+ }
+ 102 /G66 MSTT31c1f0 AddChar
+%%EndResource
+
+586 614 994 (Disk space is not infinite) 994 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G53 [56.0 0.0 6.0 -1.0 50.0 68.0]
+/G53 {
+ 44 69 true [1 0 0 -1 -6.0 68.0] {<0001ff000300001ffff00300007ffffc070000ff00ff8f0003fc001fff0007f00007ff000fe00003
+ff001fc00001ff001f800000ff003f8000007f003f8000003f007f0000001f007f0000001f00ff00
+00000f00ff0000000f00ff0000000f00ff8000000700ff8000000700ffc000000700ffe000000700
+fff0000003007ff8000003007ffc000003007ffe000000003fff800000003fffe00000001ffff000
+00000ffffc00000007ffff00000007ffffc0000001ffffe0000000fffff80000007ffffe0000001f
+ffff8000000fffffc0000003fffff0000000fffff80000003ffffc0000001ffffe00000007ffff00
+000001ffff800000007fff800000001fffc00000000fffc000000003ffe000000001ffe060000000
+fff0600000007ff0600000003ff0700000001ff0700000001ff0700000001ff0700000000ff07800
+00000ff0780000000ff07c0000000fe07c0000000fe07e0000000fe07e0000001fc07f0000001fc0
+7f8000003f807fc000003f007fe000007e007ff80001fc007ffe0003f80070ffc01ff000700fffff
+c0006003ffff000060003ff00000>} imagemask
+ }
+ 83 /G53 MSTT31c1f0 AddChar
+/G6d [78.0 0.0 1.0 0.0 77.0 46.0]
+/G6d {
+ 76 46 true [1 0 0 -1 -1.0 46.0] {<000e001fc00003f80000007e00fff0001ffe000003fe01fffc007fff00000ffe07fffe00ffff8000
+7ffe0fffff01ffffc000fffe1fffff03ffffe00047fe3e07ff87c07fe00003fe7801ff8f003ff000
+03fee000ff9c001ff00001ffc0007ff8000ff00001ff80007ff0000ff80001ff00007fe00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f80001fe00003fc00007f800
+01fe00003fc00007f80003ff00007fe0000ffc0003ff00007fe0000ffc000fffc001fff8003fff00
+fffffc1fffff83fffff0fffffc1fffff83fffff0>} imagemask
+ }
+ 109 /G6d MSTT31c1f0 AddChar
+/G6c [28.0 0.0 3.0 0.0 25.0 70.0]
+/G6c {
+ 22 70 true [1 0 0 -1 -3.0 70.0] {<000e00007e0003fe000ffe007ffe00fffe0047fe0003fe0001fe0001fe0001fe0001fe0001fe0001
+fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe
+0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe00
+01fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001
+fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0001fe0003ff0003ff
+000fffc0fffffcfffffc>} imagemask
+ }
+ 108 /G6c MSTT31c1f0 AddChar
+/G64 [50.0 0.0 3.0 -1.0 49.0 70.0]
+/G64 {
+ 46 71 true [1 0 0 -1 -3.0 70.0] {<000000000e00000000007e0000000003fe000000000ffe000000007ffe00000000fffe00000000c7
+fe0000000003fe0000000003fe0000000001fe0000000001fe0000000001fe0000000001fe000000
+0001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe00
+00000001fe0000000001fe0000000001fe0000000001fe0000007f81fe000003fff1fe00000ffff9
+fe00003f81fdfe00007e007ffe0000fc001ffe0001f8000ffe0003f00007fe0003e00007fe0007e0
+0003fe000fc00003fe000fc00003fe001f800001fe001f800001fe003f800001fe003f000001fe00
+7f000001fe007f000001fe007f000001fe007f000001fe00ff000001fe00ff000001fe00ff000001
+fe00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff800001fe00ff800001fe00ff80
+0001fe00ff800001fe007fc00001fe007fc00001fe007fe00001fe003fe00001fe003ff00001fe00
+3ff80001fe001ffc0003fe000ffe0007ff000fff801fff0007ffe07dff8c03fffff9fffc01fffff1
+fff800ffffe1ffc0003fffc1ff00001fff01f8000003fc01c000>} imagemask
+ }
+ 100 /G64 MSTT31c1f0 AddChar
+/G68 [50.0 0.0 1.0 0.0 50.0 70.0]
+/G68 {
+ 49 70 true [1 0 0 -1 -1.0 70.0] {<000e0000000000007e000000000003fe00000000000ffe00000000007ffe0000000000fffe000000
+0000c7fe000000000003fe000000000001fe000000000001fe000000000001fe000000000001fe00
+0000000001fe000000000001fe000000000001fe000000000001fe000000000001fe000000000001
+fe000000000001fe000000000001fe000000000001fe000000000001fe000000000001fe00000000
+0001fe000000000001fe001fc0000001fe00fff0000001fe03fff8000001fe07fffc000001fe0fff
+fe000001fe1fffff000001fe3e07ff000001fe7801ff800001fee000ff800001ffc0007f800001ff
+80007f800001ff00007fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc000
+01fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003f
+c00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00
+003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001
+fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc0
+0001fe00003fc00001fe00003fc00003ff00007fe00003ff00007fe0000fffc001fff800fffffc1f
+ffff80fffffc1fffff80>} imagemask
+ }
+ 104 /G68 MSTT31c1f0 AddChar
+/G72 [33.0 0.0 1.0 0.0 33.0 46.0]
+/G72 {
+ 32 46 true [1 0 0 -1 -1.0 46.0] {<000e00f0007e03fc01fe07fe0ffe0ffe7ffe1ffffffe3fffc7fe3fff03fe71ff01fee0fe01fec07e
+01ffc01c01ff800001ff000001ff000001fe000001fe000001fe000001fe000001fe000001fe0000
+01fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe0000
+01fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe000001fe0000
+01ff000003ff000003ff80000fffe000fffffe00fffffe00>} imagemask
+ }
+ 114 /G72 MSTT31c1f0 AddChar
+%%EndResource
+
+1 7 SJ
+586 758 2329 (Some installations need a mechanism to control allocation) 2329 SB
+1 2 SJ
+586 878 521 (of disk space) 521 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G71 [50.0 0.0 3.0 -21.0 49.0 46.0]
+/G71 {
+ 46 67 true [1 0 0 -1 -3.0 46.0] {<00003fe00e000001fffc1e000007ffff7e00001fc07ffe00003f001ffe0000fc000ffe0001f80007
+fe0003f00003fe0007e00003fe0007e00001fe000fc00001fe001fc00001fe001f800001fe003f80
+0001fe003f800001fe003f800001fe007f000001fe007f000001fe007f000001fe007f000001fe00
+ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff000001fe00ff000001
+fe00ff800001fe00ff800001fe00ff800001fe00ff800001fe007fc00001fe007fc00001fe007fe0
+0001fe007fe00001fe003ff00003fe003ff80003fe001ffc0007fe001fff001dfe000fffc079fe00
+07fffff9fe0007fffff1fe0003ffffe1fe0001ffff81fe00007fff01fe00003ffc01fe000007f001
+fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe000000
+0001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe00
+00000001fe0000000001fe0000000003ff0000000003ff000000000fffc0000000fffffc000000ff
+fffc>} imagemask
+ }
+ 113 /G71 MSTT31c1f0 AddChar
+/G75 [50.0 0.0 1.0 -1.0 50.0 45.0]
+/G75 {
+ 49 46 true [1 0 0 -1 -1.0 45.0] {<fffe001fffc000fffe001fffc0000ffe0001ffc00003fe00007fc00003fe00007fc00001fe00003f
+c00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00
+003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001
+fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc0
+0001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe0000
+3fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe00003fc00001fe
+00007fc00001ff0000ffc00000ff0001ffc00000ff8007bfe00000ffc00f3fe000007ff07e3ff180
+007ffffc3fff80003ffff83fff00001ffff03ff800000fffe03fe0000007ff803f00000001fc0038
+0000>} imagemask
+ }
+ 117 /G75 MSTT31c1f0 AddChar
+/G77 [72.0 0.0 1.0 -1.0 73.0 45.0]
+/G77 {
+ 72 46 true [1 0 0 -1 -1.0 45.0] {<ffffe01ffffc003fffffffe01ffffc003fff3fff0003fff00003fc0ffe0000ffe00000f007fe0000
+7fc00000e003fe00007fc00000e003fe00003fc00001c001fe00003fe000018001ff00001fe00003
+8001ff00001fe000038000ff00000ff000070000ff80000ff0000700007f80000ff8000700007fc0
+000ff8000e00007fc0001ffc000e00003fc0001ffc000e00003fe0003ffc001c00001fe0003bfe00
+1c00001ff00079fe001c00001ff00071ff003800000ff000f0ff003800000ff800e0ff0038000007
+f801e0ff8070000007fc01c07f8070000007fc03c07fc0f0000003fc03803fc0e0000003fe07803f
+e0e0000001fe07003fe1e0000001fe0f001fe1c0000001ff0e001ff1c0000000ff1e000ff3c00000
+00ff9c000ffb800000007fbc0007fb800000007fb80007ff800000007ff80007ff000000003ff000
+03ff000000003ff00003ff000000001fe00001fe000000001fe00001fe000000001fc00001fc0000
+00000fc00000fc000000000f800000fc000000000780000078000000000700000078000000000700
+0000780000000002000000300000>} imagemask
+ }
+ 119 /G77 MSTT31c1f0 AddChar
+%%EndResource
+
+586 1021 2192 (Disk quotas allow the administrator to set limits on the) 2192 SB
+
+%%BeginResource: font MSTT31c1f0
+/G62 [50.0 0.0 1.0 -1.0 47.0 70.0]
+/G62 {
+ 46 71 true [1 0 0 -1 -1.0 70.0] {<000e00000000007e0000000003fe000000000ffe000000007ffe00000000fffe00000000c7fe0000
+000003fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe
+0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe00000000
+01fe0000000001fe0000000001fe0000000001fe0000000001fe003f800001fe01ffe00001fe07ff
+f80001fe0ffffe0001fe1fffff0001fe3fffff8001fe7fffff8001fefc0fffc001fff001ffe001ff
+c000ffe001ff80007ff001ff00003ff001fe00001ff801fe00001ff801fe00000ff801fe00000ff8
+01fe000007fc01fe000007fc01fe000007fc01fe000003fc01fe000003fc01fe000003fc01fe0000
+03fc01fe000003fc01fe000003fc01fe000003fc01fe000003fc01fe000003f801fe000003f801fe
+000003f801fe000003f801fe000007f001fe000007f001fe000007f001fe000007e001fe00000fc0
+01fe00000fc001fe00001f8001fe00001f0001fe00003e0001ff80007c0001ffc000f80000fff001
+f000003ffc0fe000000fffff80000001fffe000000003ff00000>} imagemask
+ }
+ 98 /G62 MSTT31c1f0 AddChar
+/G2f [28.0 0.0 0.0 -1.0 28.0 70.0]
+/G2f {
+ 28 71 true [1 0 0 -1 0.0 70.0] {<000000f0000001f0000001e0000001e0000003e0000003c0000003c0000007c00000078000000780
+00000f8000000f0000000f0000001f0000001e0000001e0000003e0000003c0000003c0000007c00
+00007800000078000000f8000000f0000000f0000001f0000001e0000001e0000003e0000003c000
+0003c0000007c0000007800000078000000f0000000f0000000f0000001e0000001e0000001e0000
+003c0000003c0000003c000000780000007800000078000000f0000000f0000000f0000001e00000
+01e0000001e0000003c0000003c0000003c000000780000007800000078000000f0000000f000000
+0f0000001e0000001e0000001e0000003c0000003c0000003c000000780000007800000078000000
+f0000000>} imagemask
+ }
+ 47 /G2f MSTT31c1f0 AddChar
+/G3a [28.0 0.0 9.0 -1.0 20.0 46.0]
+/G3a {
+ 11 47 true [1 0 0 -1 -9.0 46.0] {<1f003f807fc0ffe0ffe0ffe0ffe0ffe07fc03f801f00000000000000000000000000000000000000
+00000000000000000000000000000000000000000000000000000000000000001f003f807fc0ffe0
+ffe0ffe0ffe0ffe07fc03f801f00>} imagemask
+ }
+ 58 /G3a MSTT31c1f0 AddChar
+%%EndResource
+
+2 5 SJ
+586 1141 1589 (number of allocated blocks and/or files:) 1589 SB
+
+%%BeginResource: font MSTT31c1fd
+/MSTT31c1fd [75.0 0 0 0 0 0] 53 -104 [-75.0 -75.0 75.0 75.0] [1 75 div 0 0 1 75 div 0 0] /MSTT31c1fd GreNewFont
+%%EndResource
+
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+
+%%BeginResource: font MSTT31c1fd
+/G96 [38.0 0.0 -1.0 17.0 39.0 20.0]
+/G96 {
+ 40 3 true [1 0 0 -1 1.0 20.0] {<ffffffffffffffffffffffffffffff>} imagemask
+ }
+ 150 /G96 MSTT31c1fd AddChar
+%%EndResource
+
+623 1280 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G6c [21.0 0.0 3.0 0.0 19.0 52.0]
+/G6c {
+ 16 52 true [1 0 0 -1 -3.0 52.0] {<00e003e00fe07fe0dfe00fe007e007e007e007e007e007e007e007e007e007e007e007e007e007e0
+07e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e0
+07e007e007e007e007e007e007e007e007e00ff01ff8ffff>} imagemask
+ }
+ 108 /G6c MSTT31c1fd AddChar
+/G69 [21.0 0.0 3.0 0.0 19.0 52.0]
+/G69 {
+ 16 52 true [1 0 0 -1 -3.0 52.0] {<03c007e00ff00ff00ff00ff007e003c000000000000000000000000000000000000000e003e00fe0
+7fe0dfe00fe007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e007e0
+07e007e007e007e007e007e007e007e007e00ff01ff8ffff>} imagemask
+ }
+ 105 /G69 MSTT31c1fd AddChar
+/G6d [57.0 0.0 1.0 0.0 57.0 35.0]
+/G6d {
+ 56 35 true [1 0 0 -1 -1.0 35.0] {<00e00fc001f80003e07fe007fe000fe0fff81fff007fe3fff83fff80dfe783fc783fc00fee01fce0
+1fc007f800ffc00fc007f000ff000fe007e0007e0007e007e0007e0007e007e0007e0007e007e000
+7e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007
+e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007
+e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e0007e007e0007e
+0007e007e0007e0007e007e0007e0007e007e0007e0007e00ff000ff000ff01ff801ff801ff8ffff
+0ffff0ffff>} imagemask
+ }
+ 109 /G6d MSTT31c1fd AddChar
+/G74 [21.0 0.0 0.0 -1.0 21.0 45.0]
+/G74 {
+ 21 46 true [1 0 0 -1 0.0 45.0] {<00100000300000300000700000700000f00000f00001f00003f00007f0001ff0007ffff0fffff003
+f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f0
+0003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f00003f018
+03f83001fc7001ffe000ffc000ff80003e00>} imagemask
+ }
+ 116 /G74 MSTT31c1fd AddChar
+/G73 [29.0 0.0 4.0 -1.0 27.0 35.0]
+/G73 {
+ 23 36 true [1 0 0 -1 -4.0 35.0] {<01fe0807fff81e03f83c00f8780078700038700038f00018f00018f80008fc0008fe00007f80007f
+e0003ff8001ffe000fff0003ffc001ffe0007ff0001ff80007fc0001fc0000fe00007e80007e8000
+3ec0003ec0003ee0003cf0003cf80078fc00f0ff81e0ffff8083fe00>} imagemask
+ }
+ 115 /G73 MSTT31c1fd AddChar
+/G20 [19.0 0.0 0.0 0.0 0.0 0.0]
+/G20 {
+}
+ 32 /G20 MSTT31c1fd AddChar
+/G61 [33.0 0.0 3.0 -1.0 34.0 35.0]
+/G61 {
+ 31 36 true [1 0 0 -1 -3.0 35.0] {<007fc00003fff80007c1fc001f007e003e003f003e003f007e001f807e001f807e001f807e001f80
+7e001f803c001f8000003f800001ff800007df80003f1f8000f81f8001e01f8007c01f800f801f80
+1f001f803e001f807e001f807c001f80fc001f80fc001f80fc001f80fc001f80fe003f80fe007f82
+7f00ff867f83dfce3fff1ffc3ffe1ff81ff80fe007e00780>} imagemask
+ }
+ 97 /G61 MSTT31c1fd AddChar
+/G72 [25.0 0.0 1.0 0.0 25.0 35.0]
+/G72 {
+ 24 35 true [1 0 0 -1 -1.0 35.0] {<00e07c03e0fe0fe1ff7fe3ffdfe7ff0fee7f07ec3e07f80e07f00007f00007e00007e00007e00007
+e00007e00007e00007e00007e00007e00007e00007e00007e00007e00007e00007e00007e00007e0
+0007e00007e00007e00007e00007f0000ff0001ffc00ffff00>} imagemask
+ }
+ 114 /G72 MSTT31c1fd AddChar
+/G65 [33.0 0.0 3.0 -1.0 31.0 35.0]
+/G65 {
+ 28 36 true [1 0 0 -1 -3.0 35.0] {<001fe000007ffc0001c1fe0003807f0007003f800e001fc01c001fe03c000fe038000fe038000ff0
+78000ff07ffffff07ffffff0f8000000f8000000f8000000f8000000f8000000fc000000fc000000
+fc000000fc000000fe000010fe0000307f0000307f8000607fc000603fe000e03ff001c01ffc07c0
+0fffff8007ffff0003fffe0001fffc0000fff800001fc000>} imagemask
+ }
+ 101 /G65 MSTT31c1fd AddChar
+/G6e [38.0 0.0 1.0 0.0 37.0 35.0]
+/G6e {
+ 36 35 true [1 0 0 -1 -1.0 35.0] {<00e01f800003e07fe0000fe0fff0007fe3fff800dfe783fc000fee01fc0007fc00fc0007f000fe00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+0ff000ff001ff801ff80ffff0ffff0>} imagemask
+ }
+ 110 /G6e MSTT31c1fd AddChar
+/G67 [37.0 0.0 2.0 -16.0 36.0 35.0]
+/G67 {
+ 34 51 true [1 0 0 -1 -2.0 35.0] {<000ff00000003ffc000000f83f000001f00fffc003e00fffc007c007e0000fc003f0000f8003f000
+0f8003f8001f8001f8001f8001f8001f8001f8001f8001f8001f8001f8001f8001f8001fc001f800
+0fc001f0000fc003f00007e003e00003e007c00001f007800000fc1f0000007ffe000000eff00000
+01c0000000038000000007000000000f000000000f000000001f800000001ffff000001ffffff800
+0ffffffe0007ffffff0003ffffff800307ffff800600000fc00e000001c01c000000c038000000c0
+38000000c07800000080f800000180fc00000300fe00000600ff80001c007ff000f8003ffffff000
+0fffffc00003ffff0000003ff00000>} imagemask
+ }
+ 103 /G67 MSTT31c1fd AddChar
+/G64 [38.0 0.0 3.0 -1.0 37.0 52.0]
+/G64 {
+ 34 53 true [1 0 0 -1 -3.0 52.0] {<0000003800000000f800000003f80000001ff800000037f800000003f800000001f800000001f800
+000001f800000001f800000001f800000001f800000001f800000001f800000001f800000001f800
+000001f800000fe1f800003ff9f80000f83df80001e01ff80003c00ff800078007f8000f0003f800
+1f0003f8001e0001f8003e0001f8003e0001f8007c0001f8007c0001f8007c0001f8007c0001f800
+fc0001f800fc0001f800fc0001f800fc0001f800fc0001f800fc0001f800fc0001f800fe0001f800
+fe0001f8007e0001f8007f0001f8007f0001f8003f8001f8003fc001f8001fe003f8001ff00ffc00
+0ffc1dfec007fff9ff8003fff1fc0000ffe1f000003f81c000>} imagemask
+ }
+ 100 /G64 MSTT31c1fd AddChar
+/G6f [38.0 0.0 3.0 -1.0 35.0 35.0]
+/G6f {
+ 32 36 true [1 0 0 -1 -3.0 35.0] {<000ff000003ffe0000f83f8003e01fc007c00fe0078007f00f0003f81f0003f81f0001fc3e0001fc
+3e0000fe7e0000fe7e0000fe7e00007ffe00007ffe00007ffe00007ffe00007ffe00007ffe00007f
+fe00007ffe00007fff00007e7f00007e7f00007e7f00007c3f80007c3f8000f81fc000f81fc000f0
+0fe001e007f003e003f8078001fe0f00007ffc00000ff000>} imagemask
+ }
+ 111 /G6f MSTT31c1fd AddChar
+/G66 [24.0 0.0 2.0 0.0 32.0 52.0]
+/G66 {
+ 30 52 true [1 0 0 -1 -2.0 52.0] {<00007f000001ffc000070ff0000e07f8001c03fc003c01fc007800fc007800fc00f8003800f80000
+00f8000001f8000001f8000001f8000001f8000001f8000001f8000001f80000fffffc00fffffc00
+01f8000001f8000001f8000001f8000001f8000001f8000001f8000001f8000001f8000001f80000
+01f8000001f8000001f8000001f8000001f8000001f8000001f8000001f8000001f8000001f80000
+01f8000001f8000001f8000001f8000001f8000001f8000001f8000001f8000003fc000007fc0000
+0fff0000fffff800>} imagemask
+ }
+ 102 /G66 MSTT31c1fd AddChar
+/G79 [36.0 0.0 0.0 -16.0 36.0 34.0]
+/G79 {
+ 36 50 true [1 0 0 -1 0.0 34.0] {<ffff003ff03ff80007c01ff00003800ff000030007f000070007f000060003f000060003f8000e00
+01f8000c0001fc000c0000fc00180000fe001800007e003800007f003000003f003000003f806000
+001f806000001fc0c000000fc0c000000fe0c0000007e180000007f180000003f300000003fb0000
+0001ff00000001fe00000000fe00000000fc000000007c0000000078000000003800000000380000
+00003000000000300000000060000000006000000000e000000000c000000000c000000001800000
+000380000000030000001f0f0000003ffe0000007ffe0000007ffc0000007ff80000003ff0000000
+3fe00000000f80000000>} imagemask
+ }
+ 121 /G79 MSTT31c1fd AddChar
+/G62 [38.0 0.0 1.0 -1.0 35.0 52.0]
+/G62 {
+ 34 53 true [1 0 0 -1 -1.0 52.0] {<00e000000003e00000000fe00000007fe0000000dfe00000000fe000000007e000000007e0000000
+07e000000007e000000007e000000007e000000007e000000007e000000007e000000007e0000000
+07e000000007e03f800007e0ffe00007e1fff00007e3fff80007e7fffc0007ef07fe0007fc01ff00
+07f800ff0007f0007f8007e0003f8007e0003f8007e0001f8007e0001fc007e0001fc007e0000fc0
+07e0000fc007e0000fc007e0000fc007e0000fc007e0000fc007e0000fc007e0000fc007e0000f80
+07e0000f8007e0001f8007e0001f0007e0001f0007e0001e0007e0003e0007e0003c0007e0007800
+07f800f00007fc01e00001ff078000003ffe00000007f80000>} imagemask
+ }
+ 98 /G62 MSTT31c1fd AddChar
+%%EndResource
+
+5 7 SJ
+717 1280 1226 (limits are managed on a file system basis) 1226 SB
+623 1388 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G71 [38.0 0.0 3.0 -16.0 37.0 35.0]
+/G71 {
+ 34 51 true [1 0 0 -1 -3.0 35.0] {<0007f81800003ffe780000f81ff80001e00ff80003c007f800078003f8000f0003f8001f0001f800
+1e0001f8003e0001f8003e0001f8007c0001f8007c0001f8007c0001f800fc0001f800fc0001f800
+fc0001f800fc0001f800fc0001f800fc0001f800fc0001f800fc0001f800fe0001f800fe0001f800
+fe0001f8007f0001f8007f0001f8007f8001f8003fc003f8003fe007f8001ff81df8000ffff9f800
+07fff1f80003ffe1f80001ff81f800007e01f800000001f800000001f800000001f800000001f800
+000001f800000001f800000001f800000001f800000001f800000001f800000001f800000001f800
+000003fc00000007fe0000003fffc0>} imagemask
+ }
+ 113 /G71 MSTT31c1fd AddChar
+/G75 [38.0 0.0 1.0 -1.0 37.0 34.0]
+/G75 {
+ 36 35 true [1 0 0 -1 -1.0 34.0] {<ffe00ffe001fe001fe000fe000fe0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007f000fe0003f003fe0003f8077f0003fc1e7fb001fffc7fe0
+00fff07f00007fe07c00001f807000>} imagemask
+ }
+ 117 /G75 MSTT31c1fd AddChar
+/G63 [33.0 0.0 3.0 -1.0 31.0 35.0]
+/G63 {
+ 28 36 true [1 0 0 -1 -3.0 35.0] {<000ff000007ffc0000f07f0003c03f8007801fc00f001fc01f000fe01e000fe03e000fe03e0007e0
+7c0003c07c0000007c000000fc000000fc000000fc000000fc000000fc000000fc000000fe000000
+fe000000fe000000ff0000107f0000307f0000307f8000607fc000603fe000c03ff001c01ffc0f80
+0fffff8007ffff0003fffe0001fffc0000fff000001f8000>} imagemask
+ }
+ 99 /G63 MSTT31c1fd AddChar
+/G77 [53.0 0.0 1.0 -1.0 53.0 34.0]
+/G77 {
+ 52 35 true [1 0 0 -1 -1.0 34.0] {<fffc0fffc03ff07ff003ff0007e01fe000fe0003800fe000fe0003000fe0007e00030007e0007e00
+060007e0003f00060007f0003f00060003f0003f000c0003f0003f800c0001f8003f800c0001f800
+7fc0180001fc006fc0180000fc00efc0180000fc00cfe0300000fe00c7e03000007e0187e0300000
+7e0183f06000003f0303f06000003f0303f8e000003f8601f8c000001f8601f8c000001f8c01fdc0
+00001fcc00fd8000000fd800fd8000000fd8007f80000007f8007f00000007f0007f00000007f000
+3e00000003e0003e00000003e0003e00000003c0001c00000001c0001c0000000180001c00000000
+8000080000>} imagemask
+ }
+ 119 /G77 MSTT31c1fd AddChar
+/G68 [38.0 0.0 1.0 0.0 37.0 52.0]
+/G68 {
+ 36 52 true [1 0 0 -1 -1.0 52.0] {<00e000000003e00000000fe00000007fe0000000dfe00000000fe000000007e000000007e0000000
+07e000000007e000000007e000000007e000000007e000000007e000000007e000000007e0000000
+07e000000007e01f800007e07fe00007e0fff00007e3fff80007e783f80007ee01fc0007fc00fc00
+07f000fe0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e0007e00
+07e0007e000ff000ff001ff801ff80ffff0ffff0>} imagemask
+ }
+ 104 /G68 MSTT31c1fd AddChar
+/G70 [38.0 0.0 1.0 -16.0 35.0 35.0]
+/G70 {
+ 34 51 true [1 0 0 -1 -1.0 35.0] {<00e01f800003e07fe0000fe1fff0007fe3fff800ffe7fffc000fef07fe0007ee01ff0007f800ff00
+07f0007f8007e0003f8007e0003f8007e0001f8007e0001fc007e0001fc007e0001fc007e0000fc0
+07e0000fc007e0000fc007e0000fc007e0000fc007e0000fc007e0000fc007e0000f8007e0000f80
+07e0000f8007e0001f0007e0001f0007e0001f0007e0003e0007f0003c0007f0007c0007f8007800
+07fc00f00007ff03e00007e7ff800007e1fe000007e000000007e000000007e000000007e0000000
+07e000000007e000000007e000000007e000000007e000000007e000000007e000000007e0000000
+0ff00000001ff8000000ffff000000>} imagemask
+ }
+ 112 /G70 MSTT31c1fd AddChar
+%%EndResource
+
+717 1388 1558 (quotas can be associated with users and user groups) 1558 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G34 [29.0 0.0 1.0 0.0 26.0 40.0]
+/G34 {
+ 25 40 true [1 0 0 -1 -1.0 40.0] {<0000f0000000f0000001f0000001f0000003f0000007f0000007f000000df000001df0000019f000
+0031f0000031f0000061f00000e1f00000c1f0000181f0000181f0000301f0000701f0000601f000
+0c01f0000c01f0001801f0003801f0003001f0006001f000e001f000ffffff80ffffff80ffffff80
+0001f0000001f0000001f0000001f0000001f0000001f0000001f0000001f0000001f0000001f000
+>} imagemask
+ }
+ 52 /G34 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (4) 29 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d0439a4b687a9024e596c4b1dde5fe3f345cafae8cf4c808fb96646624e02e6ffc7fee976c6bc04297090beef82b38032beb8ee2f
+6bc81681d15818312c65bab2e7a843bdd3f258a0a30ee0b1c119aff67bb748720cea1369ef4bc2b2aa5b4c1af425550815b3e5607df8333913f207b8e5750be8
+ea52046b1728bbe207ca2300df72213da0e76feaea3f072404ebb5a7d7c446ac0c712bebbc02a47962fbd614355b5948e7d659101d06ea214be3a60a4699f41f
+ba51b6a14fd6436539f3f3f178ea676bf5eb0ccb02b42c86d0ea544cefcebaf0d98921a2ccdf71b977889a5a877dbe0dad197f68c7b9d48da8c3268038eb4550
+7174185a8934678b3172e281758f08f294af4f839c9cba87637bf400551254e6e21cda
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-6 3 SJ
+256 284 1650 (Principles of disk quotas) 1650 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G67 [49.0 0.0 3.0 -21.0 47.0 46.0]
+/G67 {
+ 44 67 true [1 0 0 -1 -3.0 46.0] {<0000ff8000000007fff80000001f81fe0000003e007ffff000fc003ffff001f8001ffff001f8001f
+f00003f0000ff00007f0000ff80007e00007f8000fe00007f8000fe00007fc000fe00003fc001fe0
+0003fc001fe00003fc001fe00003fc001fe00003fc001fe00003fc001fe00003fc001fe00003fc00
+1ff00003f8000ff00003f8000ff00003f80007f80007f00007f80007e00003fc0007e00003fc000f
+c00001fe001f8000007f003f0000003fc0fc0000001ffff000000038ff80000000700000000000e0
+0000000003e00000000007c00000000007c0000000000fc0000000001ff0000000001fffffc00000
+1ffffffff0001ffffffffe000fffffffff0007ffffffff8003ffffffffc000ffffffffe001c0ffff
+ffe003c000001ff00780000001f00700000000f00f00000000701e00000000703e00000000703e00
+000000607e00000000e07e00000000e0ff00000001c0ff8000000380ffe000000f00fff800003e00
+7fff8003fc003ffffffff8001ffffffff00007ffffffc00001ffffff0000007ffff800000007ff80
+0000>} imagemask
+ }
+ 103 /G67 MSTT31c1f0 AddChar
+%%EndResource
+
+4 9 SJ
+586 614 2281 (Disk quotas can be associated with users and user groups) 2281 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G54 [61.0 0.0 3.0 0.0 59.0 67.0]
+/G54 {
+ 56 67 true [1 0 0 -1 -3.0 67.0] {<7ffffffffffffe7ffffffffffffe7ffffffffffffe7f8001ff0003fe7e0001ff00007e7c0001ff00
+003e780001ff00001ef00001ff00000fe00001ff000007e00001ff000007e00001ff000007c00001
+ff000003c00001ff000003c00001ff000003000001ff000000000001ff000000000001ff00000000
+0001ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff0000
+00000001ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff
+000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff0000000000
+01ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff000000
+000001ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff00
+0000000001ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001
+ff000000000001ff000000000001ff000000000001ff000000000001ff000000000001ff00000000
+0001ff000000000001ff000000000001ff000000000001ff000000000003ff800000000003ff8000
+00000007ffc0000000001ffff000000003ffffff80000003ffffff8000>} imagemask
+ }
+ 84 /G54 MSTT31c1f0 AddChar
+/G79 [47.0 0.0 0.0 -21.0 47.0 45.0]
+/G79 {
+ 47 66 true [1 0 0 -1 0.0 45.0] {<fffff8007ffefffff8007ffe3fff800007f00fff000003e007fe000003c007fe0000038003ff0000
+038001ff0000070001ff0000070000ff80000f0000ff80000e00007fc0000e00007fc0001c00003f
+e0001c00003fe0003c00001ff0003800001ff0003800000ff0007000000ff80070000007f800f000
+0007fc00e0000003fc00e0000003fe01c0000001fe01c0000001ff01c0000000ff0380000000ff83
+80000000ff87800000007fc7000000007fc7000000003fee000000003fee000000001ffe00000000
+1ffc000000000ffc000000000ff80000000007f80000000007f80000000003f00000000003f00000
+000001e00000000001e00000000001e00000000001c00000000001c0000000000380000000000380
+000000000780000000000700000000000700000000000e00000000000e00000000001e0000000000
+1c00000000003c00000007c0780000001ff0f80000001ffff00000003ffff00000003fffe0000000
+3fffc00000003fff800000001fff000000001ffe000000000ff80000000003e000000000>} imagemask
+ }
+ 121 /G79 MSTT31c1f0 AddChar
+%%EndResource
+
+5 10 SJ
+586 758 2328 (They limit the number of blocks and the number of inodes) 2328 SB
+
+%%BeginResource: font MSTT31c1f0
+/G28 [33.0 0.0 4.0 -21.0 31.0 69.0]
+/G28 {
+ 27 90 true [1 0 0 -1 -4.0 69.0] {<00000020000000e0000003c00000078000001e0000003c00000078000000f0000001e0000003c000
+00078000000f8000001f0000003e0000003e0000007c000000fc000000f8000001f8000003f80000
+03f0000007f0000007f000000fe000000fe000000fe000001fe000001fe000001fc000003fc00000
+3fc000003fc000007fc000007fc000007f8000007f8000007f8000007f800000ff800000ff800000
+ff800000ff800000ff800000ff800000ff800000ff800000ff800000ff800000ff800000ff800000
+ff800000ff8000007f8000007f8000007fc000007fc000007fc000007fc000003fc000003fc00000
+3fc000001fc000001fe000001fe000000fe000000fe0000007f0000007f0000007f0000003f00000
+03f8000001f8000000fc000000fc0000007c0000003e0000003f0000001f0000000f80000007c000
+0003c0000001e0000000f0000000780000003c0000000f0000000780000001c0000000e000000020
+>} imagemask
+ }
+ 40 /G28 MSTT31c1f0 AddChar
+/G29 [33.0 0.0 2.0 -21.0 29.0 69.0]
+/G29 {
+ 27 90 true [1 0 0 -1 -2.0 69.0] {<80000000e0000000780000003c0000001f0000000780000003c0000001e0000000f0000000780000
+007c0000003e0000001f0000001f8000000f80000007c0000007e0000003e0000003f0000003f800
+0001f8000001fc000001fc000001fc000000fe000000fe000000ff000000ff0000007f0000007f80
+00007f8000007f8000007fc000007fc000007fc000007fc000003fc000003fc000003fe000003fe0
+00003fe000003fe000003fe000003fe000003fe000003fe000003fe000003fe000003fe000003fe0
+00003fe000003fe000003fc000003fc000003fc000003fc000007fc000007fc000007f8000007f80
+00007f8000007f000000ff000000ff000000fe000000fe000000fe000001fc000001fc000001f800
+0003f8000003f0000003e0000007e0000007c000000f8000000f8000001f0000003e0000003c0000
+0078000000f0000001e0000003c00000078000000f0000003c00000078000000e000000080000000
+>} imagemask
+ }
+ 41 /G29 MSTT31c1f0 AddChar
+%%EndResource
+
+4 7 SJ
+586 878 1804 (\(files\) that a user/group is allowed to allocate) 1804 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G4c [59.0 0.0 2.0 0.0 57.0 67.0]
+/G4c {
+ 55 67 true [1 0 0 -1 -2.0 67.0] {<fffffff8000000fffffff800000007fffe0000000001fff80000000000ffe00000000000ffe00000
+0000007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc0
+00000000007fc000000000007fc000000000007fc000000000007fc000000000007fc00000000000
+7fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc0000000
+00007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc000
+000000007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007f
+c000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000
+007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc00000
+0000007fc000000000007fc000000000007fc000000000007fc000000006007fc00000000e007fc0
+0000000c007fc00000000c007fc00000001c007fc00000001c007fc000000038007fc00000003800
+7fc000000078007fc0000000f0007fc0000001f0007fc0000003f000ffe0000007f000ffe000001f
+e001fff80000ffe007ffffffffffe0ffffffffffffc0ffffffffffffc0>} imagemask
+ }
+ 76 /G4c MSTT31c1f0 AddChar
+%%EndResource
+
+586 1021 288 (Limits:) 288 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1160 38 (\226) 38 SB
+717 1160 402 (current usage) 402 SB
+623 1268 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G3a [21.0 0.0 7.0 -1.0 15.0 35.0]
+/G3a {
+ 8 36 true [1 0 0 -1 -7.0 35.0] {<3c7effffffff7e3c00000000000000000000000000000000000000003c7effffffff7e3c>} imagemask
+ }
+ 58 /G3a MSTT31c1fd AddChar
+/G78 [37.0 0.0 0.0 0.0 37.0 34.0]
+/G78 {
+ 37 34 true [1 0 0 -1 0.0 34.0] {<ffff01ffc01ffc007f000ff8003c0007f800380003f800300001fc00700000fe00600000fe00c000
+007f018000003f830000003fc70000001fee0000000fec00000007f800000007f000000003f80000
+0001fc00000001fe00000001fe000000037f000000063f8000000c3f8000001c1fc00000380fe000
+00300ff000006007f00000c003f80001c003fc00038001fc00030000fe00070000ff000f0000ff80
+1fc001ffe07ff007fff8>} imagemask
+ }
+ 120 /G78 MSTT31c1fd AddChar
+/G6b [37.0 0.0 1.0 0.0 37.0 52.0]
+/G6b {
+ 36 52 true [1 0 0 -1 -1.0 52.0] {<00e000000003e00000000fe00000007fe0000000dfe00000000fe000000007e000000007e0000000
+07e000000007e000000007e000000007e000000007e000000007e000000007e000000007e0000000
+07e000000007e000000007e007ffe007e003fe0007e001f00007e001e00007e001c00007e0030000
+07e006000007e00c000007e038000007e070000007e0e0000007e1c0000007e380000007e7800000
+07efc0000007ffe0000007efe0000007e7f0000007e3f8000007e3fc000007e1fe000007e0fe0000
+07e07f000007e03f800007e03fc00007e01fe00007e00fe00007e007f00007e003f80007e003fc00
+07e001fe000ff001ff801ff801fff0ffff07fff0>} imagemask
+ }
+ 107 /G6b MSTT31c1fd AddChar
+/G2f [21.0 0.0 0.0 -1.0 21.0 52.0]
+/G2f {
+ 21 53 true [1 0 0 -1 0.0 52.0] {<0000380000780000700000700000e00000e00000e00001c00001c00001c000038000038000038000
+0700000700000700000e00000e00000e00001c00001c00001c000038000038000038000070000070
+0000700000e00000e00000e00001c00001c00001c000038000038000038000070000070000070000
+0e00000e00000e00001c00001c00001c0000380000380000380000700000700000700000e00000>} imagemask
+ }
+ 47 /G2f MSTT31c1fd AddChar
+%%EndResource
+
+717 1268 2212 (soft limit: maximal number of blocks/inodes that a user/group is expected) 2212 SB
+-1 1 SJ
+717 1359 220 (to need) 220 SB
+623 1467 38 (\226) 38 SB
+717 1467 2205 (hard limit: maximal number of blocks/inodes that a user/group is allowed) 2205 SB
+-1 1 SJ
+717 1557 311 (to allocate) 311 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G35 [29.0 0.0 3.0 0.0 25.0 39.0]
+/G35 {
+ 22 39 true [1 0 0 -1 -3.0 39.0] {<00fffc00fff801fff801fff003fff00300000600000600000c00000c00001f80001ff0003ffc003f
+fe007fff8003ffc0007fc0001fe00007f00003f00001f00000f80000f80000780000780000780000
+780000780000700000700000700000e00000c00001c0700380fc0f00fffc007ff8001fc000>} imagemask
+ }
+ 53 /G35 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (5) 29 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d013dcfd52cf6001bd0d7663003bf0bea02713009112d390690aa8cec87224298d4c086f147a6b31276874f777b1552311010bf1a
+02aa65d153b06e732c7e0ffde68b3179b32ebd2d3d8bc355078d5346e8a53371f430cca006c34facac0d84562ed903c711b1506f186956159070ec7f114ff4d3
+59e5ee8ff1d184226fed9ea73198dfc19f44a91fe1380a15adaabcc4c52aa3c0690bcddedd640992169f01e19541e67a31503a333d47c5bde2cf24604721b6f0
+be8540fe1805b6425f3999bf18b8b12287e1ba05c78f36d229d0
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+256 305 1695 (Principles of disk quotas \(2\)) 1695 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G57 [95.0 0.0 3.0 -1.0 94.0 67.0]
+/G57 {
+ 91 68 true [1 0 0 -1 -3.0 67.0] {<ffffff03fffffe0000ffffe0ffffff03fffffe0000ffffe00ffff0007fffe000000fff0007ffe000
+1fff80000003fc0003ffc0000fff80000001f80001ffc00007ff00000001f80000ffc00007ff0000
+0001f00000ffc00003ff00000001f00000ffc00003ff80000001e000007fc00001ff80000001e000
+007fe00001ff80000001c000007fe00000ff80000003c000003fe00000ffc0000003c000003ff000
+00ffc00000038000001ff000007fc00000078000001ff000007fe00000078000001ff800007fe000
+00070000000ff800003fe000000f0000000ff800003ff000000f0000000ffc00003ff000000e0000
+0007fc00001ff000001e00000007fc00001ff800001c00000007fe00001ff800003c00000003fe00
+003ff800003c00000003fe00003ffc00003800000001ff00003ffc00007800000001ff00007ffc00
+007800000001ff00007ffe0000f000000000ff80007bfe0000f000000000ff80007bff0000e00000
+0000ffc000fbff0001e0000000007fc000f1ff0001e0000000007fc000f1ff8001c0000000007fe0
+01f1ff8003c0000000003fe001e0ff8003c0000000003fe001e0ffc00780000000001ff003e0ffc0
+0780000000001ff003c07fc00700000000001ff003c07fe00f00000000000ff803c03fe00f000000
+00000ff807c03fe00e00000000000ff807803ff01e000000000007fc07801ff01e000000000007fc
+0f801ff03c000000000007fe0f001ff83c000000000003fe0f000ff838000000000003fe1f000ffc
+78000000000001ff1e000ffc78000000000001ff1e0007fc70000000000001ff3e0007fef0000000
+000000ffbc0007fef0000000000000ffbc0003ffe0000000000000ffbc0003ffe00000000000007f
+f80001ffc00000000000007ff80001ffc00000000000007ff80001ffc00000000000003ff80000ff
+800000000000003ff00000ff800000000000001ff00000ff800000000000001ff000007f00000000
+0000001fe000007f000000000000000fe000007f000000000000000fe000003e000000000000000f
+c000003e0000000000000007c000003c0000000000000007c000001c00000000000000078000001c
+00000000000000038000000800000000>} imagemask
+ }
+ 87 /G57 MSTT31c1f0 AddChar
+/G2c [25.0 0.0 5.0 -16.0 20.0 10.0]
+/G2c {
+ 15 26 true [1 0 0 -1 -5.0 10.0] {<0f803fe07ff0fff8fffcfffcfffcfffe7ffe3ffe1f0e000e000e000e001c001c00180038007000e0
+01c003800f007c00f0008000>} imagemask
+ }
+ 44 /G2c MSTT31c1f0 AddChar
+%%EndResource
+
+4 9 SJ
+586 614 2101 (When the soft limit is reached, a warning message is) 2101 SB
+586 734 283 (printed) 283 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 908 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G78 [51.0 0.0 1.0 0.0 49.0 45.0]
+/G78 {
+ 48 45 true [1 0 0 -1 -1.0 45.0] {<ffffe007fff8ffffe007fff81fff8000ffc007ff00007f0003ff00007e0001ff00007c0000ff8000
+780000ffc000f000007fe001e000003fe001c000003ff003c000001ff8078000000ffc0f00000007
+fe1e00000007fe1c00000003ff3800000001fff800000000fff000000000ffe0000000007fe00000
+00003ff0000000001ff0000000001ff8000000001ffc000000003ffe000000003bfe0000000073ff
+00000000e1ff80000001e0ff80000003c07fc0000007807fe0000007003ff000000e001ff000001c
+001ff800003c000ffc0000780007fe0000700003fe0000f00003ff0001e00001ff8003e00000ffc0
+07e00000ffc00ff00000ffe01ff80003fff87fff001fffff7fff001fffff>} imagemask
+ }
+ 120 /G78 MSTT31c1f0 AddChar
+%%EndResource
+
+6 9 SJ
+586 878 2329 (The hard limit cannot be exceeded \(system calls return the) 2329 SB
+2 1 SJ
+586 998 218 (error ) 218 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+806 1002 360 (EDQUOT) 360 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1166 998 33 (\)) 33 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1171 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G47 [72.0 0.0 4.0 -1.0 71.0 68.0]
+/G47 {
+ 67 69 true [1 0 0 -1 -4.0 68.0] {<0000000fff00030000000001fffff0030000000007fffffe03000000001ffc00ffc7000000007fc0
+001fff00000001ff000007ff80000003fe000001ff80000007f8000000ff8000000ff00000007f80
+00001fe00000003f8000003fc00000001f8000007f800000000f800000ff800000000f800001ff00
+00000007800001ff0000000007800003fe0000000003800007fc0000000003c00007fc0000000001
+c0000ffc0000000001c0000ff80000000000c0001ff80000000000c0001ff8000000000000003ff0
+000000000000003ff0000000000000003ff0000000000000007ff0000000000000007ff000000000
+0000007fe0000000000000007fe0000000000000007fe000000000000000ffe000000000000000ff
+e00000007fffffe0ffe00000007fffffe0ffe000000003fffe00ffe000000000fff800ffe0000000
+007ff000ffe0000000007ff000ffe0000000003fe000ffe0000000003fe000ffe0000000003fe000
+fff0000000003fe000fff0000000003fe0007ff0000000003fe0007ff0000000003fe0007ff00000
+00003fe0007ff8000000003fe0003ff8000000003fe0003ff8000000003fe0001ffc000000003fe0
+001ffc000000003fe0001ffe000000003fe0000ffe000000003fe0000fff000000003fe00007ff00
+0000003fe00003ff800000003fe00003ff800000003fe00001ffc00000003fe00000ffe00000003f
+e000007ff00000003fe000003ff80000003fe000001ffc0000003fe000000ffe0000003fe0000007
+ff8000003fe0000001ffc00000ffc00000007ff80007ff000000001fff003ffc0000000007ffffff
+f00000000000ffffff00000000000007ffe0000000>} imagemask
+ }
+ 71 /G47 MSTT31c1f0 AddChar
+%%EndResource
+
+2 1 SJ
+586 1141 545 (Grace period:) 545 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1280 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G37 [38.0 0.0 3.0 -1.0 35.0 50.0]
+/G37 {
+ 32 51 true [1 0 0 -1 -3.0 50.0] {<07ffffff0fffffff0fffffff0ffffffe1ffffffe1ffffffe3ffffffc3e00003c3800007c70000078
+60000078400000f8c00000f0000000f0000001f0000001e0000001e0000003e0000003c0000003c0
+00000780000007800000078000000f0000000f0000000f0000001e0000001e0000001e0000003c00
+00003c0000003c000000780000007800000078000000f0000000f0000000f0000001e0000001e000
+0003e0000003c0000003c0000007c0000007800000078000000f8000000f0000000f0000001f0000
+001e0000>} imagemask
+ }
+ 55 /G37 MSTT31c1fd AddChar
+%%EndResource
+
+2 3 SJ
+717 1280 513 (7 days by default) 513 SB
+623 1388 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G57 [70.0 0.0 2.0 -1.0 70.0 50.0]
+/G57 {
+ 68 51 true [1 0 0 -1 -2.0 50.0] {<ffffc1ffffc007fff01ffe007ffc00007f800ffc001ff800003f0007f8000ff800001e0003f8000f
+f800001c0003fc0007f800001c0003fc0007f80000180001fc0003f80000380001fc0003f8000038
+0001fe0003fc0000300000fe0001fc0000700000fe0001fc0000700000ff0001fe00006000007f00
+00fe0000e000007f0000fe0000e000007f8000ff0000c000003f8000ff0001c000003f8001ff0001
+c000003fc001ff80018000001fc001ff80038000001fc003ff80038000001fe0039fc0030000000f
+e0039fc0070000000fe0079fe0070000000ff0070fe00600000007f0070fe00e00000007f0070ff0
+0e00000007f80e07f00c00000003f80e07f01c00000003f80e07f81c00000003fc1c03f818000000
+01fc1c03f83800000001fc1c03fc3800000001fe3801fc3000000000fe3801fc7000000000fe3801
+fe70000000007f7000fee0000000007f7000fee0000000007f70007fe0000000003fe0007fc00000
+00003fe0007fc0000000003fe0003fc0000000001fc0003f80000000001fc0003f80000000001fc0
+001f00000000000f80001f00000000000f80001f00000000000f80000e00000000000700000e0000
+0000000700000e000000000007000004000000>} imagemask
+ }
+ 87 /G57 MSTT31c1fd AddChar
+/G76 [37.0 0.0 1.0 -1.0 36.0 34.0]
+/G76 {
+ 35 35 true [1 0 0 -1 -1.0 34.0] {<ffff007fe03ff8000f800ff800070007f000060007f800060003f8000e0003f8000c0001f8001c00
+01fc00180001fc00180000fe00380000fe003000007e007000007f006000007f006000003f80e000
+003f80c000001f81c000001fc18000000fc18000000fe38000000fe300000007e300000007f70000
+0003f600000003fe00000003fc00000001fc00000001fc00000000f800000000f800000000f00000
+000070000000007000000000200000>} imagemask
+ }
+ 118 /G76 MSTT31c1fd AddChar
+/G2c [19.0 0.0 3.0 -12.0 14.0 7.0]
+/G2c {
+ 11 19 true [1 0 0 -1 -3.0 7.0] {<1e007f80ff80ffc0ffe0ffe07fe03c6000600060004000c000c0018003000e001800f0008000>} imagemask
+ }
+ 44 /G2c MSTT31c1fd AddChar
+/G28 [25.0 0.0 3.0 -16.0 23.0 52.0]
+/G28 {
+ 20 68 true [1 0 0 -1 -3.0 52.0] {<0000100000600000c0000380000600000e00001c0000380000700000f00001e00001e00003c00007
+c00007c0000f80000f80001f80001f80001f00003f00003f00003f00007f00007f00007e00007e00
+007e0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000fe0000
+7e00007e00007f00007f00007f00003f00003f00003f00001f00001f80000f80000f80000f800007
+c00003c00003c00001e00000e00000f000007800003800001c00000e000007000003800000c00000
+60000010>} imagemask
+ }
+ 40 /G28 MSTT31c1fd AddChar
+%%EndResource
+
+717 1388 2078 (When this period is over, the soft limit is treated as the hard limit \(no) 2078 SB
+
+%%BeginResource: font MSTT31c1fd
+/G29 [25.0 0.0 2.0 -16.0 22.0 52.0]
+/G29 {
+ 20 68 true [1 0 0 -1 -2.0 52.0] {<8000006000003000001c00000e000007000003800001c00001e00000f000007800007800003c0000
+3c00003e00001f00001f00001f80001f80000f80000fc0000fc0000fc0000fe0000fe0000fe00007
+e00007e00007f00007f00007f00007f00007f00007f00007f00007f00007f00007f00007f00007f0
+0007e00007e00007e0000fe0000fe0000fc0000fc0000fc0000f80001f80001f80001f00001f0000
+3e00003e00003c0000780000780000f00000e00001c0000380000700000600001c00003000006000
+00800000>} imagemask
+ }
+ 41 /G29 MSTT31c1fd AddChar
+%%EndResource
+
+-3 3 SJ
+717 1478 942 (blocks/inodes can be allocated\)) 942 SB
+623 1587 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G54 [45.0 0.0 2.0 0.0 44.0 50.0]
+/G54 {
+ 42 50 true [1 0 0 -1 -2.0 50.0] {<7fffffffff807fffffffff807c007f001f8078007f00078070007f000380e0007f0001c0c0007f00
+00c0c0007f0000c0c0007f0000c0c0007f0000c080007f00004000007f00000000007f0000000000
+7f00000000007f00000000007f00000000007f00000000007f00000000007f00000000007f000000
+00007f00000000007f00000000007f00000000007f00000000007f00000000007f00000000007f00
+000000007f00000000007f00000000007f00000000007f00000000007f00000000007f0000000000
+7f00000000007f00000000007f00000000007f00000000007f00000000007f00000000007f000000
+00007f00000000007f00000000007f00000000007f00000000007f00000000007f0000000000ff80
+00000000ff8000000003ffe00000003ffffe0000>} imagemask
+ }
+ 84 /G54 MSTT31c1fd AddChar
+%%EndResource
+
+717 1587 1652 (The current usage must be reduced below the soft limit) 1652 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2919 2191 29 (6) 29 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+-12 3 SJ
+256 284 2340 (Configuration of the quota-support) 2340 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G76 [50.0 0.0 1.0 -1.0 49.0 45.0]
+/G76 {
+ 48 46 true [1 0 0 -1 -1.0 45.0] {<fffff8003ffffffff8003fff3fffc00003f80fff800001f003ff000001e003ff000001e001ff0000
+01c001ff000003c000ff8000038000ff80000380007f80000700007fc0000700003fc0000f00003f
+e0000e00003fe0000e00001ff0001c00001ff0001c00000ff0003c00000ff80038000007f8003800
+0007fc0070000007fc0070000003fe00e0000003fe00e0000001fe01e0000001ff01c0000000ff01
+c0000000ff8380000000ff83800000007fc7800000007fc7000000003fc7000000003fee00000000
+1fee000000001ffe000000001ffc000000000ffc000000000ff80000000007f80000000007f80000
+000003f00000000003f00000000003e00000000001e00000000001c00000000000c00000>} imagemask
+ }
+ 118 /G76 MSTT31c1f0 AddChar
+%%EndResource
+
+9 10 SJ
+586 614 2351 (Disk quotas have been available as a kernel patch for years) 2351 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G42 [66.0 0.0 2.0 0.0 61.0 67.0]
+/G42 {
+ 59 67 true [1 0 0 -1 -2.0 67.0] {<fffffffff0000000ffffffffff80000007fffffffff0000001fff800fffc000000ffc0001fff0000
+00ffc00007ff8000007fc00001ffc000007fc00000ffe000007fc000007ff000007fc000003ff800
+007fc000003ff800007fc000001ffc00007fc000001ffc00007fc000001ffc00007fc000000ffe00
+007fc000000ffe00007fc000000ffe00007fc000000ffe00007fc000000ffe00007fc000000ffe00
+007fc000000ffe00007fc000000ffe00007fc000001ffc00007fc000001ffc00007fc000001ffc00
+007fc000003ff800007fc000003ff000007fc000007ff000007fc00000ffe000007fc00003ffc000
+007fe0003fff0000007ffffffffe0000007ffffffff00000007ffffffffe0000007fc0007fffc000
+007fc00007fff000007fc00001fff800007fc000007ffc00007fc000001ffe00007fc000000fff00
+007fc0000007ff80007fc0000007ff80007fc0000003ffc0007fc0000001ffc0007fc0000001ffc0
+007fc0000001ffe0007fc0000000ffe0007fc0000000ffe0007fc0000000ffe0007fc0000000ffe0
+007fc0000000ffe0007fc0000000ffe0007fc0000000ffc0007fc0000001ffc0007fc0000001ffc0
+007fc0000001ff80007fc0000003ff80007fc0000007ff00007fc0000007ff00007fc000000ffe00
+007fc000003ffc0000ffc000007ff80000ffc00001fff00001fffe001fffc00007ffffffffff0000
+fffffffffffc0000ffffffffff000000>} imagemask
+ }
+ 66 /G42 MSTT31c1f0 AddChar
+%%EndResource
+
+10 8 SJ
+586 758 1973 (But they were not fully tested and contained bugs) 1973 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 932 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G41 [72.0 0.0 1.0 0.0 71.0 68.0]
+/G41 {
+ 70 68 true [1 0 0 -1 -1.0 68.0] {<00000000100000000000000000380000000000000000380000000000000000780000000000000000
+7c0000000000000000fc0000000000000000fe0000000000000000fe0000000000000001fe000000
+0000000001ff0000000000000003ff0000000000000003ff8000000000000007ff80000000000000
+07ffc00000000000000fffc00000000000000f7fc00000000000000f7fe00000000000001e3fe000
+00000000001e3ff00000000000003c3ff00000000000003c1ff00000000000007c1ff80000000000
+00780ff8000000000000f80ffc000000000000f007fc000000000000f007fe000000000001e007fe
+000000000001e003fe000000000003c003ff000000000003c001ff000000000007c001ff80000000
+00078001ff80000000000f8000ff80000000000f0000ffc0000000001f00007fc0000000001e0000
+7fe0000000001e00007fe0000000003c00003ff0000000003c00003ff0000000007c00001ff00000
+00007800001ff800000000f800000ff800000000f000000ffc00000001fffffffffc00000001ffff
+fffffc00000001fffffffffe00000003c0000003fe00000003c0000003ff0000000780000003ff00
+00000780000001ff8000000f80000001ff8000000f00000000ff8000001f00000000ffc000001e00
+0000007fc000001e000000007fe000003c000000007fe000003c000000003ff000007c000000003f
+f0000078000000003ff00000f8000000001ff80000f8000000001ffc0001f0000000001ffc0003f0
+000000001ffe0003f8000000001fff000ffc000000003fff803fff00000000ffffe0fffff000000f
+fffffcfffff000000ffffffc>} imagemask
+ }
+ 65 /G41 MSTT31c1f0 AddChar
+/G31 [50.0 0.0 11.0 0.0 37.0 68.0]
+/G31 {
+ 26 68 true [1 0 0 -1 -11.0 68.0] {<0001c0000007c000001fc000007fc00001ffc00007ffc0001fffc0007fffc000ffffc000407fc000
+007fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000
+003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000
+003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000
+003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000
+003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000
+003fc000003fc000003fc000007fe000007fe00001fff8003fffffc03fffffc0>} imagemask
+ }
+ 49 /G31 MSTT31c1f0 AddChar
+/G2e [25.0 0.0 7.0 -1.0 18.0 10.0]
+/G2e {
+ 11 11 true [1 0 0 -1 -7.0 10.0] {<1f003f807fc0ffe0ffe0ffe0ffe0ffe07fc03f801f00>} imagemask
+ }
+ 46 /G2e MSTT31c1f0 AddChar
+/G33 [50.0 0.0 4.0 -1.0 41.0 68.0]
+/G33 {
+ 37 69 true [1 0 0 -1 -4.0 68.0] {<0003fe0000001fffc000003ffff00000fffff80001fffffc0003fffffe0007ffffff0007f01fff00
+0f8003ff801f0001ff801c0000ffc03800007fc03000003fc07000003fc02000003fc00000001fc0
+0000001fc00000001f800000001f800000001f000000001f000000001e000000003e000000003c00
+000000380000000070000000006000000000c0000000018000000003e00000000ff80000001ffc00
+0000fffe000003ffff00001fffff8000007fffc000000fffe0000003ffe0000001fff00000007ff0
+0000003ff00000001ff80000001ff80000000ff80000000ff800000007f800000007f800000007f8
+00000003f800000003f800000003f800000003f000000003f000000003f000000003e000000003e0
+00000007c000000007c00000000f800000000f800000001f003e00003e007f80007c00ffe001f800
+fffc07f000ffffffc0007fffff00003ffff8000007ff800000>} imagemask
+ }
+ 51 /G33 MSTT31c1f0 AddChar
+/G34 [50.0 0.0 2.0 0.0 46.0 68.0]
+/G34 {
+ 44 68 true [1 0 0 -1 -2.0 68.0] {<00000007e00000000007e0000000000fe0000000001fe0000000001fe0000000003fe0000000007f
+e0000000007fe000000000ffe000000001ffe000000001dfe0000000039fe0000000079fe0000000
+071fe00000000e1fe00000001e1fe00000003c1fe0000000381fe0000000781fe0000000f01fe000
+0000e01fe0000001e01fe0000003c01fe0000003801fe0000007801fe000000f001fe000000e001f
+e000001e001fe000003c001fe0000038001fe0000078001fe00000f0001fe00000f0001fe00001e0
+001fe00003c0001fe00003c0001fe0000780001fe0000f00001fe0000f00001fe0001e00001fe000
+3c00001fe0007c00001fe0007800001fe000fffffffffff0fffffffffff0fffffffffff0ffffffff
+fff0fffffffffff0fffffffffff0fffffffffff00000001fe0000000001fe0000000001fe0000000
+001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe000
+0000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001fe0000000001f
+e0000000001fe000>} imagemask
+ }
+ 52 /G34 MSTT31c1f0 AddChar
+/G36 [50.0 0.0 4.0 -1.0 46.0 68.0]
+/G36 {
+ 42 69 true [1 0 0 -1 -4.0 68.0] {<000000007f8000000007ff800000003ff800000000ff8000000003fc000000000ff0000000001fe0
+000000007f8000000000ff0000000001fe0000000003fc0000000007f8000000000ff0000000001f
+e0000000003fc0000000007fc0000000007f8000000000ff0000000001ff0000000001fe00000000
+03fe0000000007fc0000000007fc000000000ff8000000000ff8000000001ff0000000001ff00ff8
+00001ff07fff00003fe1ffff80003fe7ffffe0003fff81fff0007ffe003ff8007ff8001ffc007fe0
+000ffe007fc00007fe00ffc00007ff00ffc00003ff00ffc00003ff80ff800001ff80ff800001ff80
+ff800000ff80ff800000ffc0ff800000ffc0ff800000ffc0ff8000007fc0ff8000007fc0ff800000
+7fc0ff8000007fc07f8000007fc07f8000007fc07fc000007fc07fc000007f803fc000007f803fc0
+00007f803fe000007f001fe000007f001fe00000fe000ff00000fe000ff00000fc0007f80001fc00
+03f80001f80001fc0003f00001fe0007e00000ff000fe000007f801f8000003fe07f0000000ffffe
+00000003fff8000000007fc00000>} imagemask
+ }
+ 54 /G36 MSTT31c1f0 AddChar
+%%EndResource
+
+5 8 SJ
+586 902 2139 (A revised version has been integrated in Linux 1.3.46) 2139 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1075 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 4 SJ
+586 1045 993 (To use quotas, you need:) 993 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1184 38 (\226) 38 SB
+
+%%BeginResource: font MSTT31c1fd
+/G31 [38.0 0.0 9.0 0.0 29.0 51.0]
+/G31 {
+ 20 51 true [1 0 0 -1 -9.0 51.0] {<000c00007c0001fc0007fc001ffc007ffc00c3fc0003fc0001fc0001fc0001fc0001fc0001fc0001
+fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc
+0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc00
+01fc0001fc0001fc0001fc0001fc0001fc0001fc0001fc0003fe0007ff007ffff0>} imagemask
+ }
+ 49 /G31 MSTT31c1fd AddChar
+/G2e [19.0 0.0 5.0 -1.0 13.0 7.0]
+/G2e {
+ 8 8 true [1 0 0 -1 -5.0 7.0] {<3c7effffffff7e3c>} imagemask
+ }
+ 46 /G2e MSTT31c1fd AddChar
+/G33 [38.0 0.0 3.0 -1.0 31.0 51.0]
+/G33 {
+ 28 52 true [1 0 0 -1 -3.0 51.0] {<001fc00000fff80001fffc0007fffe000fffff000f81ff801c007f8038003fc030001fc060001fc0
+00000fc000000fc000000fc000000f8000000f8000000f0000000f0000001e0000001c0000003800
+000070000000e0000001f8000007fe00003fff0000ffff800007ffc00001ffc000007fe000003fe0
+00001fe000000ff000000ff0000007f0000007f0000003f0000003f0000003f0000003f0000003e0
+000003e0000003e0000007c0000007c000000f8078000f00fe001e00ff003c00ffc0f8007fffe000
+3fff80000ffc0000>} imagemask
+ }
+ 51 /G33 MSTT31c1fd AddChar
+/G34 [38.0 0.0 2.0 0.0 35.0 51.0]
+/G34 {
+ 33 51 true [1 0 0 -1 -2.0 51.0] {<000007c00000000fc00000000fc00000001fc00000001fc00000003fc00000007fc00000007fc000
+0000dfc0000001dfc00000019fc00000039fc00000031fc00000061fc000000e1fc000000c1fc000
+001c1fc00000381fc00000301fc00000701fc00000601fc00000e01fc00001c01fc00001801fc000
+03801fc00003001fc00007001fc0000e001fc0000c001fc0001c001fc00038001fc00038001fc000
+70001fc00070001fc000ffffffff80ffffffff80ffffffff80ffffffff8000001fc00000001fc000
+00001fc00000001fc00000001fc00000001fc00000001fc00000001fc00000001fc00000001fc000
+00001fc00000001fc00000001fc000>} imagemask
+ }
+ 52 /G34 MSTT31c1fd AddChar
+/G36 [38.0 0.0 3.0 -1.0 35.0 51.0]
+/G36 {
+ 32 52 true [1 0 0 -1 -3.0 51.0] {<000000fe000007f000003f000000fc000001f8000007e000000fc000001f8000003f0000007e0000
+00fc000001fc000003f8000003f0000007f000000fe000000fe000001fe000001fc000003fc00000
+3f81fe003f8fff807fbfffe07ff83ff07fe00ff87f8007f8ff0003fcff0001feff0001fefe0001fe
+fe0000fffe0000fffe0000fffe00007ffe00007ffe00007ffe00007f7e00007f7e00007f7f00007e
+3f00007e3f00007e3f80007c1f8000fc0f8000f80fc001f007e001f003e003e001f007c000fc1f00
+003ffe00000ff000>} imagemask
+ }
+ 54 /G36 MSTT31c1fd AddChar
+/G2b [42.0 0.0 1.0 5.0 40.0 44.0]
+/G2b {
+ 39 39 true [1 0 0 -1 -1.0 44.0] {<00003800000000380000000038000000003800000000380000000038000000003800000000380000
+00003800000000380000000038000000003800000000380000000038000000003800000000380000
+00003800000000380000fffffffffefffffffffefffffffffe000038000000003800000000380000
+00003800000000380000000038000000003800000000380000000038000000003800000000380000
+0000380000000038000000003800000000380000000038000000003800000000380000>} imagemask
+ }
+ 43 /G2b MSTT31c1fd AddChar
+/G93 [33.0 0.0 2.0 32.0 30.0 51.0]
+/G93 {
+ 28 19 true [1 0 0 -1 -2.0 51.0] {<00800040038001c00e0007001c000c0010001800200010006000300040002000c0006000c0006000
+c0006000ef8077c0ffc07fe0ffe07ff0ffe07ff07fe03ff03fe01ff01fc00fe00f800780>} imagemask
+ }
+ 147 /G93 MSTT31c1fd AddChar
+/G94 [33.0 0.0 2.0 32.0 30.0 51.0]
+/G94 {
+ 28 19 true [1 0 0 -1 -2.0 51.0] {<1e001f007f003f80ff807fc0ffc07fe0ffe07fe0ffe07ff07fe03ff03ee01f700060003000600030
+006000300040002000c000600080004001800080070003800e00070038001c0020001000>} imagemask
+ }
+ 148 /G94 MSTT31c1fd AddChar
+/G51 [54.0 0.0 3.0 -14.0 51.0 51.0]
+/G51 {
+ 48 65 true [1 0 0 -1 -3.0 51.0] {<00001ff800000000ffff00000003f00fe000000f8003f000003f0000fc00007c00007e0000f80000
+3f0001f800001f8003f000000fc007e000000fe007e0000007f00fc0000007f01fc0000003f81fc0
+000003f83f80000003fc3f80000001fc7f80000001fe7f80000001fe7f00000001fe7f00000000fe
+ff00000000ffff00000000ffff00000000ffff00000000ffff00000000ffff00000000ffff000000
+00ffff00000000ffff00000000ffff00000000ffff00000000ff7f00000000fe7f80000000fe7f80
+000001fe7f80000001fe3f80000001fc3f80000001fc3fc0000003fc1fc0000003f81fe0000003f0
+0fe0000007f007f0000007e007f000000fc003f800001fc001fc00001f8000fe00003f00007f0000
+fc00001f8001f8000007f00ff0000001ffffc00000007ffe000000001ffc000000000ffe00000000
+07fe0000000003ff0000000001ff8000000000ffc0000000003fc0000000001fe00000000007f000
+00000001fc00000000007e00000000001f800000000003f000000000001e>} imagemask
+ }
+ 81 /G51 MSTT31c1fd AddChar
+%%EndResource
+
+717 1184 2057 (a recent \(1.3.46+\) kernel \(answer \223y\224 to \223Quota support\224 during the ) 2057 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+2774 1187 180 (make) 180 SB
+717 1277 270 (config) 270 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+-1 1 SJ
+987 1274 165 ( step\)) 165 SB
+623 1383 38 (\226) 38 SB
+-2 2 SJ
+717 1383 545 (the quota utilities:) 545 SB
+
+%%BeginResource: font MSTT31c1fd
+/Gbb [35.0 0.0 2.0 0.0 32.0 35.0]
+/Gbb {
+ 30 35 true [1 0 0 -1 -2.0 35.0] {<c00180006000c0007000e00038007000380070001c0038001e003c000f001e000f001e0007800f00
+07c00f8003e007c003e007c001f003e001f803f000f801f000fc01f8007e00fc007c00f800fc01f8
+01f803f001f003e003e007c003e007c007c00f8007800f000f001e000f001e001e003c001c003800
+38007000380070007000e0006000c000c0018000>} imagemask
+ }
+ 187 /Gbb MSTT31c1fd AddChar
+%%EndResource
+
+773 1491 35 (\273) 35 SB
+
+%%BeginResource: font MSTT31c1fd
+/G4c [45.0 0.0 1.0 0.0 43.0 50.0]
+/G4c {
+ 42 50 true [1 0 0 -1 -1.0 50.0] {<fffff80000000fff8000000003fe0000000003fe0000000001fc0000000001fc0000000001fc0000
+000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc
+0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc00000000
+01fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000
+000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc0000000001fc
+0000000001fc0000000001fc0000000001fc0000000001fc000000c001fc000001c001fc00000180
+01fc0000038001fc0000038001fc0000070001fc0000070001fc00000f0001fc00001e0003fe0000
+3e0003ff0001fe000ffffffffc00fffffffffc00>} imagemask
+ }
+ 76 /G4c MSTT31c1fd AddChar
+/G50 [43.0 0.0 1.0 0.0 40.0 50.0]
+/G50 {
+ 39 50 true [1 0 0 -1 -1.0 50.0] {<ffffffc0000ffffffc0003fe01ff0003fc003fc001fc001fe001fc000ff001fc0007f801fc0007f8
+01fc0003fc01fc0003fc01fc0001fe01fc0001fe01fc0001fe01fc0001fe01fc0001fe01fc0001fe
+01fc0001fe01fc0003fc01fc0003fc01fc0003fc01fc0007f801fc000ff001fc001ff001fc003fc0
+01ff00ff8001fffffe0001fcfff00001fc00000001fc00000001fc00000001fc00000001fc000000
+01fc00000001fc00000001fc00000001fc00000001fc00000001fc00000001fc00000001fc000000
+01fc00000001fc00000001fc00000001fc00000001fc00000001fc00000003fe00000003fe000000
+0fff800000fffff80000>} imagemask
+ }
+ 80 /G50 MSTT31c1fd AddChar
+/G45 [46.0 0.0 1.0 0.0 44.0 50.0]
+/G45 {
+ 43 50 true [1 0 0 -1 -1.0 50.0] {<fffffffffc0007fffffffc0003fc0000fc0003fc00003c0001fc00001c0001fc00000e0001fc0000
+0e0001fc00000e0001fc00000e0001fc0000060001fc0000060001fc0000000001fc0000000001fc
+0000000001fc0000000001fc0000000001fc0000800001fc0000800001fc0000800001fc00018000
+01fc0001800001fc0003800001fc000f800001ffffff800001ffffff800001fc000f800001fc0003
+800001fc0001800001fc0001800001fc0000800001fc0000800001fc0000800001fc0000000001fc
+0000000001fc0000000001fc0000000001fc0000000001fc0000006001fc000000c001fc000000c0
+01fc000001c001fc0000018001fc0000038001fc0000078001fc0000070001fc00000f0003fc0000
+3f0003fe0000fe000ffffffffe00fffffffffe00>} imagemask
+ }
+ 69 /G45 MSTT31c1fd AddChar
+/G4f [54.0 0.0 3.0 -1.0 51.0 51.0]
+/G4f {
+ 48 52 true [1 0 0 -1 -3.0 51.0] {<00001ff800000000ffff80000003f00fe000000f8001f000003f0000fc00007e00007e0000fc0000
+3f0001f800001f8003f000000fc007e000000fe00fe0000007f00fc0000007f01fc0000003f81fc0
+000003f83f80000001fc3f80000001fc7f80000001fe7f80000001fe7f80000001fe7f00000000fe
+ff00000000ffff00000000ffff00000000ffff00000000ffff00000000ffff00000000ffff000000
+00ffff00000000ffff00000000ffff00000000ffff00000000ffff00000000fe7f00000000fe7f80
+000000fe7f80000001fe7f80000001fc3f80000001fc3fc0000001fc1fc0000003f81fc0000003f8
+0fe0000003f00fe0000007e007f0000007e003f000000fc001f800001f8000fc00003f00007e0000
+7e00003f0000fc00001f8003f0000007f00fc0000001ffff000000001ff80000>} imagemask
+ }
+ 79 /G4f MSTT31c1fd AddChar
+%%EndResource
+
+848 1491 24 (f) 25 SB
+873 1491 59 (tp) 58 SB
+931 1491 87 (://f) 88 SB
+1019 1491 59 (tp) 58 SB
+1077 1491 43 (.f) 44 SB
+1121 1491 38 (u) 37 SB
+1158 1491 135 (net.f) 136 SB
+1294 1491 80 (i/p) 79 SB
+1373 1491 76 (ub) 75 SB
+1448 1491 66 (/L) 67 SB
+1515 1491 59 (in) 58 SB
+1573 1491 139 (ux/P) 138 SB
+1711 1491 46 (E) 45 SB
+1756 1491 54 (O) 55 SB
+1811 1491 43 (P) 41 SB
+1852 1491 45 (L) 46 SB
+1898 1491 112 (E/L) 113 SB
+2011 1491 21 (i) 20 SB
+2031 1491 76 (nu) 75 SB
+2106 1491 29 (s) 30 SB
+2136 1491 21 (/) 20 SB
+2156 1491 29 (s) 30 SB
+2186 1491 38 (u) 37 SB
+2223 1491 103 (bsy) 104 SB
+2327 1491 83 (ste) 84 SB
+2411 1491 57 (m) 58 SB
+2469 1491 88 (s/q) 87 SB
+2556 1491 76 (uo) 75 SB
+2631 1491 54 (ta) 55 SB
+773 1599 35 (\273) 35 SB
+848 1599 24 (f) 25 SB
+873 1599 59 (tp) 58 SB
+931 1599 87 (://f) 88 SB
+1019 1599 59 (tp) 58 SB
+1077 1599 224 (.cistron) 223 SB
+1300 1599 57 (.n) 56 SB
+1356 1599 118 (l/pu) 117 SB
+1473 1599 59 (b/) 58 SB
+1531 1599 43 (P) 42 SB
+1573 1599 109 (eop) 108 SB
+1681 1599 54 (le) 55 SB
+1736 1599 21 (/) 20 SB
+1756 1599 57 (m) 59 SB
+1815 1599 163 (vw/qu) 162 SB
+1977 1599 92 (ota) 92 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G37 [29.0 0.0 2.0 0.0 25.0 39.0]
+/G37 {
+ 23 39 true [1 0 0 -1 -2.0 39.0] {<0ffffe1ffffe1ffffe1ffffe3ffffc38001c60001c400038c0003880003800007000007000007000
+00e00000e00000e00001c00001c00001c0000380000380000380000700000700000700000e00000e
+00000e00001c00001c00001c0000380000380000380000700000700000700000e00000e000>} imagemask
+ }
+ 55 /G37 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (7) 29 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+-6 3 SJ
+256 84 1853 (Administration of the quota) 1853 SB
+256 284 149 (su) 148 SB
+404 284 149 (bs) 148 SB
+552 284 398 (ystem) 398 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 648 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d057ee26f8d6945ed4a734c986bacc9c4e9146c536d435a3f6fe0bdd7292c545882f15c502251ef625c374cd766ecd6c027e94c0d
+02455a20a915ae7e602e4ce476c48af63ce8881e74c11919ef36f4173b1c5093a5c28b8b51817b3b2d6208d608bd4a83e1e281bccf58e2e3167313817edb8130
+3e3a3ed7fd80096a1582c85560de49313e80c9450fa16756be238e37e4e1e782239b6ef0c45e4d6a4990e6b587e1f1a8a85e38db96ba259d8b88453f687fa358
+5489f868f8cfb10e7ab8f3fe7b10d998cf8058e0ec33100415a1c7d9dcff19037c7b759645e8f5273270f67ab6adacb319ab
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-15 5 SJ
+586 615 1756 (installing a kernel with quota support) 1756 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 817 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-15 3 SJ
+586 784 1288 (installing the quota utilities) 1288 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 985 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-12 4 SJ
+586 952 1732 (activating disk quotas on filesystems) 1732 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1153 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d0007e93fb06c6a176f2b56dd99c207c01444802de9e7bcfa5f1fa63880cc63e67df2094a85d91cac055b75fb839d00387733a140
+30015b397949b626fa6b1885d027fa05dcf0eb8fe9dc385e89a67d0f95d954dc
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-16 4 SJ
+586 1120 1669 (setting disk quotas for users/groups) 1669 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1321 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-9 3 SJ
+586 1288 1114 (checking for disk usage) 1114 SB
+32 0 0 88 88 0 0 0 71 /ZapfDingbats font
+473 1489 69 (u) 69 SB
+32 0 0 117 117 0 0 0 104 /MSTT31c1c9 font
+-10 2 SJ
+586 1456 1294 (checking quota consistency) 1294 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G38 [29.0 0.0 3.0 0.0 26.0 40.0]
+/G38 {
+ 23 40 true [1 0 0 -1 -3.0 40.0] {<00fe0003ffc00f83e01f01f03e00f83c00783c007c7c007c7c007c7c007c7e007c7e00783f00f83f
+80f03fc1e01fe3c00ff78007fe0003fc0001fe0000ff8003ffc0073fe00e0ff01e07f83c03f87c01
+fc7800fcf8007ef8007ef8003ef8003ef8003e78003c7c003c3e00783f00f01f83e007ffc001fe00
+>} imagemask
+ }
+ 56 /G38 MSTT31c1bc AddChar
+%%EndResource
+
+2919 2191 29 (8) 29 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-4 4 SJ
+256 305 1789 (Installing the kernel and tools) 1789 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G4b [72.0 0.0 2.0 0.0 72.0 67.0]
+/G4b {
+ 70 67 true [1 0 0 -1 -2.0 67.0] {<ffffffe003fffffc00ffffffe003fffffc0007fffc00001fffc00001fff000000fff000000ffe000
+000ffc000000ffe000000ff00000007fc000000fe00000007fc000001f800000007fc000001f0000
+00007fc000003e000000007fc000007c000000007fc00000f8000000007fc00001f0000000007fc0
+0003e0000000007fc00007c0000000007fc0000f80000000007fc0001f00000000007fc0003e0000
+0000007fc0007c00000000007fc000f800000000007fc001f000000000007fc003e000000000007f
+c007c000000000007fc00f8000000000007fc01f0000000000007fc03e0000000000007fc07c0000
+000000007fc0f80000000000007fc1f00000000000007fc3e00000000000007fcfe0000000000000
+7fdff00000000000007ffff80000000000007ffffc0000000000007fdffe0000000000007fcfff00
+00000000007fc7ff8000000000007fc3ffc000000000007fc1ffe000000000007fc0fff000000000
+007fc07ff800000000007fc03ffc00000000007fc01fff00000000007fc00fff80000000007fc007
+ffc0000000007fc003ffe0000000007fc001fff0000000007fc000fff8000000007fc0007ffc0000
+00007fc0003ffe000000007fc0001fff000000007fc0000fff800000007fc00007ffc00000007fc0
+0003ffe00000007fc00001fff00000007fc00000fff80000007fc000003ffc0000007fc000001ffe
+0000007fc000001fff0000007fc000000fffc000007fc0000007ffe00000ffe0000007fff00000ff
+e0000007fffc0001fff000000fffff0007fffc00001fffffe0ffffffe000fffffffcffffffe000ff
+fffffc>} imagemask
+ }
+ 75 /G4b MSTT31c1f0 AddChar
+/G6a [28.0 0.0 -8.0 -21.0 18.0 70.0]
+/G6a {
+ 26 91 true [1 0 0 -1 8.0 70.0] {<00003e0000007f000000ff800001ffc00001ffc00001ffc00001ffc00001ffc00000ff8000007f00
+00003e00000000000000000000000000000000000000000000000000000000000000000000000000
+00000000000000000000000000000000000001c000000fc000007fc00001ffc0000fffc0001fffc0
+0018ffc000007fc000007fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc0
+00003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc0
+00003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc0
+00003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc000003fc0
+00003fc000003fc000003fc000003fc000003fc000003f8000003f8000003f8000003f8000003f00
+00003f0000003f003c003e007f003e00ff807c00ff807800ffc0f000fff1e0007fffc0003fff0000
+07f80000>} imagemask
+ }
+ 106 /G6a MSTT31c1f0 AddChar
+/G93 [44.0 0.0 3.0 42.0 41.0 68.0]
+/G93 {
+ 38 26 true [1 0 0 -1 -3.0 68.0] {<001000002000700000e001f00003c003c00007800700000e000e00001c001c000038001800007000
+3000006000700000e000600000c000600000c000e00001c000e00001c000e00001c000f3f001e7e0
+fff801fff0fffc01fff8fffe01fffc7ffe00fffc7ffe00fffc7ffe00fffc3ffc007ff81ffc003ff8
+0ff8001ff003e00007c0>} imagemask
+ }
+ 147 /G93 MSTT31c1f0 AddChar
+/G94 [44.0 0.0 3.0 42.0 41.0 68.0]
+/G94 {
+ 38 26 true [1 0 0 -1 -3.0 68.0] {<0f80001f003fe0007fc07ff000ffe07ff800fff0fffc01fff8fffc01fff8fffc01fff8fffe01fffc
+7ffe00fffc3ffe007ffc1f9e003f3c000e00001c000e00001c000e00001c000c000018000c000018
+001c0000380018000030003800006000700000e000e00001c001c00003800780000f001f00003e00
+1c000038001000002000>} imagemask
+ }
+ 148 /G94 MSTT31c1f0 AddChar
+/G51 [72.0 0.0 4.0 -19.0 68.0 68.0]
+/G51 {
+ 64 87 true [1 0 0 -1 -4.0 68.0] {<0000001ffc000000000001ffffc0000000000ffffff8000000003fe00ffe00000000ff0001ff0000
+0003fc00007fc0000007f800001fe000000ff000000ff000001fe0000007f800003fc0000003fc00
+007f80000001fe0000ff00000001ff0001ff00000000ff8003fe000000007fc003fe000000007fc0
+07fc000000003fe00ffc000000003ff00ff8000000003ff01ff8000000001ff81ff8000000001ff8
+3ff0000000001ffc3ff0000000001ffc3ff0000000000ffc7ff0000000000ffe7ff0000000000ffe
+7ff0000000000ffe7fe0000000000ffe7fe00000000007feffe00000000007ffffe00000000007ff
+ffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ff
+ffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ff
+ffe00000000007ff7fe00000000007fe7ff00000000007fe7ff00000000007fe7ff0000000000ffe
+7ff0000000000ffc3ff0000000000ffc3ff0000000000ffc3ff8000000000ff81ff8000000001ff8
+1ff8000000001ff00ffc000000001ff00ffc000000003fe007fc000000003fe007fe000000007fc0
+03fe000000007f8001ff00000000ff8000ff80000000ff00007f80000001fe00007fc0000003fc00
+001fe0000007f800000ff000000ff0000007f800001fe0000003fe00003f80000000ff8000ff0000
+00003fe00ffc000000000ffffff00000000003ffff800000000000ffff0000000000007fff800000
+0000003fff8000000000001fffc000000000000fffe0000000000007fff0000000000001fff00000
+00000000fff80000000000007ffc0000000000001ffe0000000000000fff00000000000003ff8000
+0000000000ffc00000000000003ff00000000000000ffc00000000000001ff000000000000003ff0
+00000000000007fe000000000000003e>} imagemask
+ }
+ 81 /G51 MSTT31c1f0 AddChar
+%%EndResource
+
+6 7 SJ
+586 614 2118 (Kernel: just answer \223y\224 to \223Quota support\224, compile,) 2118 SB
+1 3 SJ
+586 734 971 (install the kernel, reboot) 971 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 908 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1 3 SJ
+586 878 689 (Tools: just type \223) 689 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1 2 SJ
+1277 882 1080 (make; make install) 1080 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1 2 SJ
+2358 878 297 (\224 but ...) 297 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G45 [61.0 0.0 2.0 0.0 59.0 67.0]
+/G45 {
+ 57 67 true [1 0 0 -1 -2.0 67.0] {<ffffffffffffe000ffffffffffffe00003ffffffffffe00001ffc000001fe00000ffc0000007e000
+00ffc0000003e000007fc0000001e000007fc0000000f000007fc0000000f000007fc00000007000
+007fc00000007000007fc00000007000007fc00000007000007fc00000003000007fc00000003000
+007fc00000000000007fc00000000000007fc00000000000007fc00000000000007fc00000000000
+007fc00000000000007fc00000000000007fc00000180000007fc00000180000007fc00000180000
+007fc00000380000007fc00000380000007fc00000380000007fc00000780000007fc00000f80000
+007fc00003f80000007ffffffff80000007ffffffff80000007ffffffff80000007fc00003f80000
+007fc00000f80000007fc00000780000007fc00000380000007fc00000380000007fc00000380000
+007fc00000180000007fc00000180000007fc00000180000007fc00000000000007fc00000000000
+007fc00000000000007fc00000000000007fc00000000000007fc00000000000007fc00000000000
+007fc00000000180007fc00000000300007fc00000000300007fc00000000700007fc00000000600
+007fc00000000e00007fc00000001e00007fc00000001c00007fc00000003c00007fc00000007c00
+007fc0000000f80000ffc0000001f80000ffe0000007f80001fff000003ff00007fffffffffff000
+fffffffffffff000ffffffffffffe000>} imagemask
+ }
+ 69 /G45 MSTT31c1f0 AddChar
+/G32 [50.0 0.0 2.0 0.0 46.0 68.0]
+/G32 {
+ 44 68 true [1 0 0 -1 -2.0 68.0] {<0000ff8000000007fff80000003ffffe0000007fffff000000ffffffc00001ffffffe00003ffffff
+f00007fc03fff0000fe000fff8000f80003ffc001f00001ffc001e00000ffe003c000007fe003800
+0003fe0038000003ff0070000001ff0070000001ff0060000001ff0000000000ff0000000000ff00
+00000000ff0000000000ff0000000000fe0000000000fe0000000000fe0000000000fe0000000000
+fc0000000001fc0000000001f80000000001f80000000003f00000000003f00000000003e0000000
+0007c00000000007c0000000000f80000000001f00000000001f00000000003e00000000003c0000
+000000780000000000f00000000001f00000000001e00000000003c0000000000780000000000f00
+000000001e00000000003c0000000000780000000000f00000000001e00000000003c00000000007
+80000000000700000000000e00000000003c0000007000780000006000f0000000e001e0000003e0
+03c000001fc007ffffffffc00fffffffff801fffffffff803fffffffff807fffffffff00ffffffff
+ff00ffffffffff00>} imagemask
+ }
+ 50 /G32 MSTT31c1f0 AddChar
+%%EndResource
+
+6 8 SJ
+586 1021 2024 (... you may want to include special Ext2fs support:) 2024 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1163 45 (\226) 45 SB
+717 1163 450 (quotacheck) 450 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+
+%%BeginResource: font MSTT31c1fd
+/G32 [38.0 0.0 2.0 0.0 35.0 51.0]
+/G32 {
+ 33 51 true [1 0 0 -1 -2.0 51.0] {<001ff00000007ffc000001ffff000003ffff800007ffffc0000fffffe0001fc0fff0001f003ff800
+3c000ff800380007f800300007fc00700003fc00600003fc00600001fc00000001fc00000001fc00
+000001fc00000001f800000001f800000001f800000001f000000003f000000003e000000003e000
+000007c000000007c00000000f800000000f000000001e000000003e000000003c00000000780000
+0000f000000001e000000001c0000000038000000007000000000e000000001c0000000038000000
+007000000000e000008001c000010003800003000700000f000ffffffe001ffffffe003ffffffe00
+7ffffffc00fffffffc00fffffffc00>} imagemask
+ }
+ 50 /G32 MSTT31c1fd AddChar
+/G92 [25.0 0.0 7.0 32.0 18.0 51.0]
+/G92 {
+ 11 19 true [1 0 0 -1 -7.0 51.0] {<3e007f00ff80ffc0ffe0ffe07fe03ee0006000600040004000c00180030006001c0038002000>} imagemask
+ }
+ 146 /G92 MSTT31c1fd AddChar
+%%EndResource
+
+1 8 SJ
+1167 1160 1478 ( uses the Ext2fs library written by Theodore Ts\222o) 1478 SB
+623 1268 38 (\226) 38 SB
+717 1268 921 (This is much faster than using ) 921 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1638 1271 405 (readdir\(\)) 405 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1412 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 1382 1036 (To enable Ext2fs support:) 1036 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1521 38 (\226) 38 SB
+717 1521 128 (add ) 128 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+845 1524 630 (-DEXT2_DIRECT ) 630 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1475 1521 78 (to ) 78 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1553 1524 270 (CFLAGS) 270 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1629 38 (\226) 38 SB
+717 1629 128 (add ) 128 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+845 1632 405 (-lext2fs ) 405 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1250 1629 78 (to ) 78 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1328 1632 315 (LDFLAGS) 315 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2919 2191 29 (9) 29 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d06220d6e2b623024556ea2a939cb367d2285f7b04631175ab33f2e59099e861b3f875c7fac9020d1ef6efbe9487d5c5b60b1182e
+1d16965caac24d6041f6f39b7cd58549c9d14c1662f11e111e33b800e8ce1d96a9f15bc4ce0b7da824583f92dceeb4d299415c584f549bd2e98ffd8078fa1235
+c39cf7fa50fd5046a9ff05ab034b9277a9a7eec0341469664499fc5d03bb261786df4623ec9dbd2dfe7a56b7b2d3476013d5286fd827fa31f4b64ef3cbde3e63
+d1c8da84fbe462d36d55b82375491a6e16e964229cce8719aa830a4ea277345799016cd9bcca9a6daf9cb9ec5b10300d750aaea0d792e6d6d33efb3ef209261f
+698d71fcb0172c34c6737c
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-5 5 SJ
+256 305 2204 (Enabling disk quotas on file systems) 2204 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+7 7 SJ
+586 614 1690 (Quotas are managed on a file system basis) 1690 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 758 1369 (Two fstab options control quotas: ) 1369 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1955 762 480 (usrquota) 480 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2435 758 169 ( and) 169 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 882 480 (grpquota) 480 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 1021 883 (Example of /etc/fstab:) 883 SB
+32 0 0 67 67 0 0 0 57 /Courier-Bold /font9 ANSIFont font
+586 1145 2280 (/dev/hda2 / ext2 defaults,rw 0 1) 2280 SB
+586 1225 2280 (/dev/hdb2 /home ext2 defaults,rw,usrquota,grpquota 0 2) 2280 SB
+586 1305 2280 (/dev/sda1 /usr/src ext2 default,usrquota 0 2) 2280 SB
+586 1385 2280 (none /proc proc defaults,rw 0 0) 2280 SB
+586 1465 2280 (/dev/hda3 none swap sw 0 0) 2280 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1596 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 1566 1042 (Quotas are activated with ) 1042 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1628 1570 420 (quotaon) 420 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2048 1566 28 (:) 28 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1690 1380 (/usr/sbin/quotaon -avug) 1380 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+
+%%BeginResource: font MSTT31c1bc
+/G30 [29.0 0.0 2.0 0.0 26.0 40.0]
+/G30 {
+ 24 40 true [1 0 0 -1 -2.0 40.0] {<007e0000ff8003c3c00780e00f00f00e00701e00781e003c3c003c3c003c7c003e7c001e7c001e78
+001ef8001ff8001ff8001ff8001ff8001ff8001ff8001ff8001ff8001ff8001ff8001ff8001f7800
+1e78001e7c003e7c003e3c003c3c003c3e00381e00780e00700f00f00781e003c3c001ff00007c00
+>} imagemask
+ }
+ 48 /G30 MSTT31c1bc AddChar
+%%EndResource
+
+2890 2191 58 (10) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+%%BeginResource: font MSTT31c1c9
+currentfile eexec
+9e67edc6b858a3e762244b628fb7f6f6b82db3d80533f85f9af7ec02fa0992f446e47e7476690365d15488a3d0557140c554c35b60083b9bf344ec199d995ff7
+cd974526686a837538b7a59d07d53e21b3fa3313fbd1f7f7696e463c6e9f4dd81a178f4cd84a9c664c8ed3ec336fd6fb9e483f3302eeb5fe4637dfe6d10e7ba4
+f53e92bb2bbdcd0a388c0136f8906ca645dc0a64a817eca590cd187ecf50e06f833cc7154aaca53c69bc3b1326502d3bbeefe3c6ca245a19007872ec8da89685
+56eb3a6dfbb3acb8151d12382ee5a80c2afd576ac183cde8d7eab3e403805ee0e68a511f2d65ee2ed6124ccd69dfee6b3e8ceb1b0708a1183f6fb7e85a1f2038
+dbdf9ef86f77652226e8a4109784e077e9d3a78d5c34c01f0b4d377941e119ddace546b11dd90abf5f228925ffb99beaf6fd83aed87d08f3849c79e7acd19a06
+2022d0a0c0082055a16412d5e30b81adcb81bf0742acf8c198c2266ef5e1cf7b86096cc517bb37e3a9dc8d3733b4135c34ed46f4d1bc36446ef1bc30ed48e948
+a8612262f068a2e3119be1286861e7a0e5
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+0000000000000000000000000000000000000000000000000000000000000000
+
+cleartomark
+%%EndResource
+-4 2 SJ
+256 305 1504 (Setting individual quotas) 1504 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G49 [31.0 0.0 2.0 0.0 29.0 67.0]
+/G49 {
+ 27 67 true [1 0 0 -1 -2.0 67.0] {<ffffffe0ffffffe007fffc0001fff00000ffe00000ffe000007fc000007fc000007fc000007fc000
+007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000
+007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000
+007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000
+007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000
+007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000007fc000
+007fc00000ffe00000ffe00001fff00007fffc00ffffffe0ffffffe0>} imagemask
+ }
+ 73 /G49 MSTT31c1f0 AddChar
+%%EndResource
+
+2 8 SJ
+586 614 1680 (Individual disk quotas can be set with the ) 1680 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+2268 618 420 (edquota) 420 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2688 614 181 ( tool) 181 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 9 SJ
+586 758 2274 (The administrator can specify the soft and hard limits for) 2274 SB
+1 1 SJ
+586 878 263 (users \() 263 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+849 882 120 (-u) 120 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2 3 SJ
+969 878 556 (\) and groups \() 556 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1527 882 120 (-g) 120 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1647 878 33 (\)) 33 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 1021 414 (Example \() 414 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1000 1025 1080 (edquota -u dugenou) 1080 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2080 1021 61 (\):) 61 SB
+32 0 0 58 58 0 0 0 50 /Courier-Bold /font9 ANSIFont font
+586 1144 840 (Quotas for user dugenou:) 840 SB
+586 1214 2240 (/dev/hdb2: blocks in use: 16, limits \(soft = 5000, hard = 6000\) ) 2240 SB
+773 1283 1960 ( inodes in use: 11, limits \(soft = 100, hard = 110\)) 1960 SB
+586 1353 1995 (/dev/sda1: blocks in use: 0, limits \(soft = 0, hard = 0\) ) 1995 SB
+773 1423 1785 ( inodes in use: 0, limits \(soft = 0, hard = 0\)) 1785 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1544 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 10 SJ
+586 1514 2265 (edquota can also copy disk quotas from a user to another) 2265 SB
+586 1634 172 (one:) 172 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1758 1800 (edquota -p prototype_user user) 1800 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (11) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-2 2 SJ
+256 305 1244 (Checking disk usage) 1244 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1 1 SJ
+586 614 180 (The ) 180 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+766 618 480 (repquota) 480 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 6 SJ
+1246 614 1435 ( command prints a summary of disk) 1435 SB
+586 734 254 (usage:) 254 SB
+32 0 0 58 58 0 0 0 50 /Courier-Bold /font9 ANSIFont font
+773 894 1645 (*** Report for user quotas on /dev/hdb2 \(/home\)) 1645 SB
+1073 976 1505 ( Block limits File limits) 1505 SB
+586 1046 2345 (User used soft hard grace used soft hard grace) 2345 SB
+586 1116 2065 (root -- 19 0 0 2 0 0) 2065 SB
+586 1185 2065 (bin -- 3 0 0 3 0 0) 2065 SB
+586 1255 2065 (news -- 31691 0 0 11846 0 0) 2065 SB
+586 1325 2065 (card -- 111498 0 0 8673 0 0) 2065 SB
+586 1395 2065 (dugenou -- 16 5000 6000 11 100 110) 2065 SB
+586 1465 2065 (melanie -- 6 5000 6000 7 100 110) 2065 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1586 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 9 SJ
+586 1556 1961 (The quota command can also be used to print the) 1961 SB
+586 1676 2013 (individual quota associated with a user or a group:) 2013 SB
+32 0 0 58 58 0 0 0 50 /Courier-Bold /font9 ANSIFont font
+586 1798 2030 (Disk quotas for user dugenou \(uid 1004\): ) 2030 SB
+773 1868 2170 (Filesystem blocks quota limit grace files quota limit grace) 2170 SB
+773 1938 1855 (/dev/hdb2 16 5000 6000 11 100 110) 1855 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (12) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-6 2 SJ
+256 305 1690 (Checking quota consistency) 1690 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+9 9 SJ
+586 614 2243 (Disk quota descriptors are kept in memory by the kernel) 2243 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+9 7 SJ
+586 758 1810 (They are periodically written back to the disk) 1810 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 932 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+9 7 SJ
+586 902 2182 (They can become corrupted after an unclean shutdown) 2182 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1075 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1049 600 (quotacheck) 600 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 6 SJ
+1186 1045 1545 ( checks the consistency of disk quotas:) 1545 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1169 1560 (/usr/sbin/quotacheck -avug) 1560 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1339 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 1309 2266 (Be sure to compile the quota tools with Ext2fs support if) 2266 SB
+
+%%BeginResource: font MSTT31c1f0
+/G21 [33.0 0.0 11.0 -1.0 22.0 68.0]
+/G21 {
+ 11 69 true [1 0 0 -1 -11.0 68.0] {<1f003f807fc07fc0ffe0ffe0ffe0ffe0ffe0ffe0ffe0ffe0ffe07fc07fc07fc07fc07fc07fc07fc0
+7fc07f807f807f803f803f803f803f803f803f003f003f003f003f001f001f001f001f001e001e00
+1e001e001e001e001e000e000c000c000c000c00000000000000000000000000000000001f003f80
+7fc0ffe0ffe0ffe0ffe0ffe07fc03f801f00>} imagemask
+ }
+ 33 /G21 MSTT31c1f0 AddChar
+%%EndResource
+
+4 5 SJ
+586 1429 910 (you want it to run fast!) 910 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (13) 58 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+-3 1 SJ
+256 284 721 (Quota API) 721 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+5 8 SJ
+586 614 1850 (A system call can be used to manipulate quota) 1850 SB
+32 0 0 63 63 0 0 0 50 /ZapfDingbats font
+473 779 50 (u) 50 SB
+32 0 0 83 83 0 0 0 71 /Courier-Bold /font9 ANSIFont font
+586 758 2250 (int quotactl \(int cmd, char *special, int id,) 2250 SB
+586 858 650 (caddr_t addr\)) 650 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1008 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G43 [67.0 0.0 4.0 -1.0 63.0 68.0]
+/G43 {
+ 59 69 true [1 0 0 -1 -4.0 68.0] {<0000001ffc000600000001ffffc00e0000000ffffff80e0000003ff803fe1e000000ffc0007ffe00
+0001ff00000ffe000007fc000007ff00000ff8000003ff00001fe0000001ff00003fc0000000ff00
+007fc00000007f0000ff800000003f0001ff000000001f0001ff000000001f0003fe000000000f00
+07fe000000000f0007fc0000000007000ffc0000000007800ff80000000003801ff8000000000380
+1ff80000000003803ff80000000001803ff00000000001803ff00000000000007ff0000000000000
+7ff00000000000007ff00000000000007fe00000000000007fe0000000000000ffe0000000000000
+ffe0000000000000ffe0000000000000ffe0000000000000ffe0000000000000ffe0000000000000
+ffe0000000000000ffe0000000000000ffe0000000000000ffe0000000000000ffe0000000000000
+ffe0000000000000ffe00000000000007fe00000000000007ff00000000000007ff0000000000000
+7ff00000000000003ff00000000000003ff80000000000003ff80000000000001ff8000000000000
+1ffc0000000000001ffc0000000000000ffc00000000004007fe0000000000e007ff0000000000c0
+03ff00000000018003ff80000000038001ffc0000000070000ffe00000000e00007ff00000001c00
+003ff80000003800001ffe000000f000000fff000003e0000007ffe0000fc0000001fffc007f8000
+00007ffffffe000000001ffffff80000000003ffffc000000000003ffc000000>} imagemask
+ }
+ 67 /G43 MSTT31c1f0 AddChar
+%%EndResource
+
+586 978 509 (Commands: ) 509 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+1095 982 1260 (QCMD\(operation, type\)) 1260 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1152 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G4f [72.0 0.0 4.0 -1.0 68.0 68.0]
+/G4f {
+ 64 69 true [1 0 0 -1 -4.0 68.0] {<0000001ffc000000000001ffffc0000000000ffffff8000000003fe00ffe00000000ff0000ff0000
+0001fc00003fc0000007f800001fe000000ff000000ff000001fe0000007f800003fc0000003fc00
+007f80000001fe0000ff00000000ff0001ff00000000ff8003fe000000007fc003fe000000007fc0
+07fc000000003fe00ffc000000003ff00ff8000000003ff01ff8000000001ff81ff8000000001ff8
+3ff8000000001ffc3ff0000000000ffc3ff0000000000ffc7ff0000000000ffe7ff0000000000ffe
+7ff0000000000ffe7fe0000000000ffe7fe00000000007feffe00000000007ffffe00000000007ff
+ffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ff
+ffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ffffe00000000007ff
+ffe00000000007ff7fe00000000007fe7ff00000000007fe7ff00000000007fe7ff0000000000ffe
+7ff0000000000ffc3ff0000000000ffc3ff0000000000ffc3ff8000000000ff81ff8000000001ff8
+1ff8000000001ff80ffc000000001ff00ffc000000003fe007fc000000003fe007fe000000003fc0
+03fe000000007fc001ff00000000ff8000ff80000000ff0000ff80000001fe00007fc0000003fc00
+003fe0000007f800001ff000000ff0000007f800001fe0000003fe00007fc0000000ff0001ff0000
+00007fe00ffc000000001ffffff00000000003ffffc000000000003ff8000000>} imagemask
+ }
+ 79 /G4f MSTT31c1f0 AddChar
+%%EndResource
+
+586 1122 466 (Operations:) 466 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1263 45 (\226) 45 SB
+717 1263 405 (Q_QUOTAON) 405 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1122 1260 38 (, ) 38 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1160 1263 450 (Q_QUOTAOFF) 450 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1610 1260 1128 (: activate or deactivate quota on a file) 1128 SB
+717 1350 205 (system) 205 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1462 45 (\226) 45 SB
+717 1462 450 (Q_GETQUOTA) 450 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1167 1459 38 (, ) 38 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1205 1462 450 (Q_SETQUOTA) 450 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1655 1459 821 (: get or set usage and limits) 821 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1570 45 (\226) 45 SB
+717 1570 360 (Q_SETLIM) 360 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1077 1567 38 (, ) 38 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1115 1570 360 (Q_SETUSE) 360 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1475 1567 629 (: set limits and usage) 629 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1678 45 (\226) 45 SB
+717 1678 270 (Q_SYNC) 270 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+987 1675 791 (: write quotas back to disk) 791 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+623 1787 45 (\226) 45 SB
+717 1787 450 (Q_GETSTATS) 450 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+1167 1784 408 (: get statistics) 408 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (14) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+256 305 589 (Structure ) 589 SB
+32 0 0 150 150 0 0 0 128 /Courier-Bold /font9 ANSIFont font
+845 311 450 (dqblk) 450 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 618 840 (dqb_bhardlimit) 840 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1426 614 856 (: hard limit on blocks) 856 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 788 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 762 840 (dqb_bsoftlimit) 840 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1426 758 829 (: soft limit on blocks) 829 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 932 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 906 780 (dqb_curblocks) 780 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 3 SJ
+1366 902 872 (: current blocks usage) 872 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1075 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1049 840 (dqb_ihardlimit) 840 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1426 1045 856 (: hard limit on inodes) 856 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1219 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1193 840 (dqb_isoftlimit) 840 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1426 1189 829 (: soft limit on inodes) 829 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1363 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1337 780 (dqb_curinodes) 780 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 3 SJ
+1366 1333 872 (: current inodes usage) 872 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1507 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1481 540 (dqb_btime) 540 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 7 SJ
+1126 1477 1794 (: grace period associated with the block limit) 1794 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1650 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1624 540 (dqb_inode) 540 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 7 SJ
+1126 1620 1794 (: grace period associated with the inode limit) 1794 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (15) 58 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+-6 3 SJ
+256 284 2038 (Implementation of disk quotas) 2038 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 614 1495 (Disk quotas are stored in quota files \() 1495 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+2081 618 600 (quota.user) 600 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2681 614 169 ( and) 169 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 738 660 (quota.group) 660 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+5 7 SJ
+1246 734 1430 (\) located in the root directory of file) 1430 SB
+586 854 314 (systems) 314 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1028 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+586 998 1897 (Each quota file is seen as an array of structures ) 1897 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+2483 1002 360 (struct) 360 SB
+586 1121 300 (dqblk) 300 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 7 SJ
+886 1117 1685 (, that describe the current usage and limits) 1685 SB
+3 4 SJ
+586 1237 1247 (associated with users or groups) 1247 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1411 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 14 SJ
+586 1381 2271 (The user id or group id is used as an index in the array to) 2271 SB
+4 4 SJ
+586 1501 1551 (access the appropriate quota descriptor) 1551 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (16) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-2 1 SJ
+256 305 1064 (Quota descriptors) 1064 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+5 9 SJ
+586 614 2336 (The kernel maintains a list of quota descriptors in memory) 2336 SB
+586 734 33 (\() 33 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+619 738 720 (struct dquot) 720 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1339 734 33 (\)) 33 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 908 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1 6 SJ
+586 878 1598 (The descriptors are stored in linked lists) 1598 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 5 SJ
+586 1021 1765 (Inodes contain pointers on quota descriptors) 1765 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1195 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 7 SJ
+586 1165 2341 (Quota operations are associated with mounted file systems) 2341 SB
+586 1285 33 (\() 33 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+619 1289 1020 (struct superblock) 1020 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+1639 1285 33 (\)) 33 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (17) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-2 1 SJ
+256 305 1031 (Quota operations) 1031 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 618 600 (initialize) 600 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+2 6 SJ
+1186 614 1681 (: loads quota descriptors associated with a) 1681 SB
+586 734 222 (inode) 222 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 908 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 882 240 (drop) 240 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 7 SJ
+826 878 1910 (: frees quota descriptors associated with a inode) 1910 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1025 660 (alloc_block) 660 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 6 SJ
+1246 1021 1630 (: checks for block allocation and updates) 1630 SB
+586 1141 226 (usage) 226 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1315 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1289 660 (alloc_inode) 660 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 6 SJ
+1246 1285 1630 (: checks for inode allocation and updates) 1630 SB
+586 1405 226 (usage) 226 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1579 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1553 600 (free_block) 600 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+4 7 SJ
+1186 1549 1737 (: updates usage when a block is deallocated) 1737 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1722 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1696 600 (free_inode) 600 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+3 6 SJ
+1186 1692 1308 (: updates usage when an inode is) 1308 SB
+586 1812 454 (deallocated) 454 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1986 59 (u) 59 SB
+32 0 0 100 100 0 0 0 86 /Courier-Bold /font9 ANSIFont font
+586 1960 480 (transfer) 480 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 8 SJ
+1066 1956 1838 (: updates usages when a file owner is changed) 1838 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (18) 58 SB
+32 0 0 150 150 0 0 0 134 /MSTT31c1c9 font
+-6 3 SJ
+256 305 1727 (Quota support in filesystems) 1727 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G4d [89.0 0.0 2.0 0.0 87.0 67.0]
+/G4d {
+ 85 67 true [1 0 0 -1 -2.0 67.0] {<ffffc000000000000ffff8ffffe000000000001ffff80fffe000000000001fff0003fff000000000
+003ffc0001fff000000000003ff80000fff000000000007ff80000fff800000000007ff000007ff8
+0000000000fff000007ffc0000000000fff000007ffc0000000001fff000007ffe0000000001fff0
+00007ffe0000000003fff000007bff0000000003dff000007bff0000000007dff0000079ff800000
+00079ff0000079ff800000000f9ff0000078ffc00000000f1ff0000078ffc00000001f1ff0000078
+7fc00000001e1ff00000787fe00000003e1ff00000783fe00000003c1ff00000783ff00000007c1f
+f00000783ff0000000781ff00000781ff8000000781ff00000781ff8000000f01ff00000780ffc00
+0000f01ff00000780ffc000001e01ff000007807fe000001e01ff000007807fe000003c01ff00000
+7803ff000003c01ff000007803ff000007801ff000007801ff000007801ff000007801ff80000f80
+1ff000007800ff80000f001ff000007800ffc0001f001ff000007800ffc0001e001ff0000078007f
+e0003e001ff0000078007fe0003c001ff0000078003ff0007c001ff0000078003ff00078001ff000
+0078001ff800f8001ff0000078001ff800f0001ff0000078000ffc01f0001ff0000078000ffc01e0
+001ff00000780007fc03e0001ff00000780007fe03c0001ff00000780003fe03c0001ff000007800
+03ff0780001ff00000780003ff0780001ff00000780001ff8f00001ff00000780001ff8f00001ff0
+0000780000ffde00001ff00000780000ffde00001ff000007800007ffc00001ff000007800007ffc
+00001ff000007800003ffc00001ff000007800003ff800001ff000007800001ff800001ff0000078
+00001ff000001ff000007800000ff000001ff000007800000fe000001ff00000fc00000fe000003f
+f80000fc000007c000003ff80001fe000007c000007ffc0007ff800003800001ffff00fffffc0003
+80003ffffff8fffffc000100003ffffff8>} imagemask
+ }
+ 77 /G4d MSTT31c1f0 AddChar
+%%EndResource
+
+586 614 2116 (Most of the quota implementation is contained in the) 2116 SB
+
+%%BeginResource: font MSTT31c1f0
+/G56 [72.0 0.0 1.0 -1.0 69.0 67.0]
+/G56 {
+ 68 68 true [1 0 0 -1 -1.0 67.0] {<ffffffe00000fffff0ffffffe00000fffff01fffff0000001fffc003fff800000007ff0001fff000
+000003fe0000fff000000001fc00007ff000000001f800007ff000000001f800003ff000000001f0
+00003ff000000001e000001ff800000003e000001ff800000003e000001ff800000003c000000ffc
+00000007c000000ffc0000000780000007fe0000000780000007fe0000000f80000003fe0000000f
+00000003ff0000000f00000003ff0000001f00000001ff8000001e00000001ff8000003e00000000
+ffc000003c00000000ffc000003c000000007fc000007c000000007fe0000078000000007fe00000
+f8000000003ff00000f8000000003ff00000f0000000001ff80001f0000000001ff80001e0000000
+001ff80001e0000000000ffc0003e0000000000ffc0003c00000000007fe0007c00000000007fe00
+07c00000000003ff0007800000000003ff000f800000000003ff000f000000000001ff800f000000
+000001ff801f000000000000ffc01e000000000000ffc03e0000000000007fe03c0000000000007f
+e03c0000000000007fe07c0000000000003ff0780000000000003ff0780000000000001ff8f80000
+000000001ff8f00000000000000ff9f00000000000000ffde00000000000000ffde0000000000000
+07ffe000000000000007ffc000000000000003ffc000000000000003ffc000000000000001ff8000
+000000000001ff8000000000000001ff0000000000000000ff0000000000000000ff000000000000
+00007e00000000000000007e00000000000000003e00000000000000003c00000000000000003c00
+000000000000001800000000>} imagemask
+ }
+ 86 /G56 MSTT31c1f0 AddChar
+/G46 [55.0 0.0 2.0 0.0 51.0 67.0]
+/G46 {
+ 49 67 true [1 0 0 -1 -2.0 67.0] {<ffffffffffff00ffffffffffff0007ffffffffff0001ffc00001ff0000ffc000007f0000ffc00000
+1f00007fc000000f00007fc000000f80007fc000000780007fc000000780007fc000000380007fc0
+00000380007fc000000380007fc000000180007fc000000180007fc000000000007fc00000000000
+7fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc0000300
+00007fc000030000007fc000030000007fc000070000007fc000070000007fc000070000007fc000
+0f0000007fc0001f0000007fc0007f0000007fffffff0000007fffffff0000007fffffff0000007f
+c0003f0000007fc0001f0000007fc0000f0000007fc000070000007fc000070000007fc000030000
+007fc000030000007fc000030000007fc000030000007fc000000000007fc000000000007fc00000
+0000007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc0
+00000000007fc000000000007fc000000000007fc000000000007fc000000000007fc00000000000
+7fc000000000007fc000000000007fc000000000007fc00000000000ffe00000000000ffe0000000
+0001fff00000000007fffc00000000ffffffe0000000ffffffe0000000>} imagemask
+ }
+ 70 /G46 MSTT31c1f0 AddChar
+%%EndResource
+
+4 3 SJ
+586 734 1082 (Virtual File System \(VFS\):) 1082 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 873 38 (\226) 38 SB
+717 873 997 (management of quota descriptors) 997 SB
+623 981 38 (\226) 38 SB
+-3 1 SJ
+717 981 501 (quota operations) 501 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1124 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+8 7 SJ
+586 1094 1845 (The file systems need a very minimal support:) 1845 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1233 38 (\226) 38 SB
+717 1233 1193 (when a block or inode is allocated, call ) 1193 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1910 1236 540 (alloc_block ) 540 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+2450 1233 63 (or) 63 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+717 1326 495 (alloc_inode) 495 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+623 1431 38 (\226) 38 SB
+717 1431 1264 (when a block or inode is deallocated, call ) 1264 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+1981 1434 495 (free_block ) 495 SB
+32 0 0 75 75 0 0 1 67 /MSTT31c1fd font
+2476 1431 63 (or) 63 SB
+32 0 0 75 75 0 0 0 64 /Courier-Bold /font9 ANSIFont font
+717 1525 450 (free_inode) 450 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1665 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 7 SJ
+586 1635 2005 (Currently, this support is integrated in Ext2fs only) 2005 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1809 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+6 9 SJ
+586 1779 1913 (But it would be easy to integrate quotas in other) 1913 SB
+586 1899 447 (filesystems) 447 SB
+EJ RS
+%%PageTrailer
+SS
+0 0 18 13 783 1169 300 SM
+255 255 255 fC
+/fm 256 def
+3250 2250 88 49 B
+1 F
+n
+1 lc
+1 lj
+0 0 0 pC
+6 17 SP
+gs 2857 2349 88 0 CB
+-2765 499 M 8559 0 1 PP
+S
+n
+gr
+32 0 0 58 58 0 0 1 53 /MSTT31c1bc font
+0 0 0 fC
+25 8 SJ
+153 2191 1278 (Third International Linux Conference - Berlin - May 96) 1278 SB
+2890 2191 58 (19) 58 SB
+32 0 0 167 167 0 0 0 150 /MSTT31c1c9 font
+256 284 177 (Su) 176 SB
+432 284 129 (m) 130 SB
+562 284 343 (mary) 342 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 644 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+8 8 SJ
+586 614 2122 (Finally, the quota patches have been integrated in the) 2122 SB
+2 1 SJ
+586 734 645 (standard kernel!) 645 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 908 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G30 [50.0 0.0 4.0 -1.0 46.0 68.0]
+/G30 {
+ 42 69 true [1 0 0 -1 -4.0 68.0] {<00003f8000000001ffe000000007fff80000000fe0fc0000001f803f0000003f001f8000007e000f
+c00000fc000fc00001f80007e00003f80007f00003f00003f00007f00003f80007f00001fc000fe0
+0001fc000fe00001fc001fe00001fe001fe00000fe001fe00000ff003fc00000ff003fc00000ff00
+3fc00000ff007fc00000ff807fc000007f807fc000007f807fc000007f807fc000007f807f800000
+7fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff80
+00007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0ff8000007fc0
+ff8000007fc0ff8000007fc0ff8000007f807f8000007f807f8000007f807f800000ff807fc00000
+ff807fc00000ff803fc00000ff003fc00000ff003fc00000ff003fc00000ff001fe00001fe001fe0
+0001fe000fe00001fc000fe00001fc0007f00003f80007f00003f80003f00003f00003f80007f000
+01f80007e00000fc000fc00000fc001fc000007e003f8000003f007e0000001fc1fc00000007fff8
+00000003ffe0000000007f000000>} imagemask
+ }
+ 48 /G30 MSTT31c1f0 AddChar
+%%EndResource
+
+5 9 SJ
+586 878 1928 (They will be part of the next stable version \(2.0\)) 1928 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1051 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+
+%%BeginResource: font MSTT31c1f0
+/G50 [56.0 0.0 2.0 0.0 52.0 67.0]
+/G50 {
+ 50 67 true [1 0 0 -1 -2.0 67.0] {<ffffffff000000fffffffff8000007fffffffe000001fff007ff800000ffc001ffe00000ffc0007f
+f000007fc0003ff800007fc0001ffc00007fc0000ffe00007fc00007ff00007fc00007ff00007fc0
+0003ff80007fc00003ff80007fc00003ff80007fc00003ffc0007fc00001ffc0007fc00001ffc000
+7fc00001ffc0007fc00001ffc0007fc00001ffc0007fc00001ffc0007fc00001ffc0007fc00001ff
+c0007fc00001ff80007fc00003ff80007fc00003ff80007fc00007ff00007fc00007ff00007fc000
+0ffe00007fc0000ffe00007fc0001ffc00007fc0007ff800007fc000fff000007ff803ffe000007f
+ffffff8000007ffffffe0000007fc1ffe00000007fc000000000007fc000000000007fc000000000
+007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc00000
+0000007fc000000000007fc000000000007fc000000000007fc000000000007fc000000000007fc0
+00000000007fc000000000007fc000000000007fc000000000007fc000000000007fc00000000000
+7fc000000000007fc000000000007fc000000000007fc00000000000ffe00000000000ffe0000000
+0001fff00000000007fffc00000000ffffffe0000000ffffffe0000000>} imagemask
+ }
+ 80 /G50 MSTT31c1f0 AddChar
+/G2a [50.0 0.0 7.0 29.0 41.0 70.0]
+/G2a {
+ 34 41 true [1 0 0 -1 -7.0 70.0] {<0000e000000003f000000003f000000003f800000007f800000007f800000007f800000003f80000
+0003f000003c03f00f007e03f01f80ff81f03fc0ffc1e07fc0ffc1e0ffc07fe1e1ffc07ff0e3ff80
+1ff8c7fe0007fccff800007eff80000007f800000001e00000000ff80000007edf800007fccff800
+1ff8c7ff007ff0c3ff807fe1e1ff80ffc1e0ffc0ff81e07fc0ff03f03fc07e03f01f803c03f00f00
+0003f000000003f800000007f800000007f800000007f800000007f800000003f000000003f00000
+0000e00000>} imagemask
+ }
+ 42 /G2a MSTT31c1f0 AddChar
+%%EndResource
+
+3 9 SJ
+586 1021 2321 (The API and tools are compatible with *BSD \(the utilities) 2321 SB
+2 2 SJ
+586 1141 812 (come from 4.4BSD\)) 812 SB
+32 0 0 75 75 0 0 0 60 /ZapfDingbats font
+473 1315 59 (u) 59 SB
+32 0 0 100 100 0 0 1 90 /MSTT31c1f0 font
+7 10 SJ
+586 1285 2232 (Most of the quota management is done in the VFS layer) 2232 SB
+EJ RS
+%%PageTrailer
+%%Trailer
+SVDoc restore
+end
+% TrueType font name key:
+% MSTT31c1bc = 0c27DTimes New RomanF0000003a000001900000
+% MSTT31c1c9 = 0c27DTimes New RomanF00000000000001900000
+% MSTT31c1d6 = 0c27DTimes New RomanF000000000000019000ff
+% MSTT31c1e3 = 0c27DMonotype SortsF00000058000001900000
+% MSTT31c1f0 = 0c27DTimes New RomanF00000064000001900000
+% MSTT31c1fd = 0c27DTimes New RomanF0000004b000001900000
+% MSTT31c20a = 0c27DMonotype SortsF0000004b000001900000
+% MSTT31c217 = 0c27DTimes New RomanF00000043000001900000
+% MSTT31c22e = 0c27DMonotype SortsF0000003f000001900000
+%%DocumentSuppliedResources: procset Win35Dict 3 1
+%%+ font MSTT31c1bc
+%%+ font MSTT31c1c9
+%%+ font MSTT31c1d6
+%%+ font MSTT31c1f0
+%%+ font MSTT31c1fd
+
+%%DocumentNeededResources: font Courier-Bold
+%%+ font ZapfDingbats
+
+%%EOF
+grestore
diff --git a/doc/quotas.ms b/doc/quotas.ms
new file mode 100644
index 0000000..10e200c
--- /dev/null
+++ b/doc/quotas.ms
@@ -0,0 +1,318 @@
+.\" Copyright (c) 1983 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)quotas.ms 6.3 (Berkeley) 4/17/91
+.\"
+.EH 'SMM:4-%''Disc Quotas in a \s-2UNIX\s+2 Environment'
+.OH 'Disc Quotas in a \s-2UNIX\s+2 Environment''SMM:4-%'
+.ND 5th July, 1983
+.TL
+Disc Quotas in a \s-2UNIX\s+2\s-3\u*\d\s0 Environment
+.FS
+* UNIX is a trademark of Bell Laboratories.
+.FE
+.AU
+Robert Elz
+.AI
+Department of Computer Science
+University of Melbourne,
+Parkville,
+Victoria,
+Australia.
+.AB
+.PP
+In most computing environments, disc space is not
+infinite.
+The disc quota system provides a mechanism
+to control usage of disc space, on an
+individual basis.
+.PP
+Quotas may be set for each individual user, on any, or
+all filesystems.
+.PP
+The quota system will warn users when they
+exceed their allotted limit, but allow some
+extra space for current work.
+Repeatedly remaining over quota at logout,
+will cause a fatal over quota condition eventually.
+.PP
+The quota system is an optional part of
+\s-2VMUNIX\s0 that may be included when the
+system is configured.
+.AE
+.NH 1
+Users' view of disc quotas
+.PP
+To most users, disc quotas will either be of no concern,
+or a fact of life that cannot be avoided.
+The
+\fIquota\fP\|(1)
+command will provide information on any disc quotas
+that may have been imposed upon a user.
+.PP
+There are two individual possible quotas that may be
+imposed, usually if one is, both will be.
+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.
+.PP
+.I Quota
+provides information on the quotas that have
+been set by the system administrators, in each
+of these areas, and current usage.
+.PP
+There are four numbers for each limit, the current
+usage, soft limit (quota), hard limit, and number
+of remaining login warnings.
+The soft limit is the number of 1K blocks (or files)
+that the user is expected to remain below.
+Each time the user's usage goes past this limit,
+he will be warned.
+The hard limit cannot be exceeded.
+If a user's usage reaches this number, further
+requests for space (or attempts to create a file)
+will fail with an EDQUOT error, and the first time
+this occurs, a message will be written to the user's
+terminal.
+Only one message will be output, until space occupied
+is reduced below the limit, and reaches it again,
+in order to avoid continual noise from those
+programs that ignore write errors.
+.PP
+Whenever a user logs in with a usage greater than
+his soft limit, he will be warned, and his login
+warning count decremented.
+When he logs in under quota, the counter is reset
+to its maximum value (which is a system configuration
+parameter, that is typically 3).
+If the warning count should ever reach zero (caused
+by three successive logins over quota), the
+particular limit that has been exceeded will be treated
+as if the hard limit has been reached, and no
+more resources will be allocated to the user.
+The \fBonly\fP way to reset this condition is
+to reduce usage below quota, then log in again.
+.NH 2
+Surviving when quota limit is reached
+.PP
+In most cases, the only way to recover from over
+quota conditions, is to abort whatever activity was 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.
+.PP
+However, if you are in the editor and a write fails
+because of an over quota situation, that is not
+a suitable course of action, as it is most likely
+that initially attempting to write the file
+will have truncated its previous contents, so should
+the editor be aborted without correctly writing the
+file not only will the recent changes be lost, but
+possibly much, or even all, of the data
+that previously existed.
+.PP
+There are several possible safe exits for a user
+caught in this situation.
+He may use the editor \fB!\fP shell escape command to
+examine his file space, and remove surplus files.
+Alternatively, using \fIcsh\fP, he may 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.
+.NH 1
+Administering the quota system
+.PP
+To set up and establish the disc quota system,
+there are several steps necessary to be performed
+by the system administrator.
+.PP
+First, the system must be configured to include
+the disc quota sub-system.
+This is done by including the line:
+.DS
+options QUOTA
+.DE
+in the system configuration file, then running
+\fIconfig\fP\|(8)
+followed by a system configuration\s-3\u*\d\s0.
+.FS
+* See also the document ``Building 4.2BSD UNIX Systems with Config''.
+.FE
+.PP
+Second, a decision as to what filesystems need to have
+quotas applied needs to be made.
+Usually, only filesystems that house users' home directories,
+or other user files, will need to be subjected to
+the quota system, though it may also prove useful to
+also include \fB/usr\fR.
+If possible, \fB/tmp\fP should usually be free of quotas.
+.PP
+Having decided on which filesystems quotas need to be
+set upon, the administrator should then allocate the
+available space amongst the competing needs. How this
+should be done is (way) beyond the scope of this document.
+.PP
+Then, the
+\fIedquota\fP\|(8)
+command can be 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 \fB\-p\fP switch
+to edquota will allow this to be easily accomplished.
+.PP
+Once the quotas are set, ready to operate, the system
+must be informed to enforce quotas on the desired filesystems.
+This is accomplished with the
+\fIquotaon\fP\|(8)
+command.
+.I Quotaon
+will either enable quotas for a particular filesystem, or
+with the \fB\-a\fP switch, will enable quotas for each
+filesystem indicated in \fB/etc/fstab\fP as using quotas.
+See
+\fIfstab\fP\|(5)
+for details.
+Most sites using the quota system, will include the
+line
+.DS C
+/etc/quotaon -a
+.DE
+in \fB/etc/rc.local\fP.
+.PP
+Should quotas need to be disabled, the
+\fIquotaoff\fP(8)
+command will do that, however, should the filesystem be
+about to be dismounted, the
+\fIumount\fP\|(8)
+command will disable quotas immediately before the
+filesystem is unmounted.
+This is actually an effect of the
+\fIumount\fP\|(2)
+system call, and it guarantees that the quota system
+will not be disabled if the umount would fail
+because the filesystem is not idle.
+.PP
+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
+\fIquotacheck\fP\|(8)
+command can be used to accomplish this.
+It is not necessary to dismount 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
+.I quotacheck
+when the filesystem is idle will certainly correct any inaccuracy.
+.PP
+The super-user may use the
+\fIquota\fP\|(1)
+command to examine the usage and quotas of any user, and
+the
+\fIrepquota\fP\|(8)
+command may be used to check the usages and limits for
+all users on a filesystem.
+.NH 1
+Some implementation detail.
+.PP
+Disc quota usage and information is stored in a file on the
+filesystem that the quotas are to be applied to.
+Conventionally, this file is \fBquotas\fR in the root of
+the filesystem.
+While this name is not known to the system in any way,
+several of the user level utilities "know" it, and
+choosing any other name would not be wise.
+.PP
+The data in the file comprises an array of structures, indexed
+by uid, one structure for each user on the system (whether
+the user has a quota on this filesystem or not).
+If the uid space is sparse, then the file may have holes
+in it, which would be lost by copying, so it is best to
+avoid this.
+.PP
+The system is informed of the existence of the quota
+file by the
+\fIsetquota\fP\|(2)
+system call.
+It then reads the quota entries for each user currently
+active, then for any files open owned by users who
+are not currently active.
+Each subsequent open of a file on the filesystem, will
+be accompanied by a pairing with its quota information.
+In most cases this information will be retained in core,
+either because the user who owns the file is running some
+process, because other files are open owned by the same
+user, or because some file (perhaps this one) was recently
+accessed.
+In memory, the quota information is kept hashed by user-id
+and filesystem, and retained in an LRU chain so recently
+released data can be easily reclaimed.
+Information about those users whose last process has
+recently terminated is also retained in this way.
+.PP
+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 object.
+.PP
+Measurements have shown
+that the quota code uses a very small percentage of the system
+cpu time consumed in writing a new block to disc.
+.NH 1
+Acknowledgments
+.PP
+The current disc quota system is loosely based upon a very
+early scheme implemented at the University of New South
+Wales, and Sydney University in the mid 70's. That system
+implemented a single combined limit for both files and blocks
+on all filesystems.
+.PP
+A later system was implemented at the University of Melbourne
+by the author, but was not kept highly accurately, eg:
+chown's (etc) did not affect quotas, nor did i/o to a file
+other than one owned by the instigator.
+.PP
+The current system has been running (with only minor modifications)
+since January 82 at Melbourne.
+It is actually just a small part of a much broader resource
+control scheme, which is capable of controlling almost
+anything that is usually uncontrolled in unix. The rest
+of this is, as yet, still in a state where it is far too
+subject to change to be considered for distribution.
+.PP
+For the 4.2BSD release, much work has been done to clean
+up and sanely incorporate the quota code by Sam Leffler and
+Kirk McKusick at The University of California at Berkeley.
diff --git a/doc/quotas.preformated b/doc/quotas.preformated
new file mode 100644
index 0000000..e008aeb
--- /dev/null
+++ b/doc/quotas.preformated
@@ -0,0 +1,330 @@
+
+
+
+
+
+
+
+
+
+ DDiisscc QQuuoottaass iinn aa UUNNIIXX** EEnnvviirroonnmmeenntt
+
+ _R_o_b_e_r_t _E_l_z
+ Department of Computer Science
+ University of Melbourne,
+ Parkville,
+ Victoria,
+ Australia.
+
+
+ _A_B_S_T_R_A_C_T
+
+
+
+ In most computing environments, disc space is
+ not infinite. The disc quota system provides a
+ mechanism to control usage of disc space, on an
+ individual basis.
+
+ Quotas may be set for each individual user,
+ on any, or all filesystems.
+
+ The quota system will warn users when they
+ exceed their allotted limit, but allow some extra
+ space for current work. Repeatedly remaining over
+ quota at logout, will cause a fatal over quota
+ condition eventually.
+
+ The quota system is an optional part of VMU-
+ NIX that may be included when the system is con-
+ figured.
+
+
+ 11.. UUsseerrss'' vviieeww ooff ddiisscc qquuoottaass
+
+ To most users, disc quotas will either be of no con-
+ cern, or a fact of life that cannot be avoided. The
+ _q_u_o_t_a(1) command will provide information on any disc quotas
+ that may have been imposed upon a user.
+
+ There are two individual possible quotas that may be
+ imposed, usually if one is, both will be. 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.
+
+ _Q_u_o_t_a provides information on the quotas that have been
+ set by the system administrators, in each of these areas,
+ and current usage.
+
+ -----------
+ * UNIX is a trademark of Bell Laboratories.
+
+
+
+
+
+
+
+
+
+ SMM:4-2 Disc Quotas in a UNIX Environment
+
+
+ There are four numbers for each limit, the current
+ usage, soft limit (quota), hard limit, and number of remain-
+ ing login warnings. The soft limit is the number of 1K
+ blocks (or files) that the user is expected to remain below.
+ Each time the user's usage goes past this limit, he will be
+ warned. The hard limit cannot be exceeded. If a user's
+ usage reaches this number, further requests for space (or
+ attempts to create a file) will fail with an EDQUOT error,
+ and the first time this occurs, a message will be written to
+ the user's terminal. Only one message will be output, until
+ space occupied is reduced below the limit, and reaches it
+ again, in order to avoid continual noise from those programs
+ that ignore write errors.
+
+ Whenever a user logs in with a usage greater than his
+ soft limit, he will be warned, and his login warning count
+ decremented. When he logs in under quota, the counter is
+ reset to its maximum value (which is a system configuration
+ parameter, that is typically 3). If the warning count
+ should ever reach zero (caused by three successive logins
+ over quota), the particular limit that has been exceeded
+ will be treated as if the hard limit has been reached, and
+ no more resources will be allocated to the user. The oonnllyy
+ way to reset this condition is to reduce usage below quota,
+ then log in again.
+
+ 11..11.. SSuurrvviivviinngg wwhheenn qquuoottaa lliimmiitt iiss rreeaacchheedd
+
+ In most cases, the only way to recover from over quota
+ conditions, is to abort whatever activity was 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 you are in the editor and a write fails
+ because of an over quota situation, that is not a suitable
+ course of action, as it is most likely that initially
+ attempting to write the file will have truncated its previ-
+ ous contents, so should the editor be aborted without cor-
+ rectly writing the file not only will the recent changes be
+ lost, but possibly much, or even all, of the data that pre-
+ viously existed.
+
+ There are several possible safe exits for a user caught
+ in this situation. He may use the editor !! shell escape
+ command to examine his file space, and remove surplus files.
+ Alternatively, using _c_s_h, he may 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.
+
+
+
+
+
+
+
+
+
+
+
+ Disc Quotas in a UNIX Environment SMM:4-3
+
+
+ 22.. AAddmmiinniisstteerriinngg tthhee qquuoottaa ssyysstteemm
+
+ To set up and establish the disc quota system, there
+ are several steps necessary to be performed by the system
+ administrator.
+
+ First, the system must be configured to include the
+ disc quota sub-system. This is done by including the line:
+
+ options QUOTA
+
+ in the system configuration file, then running _c_o_n_f_i_g(8)
+ followed by a system configuration*.
+
+ Second, a decision as to what filesystems need to have
+ quotas applied needs to be made. Usually, only filesystems
+ that house users' home directories, or other user files,
+ will need to be subjected to the quota system, though it may
+ also prove useful to also include //uussrr. If possible, //ttmmpp
+ should usually be free of quotas.
+
+ Having decided on which filesystems quotas need to be
+ set upon, the administrator should then allocate the avail-
+ able space amongst the competing needs. How this should be
+ done is (way) beyond the scope of this document.
+
+ Then, the _e_d_q_u_o_t_a(8) command can be 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 --pp switch to edquota will allow this to be easily accom-
+ plished.
+
+ Once the quotas are set, ready to operate, the system
+ must be informed to enforce quotas on the desired filesys-
+ tems. This is accomplished with the _q_u_o_t_a_o_n(8) command.
+ _Q_u_o_t_a_o_n will either enable quotas for a particular filesys-
+ tem, or with the --aa switch, will enable quotas for each
+ filesystem indicated in //eettcc//ffssttaabb as using quotas. See
+ _f_s_t_a_b(5) for details. Most sites using the quota system,
+ will include the line
+
+ /etc/quotaon -a
+
+ in //eettcc//rrcc..llooccaall.
+
+ Should quotas need to be disabled, the _q_u_o_t_a_o_f_f(8) com-
+ mand will do that, however, should the filesystem be about
+ to be dismounted, the _u_m_o_u_n_t(8) command will disable quotas
+ immediately before the filesystem is unmounted. This is
+ actually an effect of the _u_m_o_u_n_t(2) system call, and it
+ guarantees that the quota system will not be disabled if the
+ -----------
+ * See also the document ``Building 4.2BSD UNIX
+ Systems with Config''.
+
+
+
+
+
+
+
+
+
+ SMM:4-4 Disc Quotas in a UNIX Environment
+
+
+ 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 _q_u_o_t_a_c_h_e_c_k(8) command can be used to accomplish
+ this. It is not necessary to dismount 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 _q_u_o_t_a_c_h_e_c_k when
+ the filesystem is idle will certainly correct any inaccu-
+ racy.
+
+ The super-user may use the _q_u_o_t_a(1) command to examine
+ the usage and quotas of any user, and the _r_e_p_q_u_o_t_a(8) com-
+ mand may be used to check the usages and limits for all
+ users on a filesystem.
+
+ 33.. SSoommee iimmpplleemmeennttaattiioonn ddeettaaiill..
+
+ Disc quota usage and information is stored in a file on
+ the filesystem that the quotas are to be applied to. Con-
+ ventionally, this file is qquuoottaass in the root of the filesys-
+ tem. While this name is not known to the system in any way,
+ several of the user level utilities "know" it, and choosing
+ any other name would not be wise.
+
+ The data in the file comprises an array of structures,
+ indexed by uid, one structure for each user on the system
+ (whether the user has a quota on this filesystem or not).
+ If the uid space is sparse, then the file may have holes in
+ it, which would be lost by copying, so it is best to avoid
+ this.
+
+ The system is informed of the existence of the quota
+ file by the _s_e_t_q_u_o_t_a(2) system call. It then reads the
+ quota entries for each user currently active, then for any
+ files open owned by users who are not currently active.
+ Each subsequent open of a file on the filesystem, will be
+ accompanied by a pairing with its quota information. In
+ most cases this information will be retained in core, either
+ because the user who owns the file is running some process,
+ because other files are open owned by the same user, or
+ because some file (perhaps this one) was recently accessed.
+ In memory, the quota information is kept hashed by user-id
+ and filesystem, and retained in an LRU chain so recently
+ released data can be easily reclaimed. Information about
+ those users whose last process has recently terminated is
+ also retained in this way.
+
+ 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
+
+
+
+
+
+
+
+
+
+ Disc Quotas in a UNIX Environment SMM:4-5
+
+
+ opportunity to object.
+
+ Measurements have shown that the quota code uses a very
+ small percentage of the system cpu time consumed in writing
+ a new block to disc.
+
+ 44.. AAcckknnoowwlleeddggmmeennttss
+
+ The current disc quota system is loosely based upon a
+ very early scheme implemented at the University of New South
+ Wales, and Sydney University in the mid 70's. That system
+ implemented a single combined limit for both files and
+ blocks on all filesystems.
+
+ A later system was implemented at the University of
+ Melbourne by the author, but was not kept highly accurately,
+ eg: chown's (etc) did not affect quotas, nor did i/o to a
+ file other than one owned by the instigator.
+
+ The current system has been running (with only minor
+ modifications) since January 82 at Melbourne. It is actu-
+ ally just a small part of a much broader resource control
+ scheme, which is capable of controlling almost anything that
+ is usually uncontrolled in unix. The rest of this is, as
+ yet, still in a state where it is far too subject to change
+ to be considered for distribution.
+
+ For the 4.2BSD release, much work has been done to
+ clean up and sanely incorporate the quota code by Sam Lef-
+ fler and Kirk McKusick at The University of California at
+ Berkeley.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/repquota(8).html b/doc/repquota(8).html
new file mode 100644
index 0000000..dc3cf70
--- /dev/null
+++ b/doc/repquota(8).html
@@ -0,0 +1,68 @@
+<HTML>
+<HEAD>
+<TITLE>repquota(8) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+repquota - summarize quotas for a file system
+<H1>SYNOPSIS</H1>
+<B>repquota</B>
+[
+<B>-vug</B>
+]
+<B>filesystem</B>
+<BR>
+<B>repquota</B>
+[
+<B>-avug</B>
+]
+<H1>DESCRIPTION</H1>
+<B>Repquota</B>
+prints a summary of the disc usage and quotas for the specified file
+systems. For each user the current number of files and amount of space
+(in kilobytes) is printed, along with any quotas created with
+<A HREF="edquota(8).html">edquota (8)</A>
+.
+<H1>OPTIONS</H1>
+<UL>
+<LI>
+<B>-a</B>
+<BR>
+Report on all file systems indicated in
+<B>/etc/fstab</B>
+to be read-write with quotas.
+<LI>
+<B>-v</B>
+<BR>
+Report all quotas, even if there is no usage.
+<LI>
+<B>-g</B>
+<BR>
+Report quotas for groups.
+<LI>
+<B>-u</B>
+<BR>
+Report quotas for users. This is the default.
+</UL>
+<P>
+Only the super-user may view quotas which are not their own.
+<H1>FILES</H1>
+<B>quota.user</B>
+ : located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+ : located at the filesystem root with group quotas
+<BR>
+<B>/etc/fstab</B>
+ : to find filesystem names and locations
+<H1>SEE ALSO</H1>
+<A HREF="quotactl(2).html">quotactl (2)</A>,
+<A HREF="fstab(5).html">fstab (5)</A>,
+<A HREF="edquota(8).html">edquota (8)</A>,
+<A HREF="quotacheck(8).html">quotacheck (8)</A>,
+<A HREF="quotaon(8).html">quotaon (8)</A>
+</BODY>
+</HTML>
diff --git a/doc/rquotad(8).html b/doc/rquotad(8).html
new file mode 100644
index 0000000..5c20a2f
--- /dev/null
+++ b/doc/rquotad(8).html
@@ -0,0 +1,38 @@
+<HTML>
+<HEAD>
+<TITLE>rquotad(8) manualpage</TITLE>
+<!-- OWNER_NAME="Marco van Wieringen, OpenWorld System Management" -->
+<!-- OWNER_INFO="The OpenWorld Foundation, The Netherlands" -->
+<LINK REV=MADE HREF="mailto:mvw@planets.elm.net">
+</HEAD>
+<BODY>
+<H1>NAME</H1>
+rquotad, rpc.rquotad - remote quota server
+<H1>SYNOPSIS</H1>
+<B>rpc.rquotad</B>
+<H1>DESCRIPTION</H1>
+<B>rquotad</B>
+is an
+<B>rpc (3N)</B>
+server which returns quotas for a user of a local file system
+which is mounted by a remote machine over the
+<B>NFS</B>
+The results are used by
+<A HREF="quota(1).html">quota (1)</A>
+to display user quotas for remote file systems.
+The
+<B>rquotad</B>
+daemon is normally started at boottime from the
+<B>rc.net</B>
+script
+<H1>FILES</H1>
+<B>quota.user</B>
+ : located at the filesystem root with user quotas
+<BR>
+<B>quota.group</B>
+ : located at the filesystem root with group quotas
+<H1>SEE ALSO</H1>
+<A HREF="quota(1).html">quota (1)</A>,
+rpc (3N), nfs (4P), services (5) inetd (8C),
+</BODY>
+</HTML>
diff --git a/dqblk_rpc.h b/dqblk_rpc.h
new file mode 100644
index 0000000..f5a666a
--- /dev/null
+++ b/dqblk_rpc.h
@@ -0,0 +1,20 @@
+/*
+ * Headerfile for rpc quotafile format
+ */
+
+#ifndef _DQBLK_RPC_H
+#define _DQBLK_RPC_H
+
+/* Values used for communication through network */
+#define Q_RPC_GETQUOTA 0x0300 /* get limits and usage */
+#define Q_RPC_SETQUOTA 0x0400 /* set limits and usage */
+#define Q_RPC_SETUSE 0x0500 /* set usage */
+#define Q_RPC_SETQLIM 0x0700 /* set limits */
+
+#define RPC_DQBLK_SIZE_BITS 10
+#define RPC_DQBLK_SIZE (1 << RPC_DQBLK_SIZE_BITS)
+
+/* Operations above this format */
+extern struct quotafile_ops quotafile_ops_rpc;
+
+#endif
diff --git a/dqblk_v1.h b/dqblk_v1.h
new file mode 100644
index 0000000..409a70c
--- /dev/null
+++ b/dqblk_v1.h
@@ -0,0 +1,18 @@
+/*
+ * Headerfile for old quotafile format
+ */
+
+#ifndef _DQBLK_V1_H
+#define _DQBLK_V1_H
+
+/* Values of quota calls */
+#define Q_V1_RSQUASH 0x1000
+#define Q_V1_GETQUOTA 0x300
+#define Q_V1_SETQUOTA 0x400
+
+struct quotafile_ops; /* Will be defined later in quotaio.h */
+
+/* Operations above this format */
+extern struct quotafile_ops quotafile_ops_1;
+
+#endif
diff --git a/dqblk_v2.h b/dqblk_v2.h
new file mode 100644
index 0000000..56aaf5f
--- /dev/null
+++ b/dqblk_v2.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Header file for disk format of new quotafile format
+ *
+ */
+
+#ifndef _DQBLK_V2_H
+#define _DQBLK_V2_H
+
+#include <sys/types.h>
+
+#define Q_V2_GETQUOTA 0x0D00 /* Get limits and usage */
+#define Q_V2_SETQUOTA 0x0E00 /* Set limits and usage */
+#define Q_V2_GETINFO 0x0900 /* Get information about quota */
+#define Q_V2_SETINFO 0x0A00 /* Set information about quota */
+
+/* Structure for format specific information */
+struct v2_mem_dqinfo {
+ uint dqi_flags; /* Flags set in quotafile */
+ uint dqi_blocks; /* Number of blocks in file */
+ uint dqi_free_blk; /* Number of first free block in the list */
+ uint dqi_free_entry; /* Number of first block with free entry in the list */
+ uint dqi_used_entries; /* Number of entries in file - updated by scan_dquots */
+ uint dqi_data_blocks; /* Number of data blocks in file - updated by scan_dquots */
+};
+
+struct v2_mem_dqblk {
+ loff_t dqb_off; /* Offset of dquot in file */
+};
+
+struct quotafile_ops; /* Will be defined later in quotaio.h */
+
+/* Operations above this format */
+extern struct quotafile_ops quotafile_ops_2;
+
+#endif
diff --git a/dqblk_xfs.h b/dqblk_xfs.h
new file mode 100644
index 0000000..8b03d98
--- /dev/null
+++ b/dqblk_xfs.h
@@ -0,0 +1,25 @@
+/*
+ * Headerfile for XFS quota format
+ */
+
+#ifndef _DQBLK_XFS_H
+#define _DQBLK_XFS_H
+
+#include "quotaio_xfs.h"
+
+#define Q_XFS_QUOTAON Q_XQUOTAON
+#define Q_XFS_QUOTAOFF Q_XQUOTAOFF
+#define Q_XFS_GETQUOTA Q_XGETQUOTA
+#define Q_XFS_SETQLIM Q_XSETQLIM
+#define Q_XFS_GETQSTAT Q_XGETQSTAT
+#define Q_XFS_QUOTARM Q_XQUOTARM
+
+#define xfs_mem_dqinfo fs_quota_stat
+#define xfs_kern_dqblk fs_disk_quota
+
+struct quotafile_ops; /* Will be defined later in quotaio.h */
+
+/* Operations above this format */
+extern struct quotafile_ops quotafile_ops_xfs;
+
+#endif
diff --git a/edquota.8 b/edquota.8
new file mode 100644
index 0000000..e02218c
--- /dev/null
+++ b/edquota.8
@@ -0,0 +1,95 @@
+.TH EDQUOTA 8
+.SH NAME
+edquota \- edit user quotas
+.SH SYNOPSIS
+.B edquota
+[
+.B \-p
+.I proto-user
+] [
+.B \-ug
+]
+.IR name .\|.\|.
+.LP
+.B edquota
+[
+.B \-r
+]
+[
+.B \-ug
+]
+.B \-t
+.SH DESCRIPTION
+.IX "edquota command" "" "\fLedquota\fP \(em edit user quotas"
+.IX edit "user quotas \(em \fLedquota\fP"
+.IX "user quotas" "edquota command" "" "\fLedquota\fP \(em edit user quotas"
+.IX "disk quotas" "edquota command" "" "\fLedquota\fP \(em edit user quotas"
+.IX "quotas" "edquota command" "" "\fLedquota\fP \(em edit user quotas"
+.IX "filesystem" "edquota command" "" "\fLedquota\fP \(em edit user quotas"
+.B edquota
+is a quota editor. One or more users or groups may be specified on the command
+line. For each user or group a temporary file is created with an
+.SM ASCII
+representation of the current disk quotas for that user or group and an editor
+is then invoked on the file. The quotas may then be modified, new
+quotas added, etc. Upon leaving the editor,
+.B edquota
+reads the temporary file and modifies the binary quota files to reflect
+the changes made.
+.LP
+The editor invoked is
+.BR vi (1)
+unless either the
+.SB EDITOR
+or the
+.SB VISUAL
+environment variable specifies otherwise.
+.LP
+Only the super-user may edit quotas.
+.SH OPTIONS
+.TP
+.B \-r
+Edit also non-local quota use rpc.rquotad on remote server to set quota.
+The
+.B \-n
+option is equivalent, and is maintained for backward compatibility.
+.TP
+.B \-u
+Edit the user quota. This is the default.
+.TP
+.B \-g
+Edit the group quota.
+.TP
+.B \-p
+Duplicate the quotas of the prototypical user
+specified for each user specified. This is the normal
+mechanism used to initialize quotas for groups of users.
+.TP
+.B \-t
+Edit the soft time limits for each filesystem.
+If the time limits are zero, the default time limits in
+.B <linux/quota.h>
+are used.
+Time units of seconds, minutes, hours, days, weeks, and months
+are understood.
+Time limits are printed in the greatest possible time unit such that
+the value is greater than or equal to one.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+mounted filesystems
+.PD
+.SH SEE ALSO
+.BR quota (1),
+.BR vi (1),
+.BR quotactl (2),
+.BR quotacheck (8),
+.BR quotaon (8),
+.BR repquota (8)
diff --git a/edquota.c b/edquota.c
new file mode 100644
index 0000000..7817750
--- /dev/null
+++ b/edquota.c
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California. All
+ * rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Robert Elz at
+ * The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
+#ident "$Copyright: All rights reserved. $"
+#ident "$Id: edquota.c,v 1.1 2001/03/23 12:03:26 jkar8572 Exp $"
+
+/*
+ * Disk quota editor.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <paths.h>
+#include <stdlib.h>
+
+#include "pot.h"
+#include "quotaops.h"
+#include "quotasys.h"
+#include "quotaio.h"
+#include "common.h"
+
+static char tmpfil[] = _PATH_TMP "EdP.aXXXXXX";
+
+void usage(void)
+{
+#if defined(RPC_SETQUOTA)
+ fprintf(stderr, "%s%s%s%s",
+ _("Usage:\tedquota [-r] [-u] [-F formatname] [-p username] username ...\n"),
+ _("\tedquota [-r] -g [-p groupname] groupname ...\n"),
+ _("\tedquota [-r] [-u] -t\n"), _("\tedquota [-r] -g -t\n"));
+#else
+ fprintf(stderr, "%s%s%s%s",
+ _("Usage:\tedquota [-u] [-F formatname] [-p username] username ...\n"),
+ _("\tedquota -g [-p groupname] groupname ...\n"),
+ _("\tedquota [-u] -t\n"), _("\tedquota -g -t\n"));
+#endif
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ struct dquot *q, *protoprivs, *curprivs, *pprivs, *cprivs;
+ long id, protoid;
+ int quotatype, tmpfd, ret;
+ char *protoname = NULL;
+ int tflag = 0, pflag = 0, rflag = 0, fmt = -1;
+ struct quota_handle **handles;
+
+ gettexton();
+
+ if (argc < 2)
+ usage();
+
+ quotatype = USRQUOTA;
+#if defined(RPC_SETQUOTA)
+ while ((ret = getopt(argc, argv, "ugrntVp:F:")) != EOF) {
+#else
+ while ((ret = getopt(argc, argv, "ugtVp:F:")) != EOF) {
+#endif
+ switch (ret) {
+ case 'p':
+ protoname = optarg;
+ pflag++;
+ break;
+ case 'g':
+ quotatype = GRPQUOTA;
+ break;
+#if defined(RPC_SETQUOTA)
+ case 'n':
+ case 'r':
+ rflag++;
+ break;
+#endif
+ case 'u':
+ quotatype = USRQUOTA;
+ break;
+ case 't':
+ tflag++;
+ break;
+ case 'F':
+ if ((fmt = name2fmt(optarg)) == QF_ERROR) /* Error? */
+ exit(1);
+ break;
+ case 'V':
+ version();
+ exit(0);
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (tflag && argc != 0)
+ usage();
+
+ handles = create_handle_list(0, NULL, quotatype, fmt, (rflag == 0));
+ if (!handles[0]) {
+ dispose_handle_list(handles);
+ fputs(_("No filesystems with quota detected.\n"), stderr);
+ return 0;
+ }
+ if (pflag) {
+ protoid = name2id(protoname, quotatype);
+ protoprivs = getprivs(protoid, handles);
+ for (q = protoprivs; q; q = q->dq_next) {
+ q->dq_dqb.dqb_btime = 0;
+ q->dq_dqb.dqb_itime = 0;
+ }
+ while (argc-- > 0) {
+ id = name2id(*argv++, quotatype);
+ curprivs = getprivs(id, handles);
+
+ for (pprivs = protoprivs, cprivs = curprivs; pprivs && cprivs;
+ pprivs = pprivs->dq_next, cprivs = cprivs->dq_next) {
+ if (strcmp(pprivs->dq_h->qh_quotadev, cprivs->dq_h->qh_quotadev))
+ fprintf(stderr, _("fsname mismatch\n"));
+ else {
+ cprivs->dq_dqb.dqb_bsoftlimit =
+ pprivs->dq_dqb.dqb_bsoftlimit;
+ cprivs->dq_dqb.dqb_bhardlimit =
+ pprivs->dq_dqb.dqb_bhardlimit;
+ cprivs->dq_dqb.dqb_isoftlimit =
+ pprivs->dq_dqb.dqb_isoftlimit;
+ cprivs->dq_dqb.dqb_ihardlimit =
+ pprivs->dq_dqb.dqb_ihardlimit;
+ }
+ }
+ putprivs(curprivs);
+ }
+ dispose_handle_list(handles);
+ warn_new_kernel(fmt);
+ exit(0);
+ }
+
+ umask(077);
+ tmpfd = mkstemp(tmpfil);
+ fchown(tmpfd, getuid(), getgid());
+ if (tflag) {
+ writetimes(handles, tmpfd);
+ if (!editprivs(tmpfil) && (readtimes(handles, tmpfd) < 0))
+ die(1, _("Failed to parse grace times file.\n"));
+ }
+ else {
+ for (; argc > 0; argc--, argv++) {
+ id = name2id(*argv, quotatype);
+ curprivs = getprivs(id, handles);
+ writeprivs(curprivs, tmpfd, *argv, quotatype);
+ if (!editprivs(tmpfil) && !readprivs(curprivs, tmpfd))
+ putprivs(curprivs);
+ freeprivs(curprivs);
+ }
+ }
+ dispose_handle_list(handles);
+ warn_new_kernel(fmt);
+
+ close(tmpfd);
+ unlink(tmpfil);
+ return 0;
+}
diff --git a/install-sh b/install-sh
new file mode 100755
index 0000000..e9de238
--- /dev/null
+++ b/install-sh
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/mntopt.h b/mntopt.h
new file mode 100644
index 0000000..c09b35f
--- /dev/null
+++ b/mntopt.h
@@ -0,0 +1,22 @@
+#ifndef _MNTOPT_H
+#define _MNTOPT_H
+
+#include <mntent.h>
+
+/* filesystem type */
+#define MNTTYPE_EXT2 "ext2" /* 2nd Extended file system */
+#define MNTTYPE_EXT3 "ext3" /* ext2 + journaling */
+#define MNTTYPE_MINIX "minix" /* MINIX file system */
+#define MNTTYPE_UFS "ufs" /* UNIX file system */
+#define MNTTYPE_UDF "udf" /* OSTA UDF file system */
+#define MNTTYPE_REISER "reiser" /* Reiser file system */
+#define MNTTYPE_XFS "xfs" /* SGI XFS file system */
+
+/* mount options */
+#define MNTOPT_NOQUOTA "noquota" /* don't enforce quota */
+#define MNTOPT_QUOTA "quota" /* enforce user quota */
+#define MNTOPT_USRQUOTA "usrquota" /* enforce user quota */
+#define MNTOPT_GRPQUOTA "grpquota" /* enforce group quota */
+#define MNTOPT_RSQUASH "rsquash" /* root as ordinary user */
+
+#endif
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..cbd31a6
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,857 @@
+# polish translation for LinuxPL.
+# i know that there are many mismatches, please inform me about them
+# Copyright (C) 2000 Free Software Foundation, Inc.
+# PAUL NIEWIADOMSKI <lilo@free.poltronic.net>, 2000.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: 1\n"
+"POT-Creation-Date: 2000-07-19 17:30+0200\n"
+"PO-Revision-Date: 2000-07-17 15:22+0200\n"
+"Last-Translator: PAUL NIEWIADOMSKI <lilo@free.poltronic.net>\n"
+"Language-Team: PL <PL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-2\n"
+"Content-Transfer-Encoding: 8-BIT\n"
+
+#: edquota.c:81 quotaops.c:143 setquota.c:111
+#, c-format
+msgid "%s: no such user\n"
+msgstr "%s: nie ma takiego u¿ytkownika\n"
+
+#: edquota.c:86 quotaops.c:148 setquota.c:116
+#, c-format
+msgid "%s: no such group\n"
+msgstr "%s: nie ma takiej grupy\n"
+
+#: edquota.c:89 quotaops.c:151 setquota.c:119
+#, c-format
+msgid "%d: unknown quota type\n"
+msgstr "%d: nieznany typ limitu\n"
+
+#: edquota.c:162
+msgid "fsname mismatch\n"
+msgstr "nieprawid³owa nazwa systemu plików\n"
+
+#: edquota.c:207
+msgid "Usage:\tedquota [-n] [-u] [-p username] username ...\n"
+msgstr "U¿ycie:\tedquota [-n] [-u] [-p u¿ytkownik] u¿ytkownik ...\n"
+
+#: edquota.c:208
+msgid "\tedquota [-n] -g [-p groupname] groupname ...\n"
+msgstr "\tedquota [-n] -g [-p grupa] grupa ...\n"
+
+#: edquota.c:209
+msgid "\tedquota [-n] [-u] -t\n"
+msgstr ""
+
+#: edquota.c:209
+msgid "\tedquota [-n] -g -t\n"
+msgstr ""
+
+#: edquota.c:212
+msgid "Usage:\tedquota [-u] [-p username] username ...\n"
+msgstr "U¿ycie:\tedquota [-u] [-p u¿ytkownik] u¿ytkownik ...\n"
+
+#: edquota.c:213
+msgid "\tedquota -g [-p groupname] groupname ...\n"
+msgstr "\tedquota -g [-p grupa] grupa ...\n"
+
+#: edquota.c:214
+msgid "\tedquota [-u] -t\n"
+msgstr ""
+
+#: edquota.c:214
+msgid "\tedquota -g -t\n"
+msgstr ""
+
+#: quota.c:81
+#, c-format
+msgid "quota %s, with RPC and EXT2_DIRECT options.\n"
+msgstr "quota %s, z opcjami RPC i EXT2_DIRECT.\n"
+
+#: quota.c:83
+#, c-format
+msgid "quota %s, with RPC options.\n"
+msgstr "quota %s, z opcjami RPC.\n"
+
+#: quota.c:87
+#, c-format
+msgid "quota %s, with EXT2_DIRECT options.\n"
+msgstr "quota %s, z opcjami EXT2_DIRECT.\n"
+
+#: quota.c:89
+#, c-format
+msgid "quota %s, without special options.\n"
+msgstr "quota %s, bez ¿adnych specjalnych opcji.\n"
+
+#: quota.c:169
+msgid "Usage: quota [-guqvV]"
+msgstr "U¿ycie: quota [-guqvV]"
+
+#: quota.c:170
+msgid "\tquota [-qv] -u username ..."
+msgstr "\tquota [-qv] -u u¿ytkownik ..."
+
+#: quota.c:171
+msgid "\tquota [-qv] -g groupname ..."
+msgstr "\tquota [-qv] -g grupa ..."
+
+#: quota.c:185
+msgid "(no account)"
+msgstr "(brak konta)"
+
+#: quota.c:190 quota.c:210
+#, c-format
+msgid "quota: %s (uid %d): permission denied\n"
+msgstr "quota: %s (uid %d): brak prawa dostêpu\n"
+
+#: quota.c:205
+#, c-format
+msgid "quota: %s: unknown user\n"
+msgstr "quota: %s: nieznany u¿ytkownik\n"
+
+#: quota.c:229
+msgid "(no entry)"
+msgstr "(brak wpisu)"
+
+#: quota.c:242 quota.c:272
+#, c-format
+msgid "quota: %s (gid %d): permission denied\n"
+msgstr "quota: %s (gid %d): brak prawa dostêpu\n"
+
+#: quota.c:260
+#, c-format
+msgid "quota: %s: unknown group\n"
+msgstr "quota: %s: nieznana grupa\n"
+
+#: quota.c:301
+msgid "File limit reached on"
+msgstr "Limit plików osi±gniêty na"
+
+#: quota.c:305
+msgid "In file grace period on"
+msgstr "Okres pob³a¿liwo¶ci dla przekroczonego limitu plików na"
+
+#: quota.c:307
+msgid "Over file quota on"
+msgstr "Limit plików przekroczony na"
+
+#: quota.c:311
+msgid "Block limit reached on"
+msgstr "Limit bloków osi±gniêty na"
+
+#: quota.c:315
+msgid "In block grace period on"
+msgstr "Okres pob³a¿liwo¶ci dla przekroczonego limitu bloków na"
+
+#: quota.c:317
+msgid "Over block quota on"
+msgstr "Limit bloków przekroczony na"
+
+#: quota.c:366 quota.c:400 repquota.c:309 warnquota.c:150
+msgid "none"
+msgstr "brak"
+
+#: quota.c:371
+#, c-format
+msgid "Disk quotas for %s %s (%cid %d): %s\n"
+msgstr "Limity dyskowe dla %s %s (%cid %d): %s\n"
+
+#: quota.c:375
+msgid "Filesystem"
+msgstr "System plików"
+
+#: quota.c:376
+msgid "blocks"
+msgstr "bloki"
+
+#: quota.c:377 quota.c:381
+msgid "quota"
+msgstr "miêkki"
+
+#: quota.c:378 quota.c:382
+msgid "limit"
+msgstr "twardy"
+
+#: quota.c:379 quota.c:383
+msgid "grace"
+msgstr "pob³."
+
+#: quota.c:380
+msgid "files"
+msgstr "pliki"
+
+#: quotacheck.c:111 warnquota.c:72
+msgid "Virtual memory exhausted\n"
+msgstr "Brak wirtualnej pamiêci\n"
+
+#: quotacheck.c:146
+#, c-format
+msgid "Adding dquot structure type %s for %d\n"
+msgstr "Dodajê strukturê dquot typu %s dla %d\n"
+
+#: quotacheck.c:190
+msgid ""
+"Usage:\n"
+"\tquotacheck [-g] [-u] [-R] [-vd] -a\n"
+msgstr ""
+"U¿ycie:\n"
+"\tquotacheck [-g] [-u] [-R] [-vd] -a\n"
+
+#: quotacheck.c:191
+msgid "\tquotacheck [-g] [-u] [-vd] filesys ...\n"
+msgstr "\tquotacheck [-g] [-u] [-vd] systemplików ...\n"
+
+#: quotacheck.c:270
+#, c-format
+msgid "%s: not found\n"
+msgstr "nie znaleziono: %s\n"
+
+#: quotacheck.c:276
+#, c-format
+msgid "Scanning %s [%s] "
+msgstr "Skanujê %s [%s] "
+
+#: quotacheck.c:299
+msgid "done\n"
+msgstr "zrobiono\n"
+
+#: quotacheck.c:301
+#, c-format
+msgid "Checked %d directories and %d files\n"
+msgstr "Sprawdzono %d katalogów i %d plików\n"
+
+#: quotacheck.c:304
+#, c-format
+msgid "%s: not a directory\n"
+msgstr "%s: nie jest katalogiem\n"
+
+#: quotacheck.c:319 quotaon.c:156 repquota.c:153
+#, c-format
+msgid "%s not found in fstab\n"
+msgstr "%s nie zosta³ znaleziony w fstab\n"
+
+#: quotacheck.c:322
+#, c-format
+msgid ""
+"Allocated %d bytes memory\n"
+"Free'd %d bytes\n"
+"Lost %d bytes\n"
+msgstr ""
+"Zaallokowano %d bajtów pamiêci\n"
+"Zwolniono %d bajtów\n"
+"Stracono %d bajtów\n"
+
+#: quotacheck.c:341
+#, c-format
+msgid "quotacheck: error while opening %s\n"
+msgstr "quotacheck: b³±d podczas otwierania %s\n"
+
+#: quotacheck.c:345
+msgid "in-use inode map"
+msgstr "mapa u¿ywanych i-wêz³ów"
+
+#: quotacheck.c:346
+msgid "quotacheck: error while allocating inode file bitmap\n"
+msgstr "quotacheck: b³±d podczas allokowania bitmapy i-wêz³ów plików\n"
+
+#: quotacheck.c:350
+msgid "directory inode map"
+msgstr "mapa i-wêz³ów katalogów"
+
+#: quotacheck.c:351
+msgid "quotacheck: error while allocating inode directory bitmap\n"
+msgstr "quotacheck: b³±d podczas allokowania bitmapy i-wêz³ów katalogów\n"
+
+#: quotacheck.c:356
+msgid "quotacheck: error while opening inode scan\n"
+msgstr "quotacheck: b³±d podczas otwierania skanu i-wêz³ów\n"
+
+#: quotacheck.c:361
+msgid "quotacheck: error while starting inode scan\n"
+msgstr "quotacheck: b³±d podczas uruchamiania skanu i-wêz³ów\n"
+
+#: quotacheck.c:368
+#, c-format
+msgid "Found i_num %ld\n"
+msgstr "Znaleziono i_num %ld\n"
+
+#: quotacheck.c:384
+msgid "Something weird while scanning\n"
+msgstr "Co¶ dziwnego podczas skanowania\n"
+
+#: quotacheck.c:415
+#, c-format
+msgid "Hmm, file `%s/%s' not found\n"
+msgstr "Hmm, plik %s/%s nie zosta³ znaleziony\n"
+
+#: quotacheck.c:416
+msgid ""
+"Guess you'd better run fsck first !\n"
+"exiting...\n"
+msgstr ""
+"Ururchom najpierw fsck !\n"
+"Koñczê...\n"
+
+#: quotacheck.c:443
+#, c-format
+msgid "\tAdding %s size %d ino %d links %d\n"
+msgstr "\tDodajê %s, o rozmiarze %d, iwêze³ %d, po³±czeñ %d\n"
+
+#: quotacheck.c:454
+msgid "Scanning stored directories from directory stack\n"
+msgstr "Skanujê zapisane na stosie katalogi\n"
+
+#: quotacheck.c:459
+#, c-format
+msgid ""
+"popd %s\n"
+"Entering directory %s\n"
+msgstr ""
+"popd %s\n"
+"Wchodzê do katalogu %s\n"
+
+#: quotacheck.c:470
+#, c-format
+msgid "Leaving %s\n"
+msgstr "Opuszczam %s\n"
+
+#: quotacheck.c:482
+#, c-format
+msgid "Adding hardlink for ino %d\n"
+msgstr "Dodajê dowi±zanie na i-wêze³ %d\n"
+
+#: quotacheck.c:528
+#, c-format
+msgid "Can't add dquot structure type %s for uid %d\n"
+msgstr "Nie mogê dodaæ struktury dquot typu %s dla uid %d\n"
+
+#: quotacheck.c:558
+#, c-format
+msgid "Adding blocks from hardlinks for %s %d\n"
+msgstr "Dodajê bloki z dowi±zañ na %s %d\n"
+
+#: quotacheck.c:622
+#, c-format
+msgid "Using quotafile %s\n"
+msgstr "Korzystam z pliku limitów %s\n"
+
+#: quotacheck.c:628
+#, c-format
+msgid "Updating in-core %s quotas\n"
+msgstr "Aktualizujê wewnêtrzne limity typu %s\n"
+
+#: quotacheck.c:665
+#, c-format
+msgid "%s %d: curinodes: %d curblocks: %d without hardlinks\n"
+msgstr "%s %d: akt.iwêz³ów: %d akt.bloków: %d bez dowi±zañ\n"
+
+#: quotacheck.c:669
+#, c-format
+msgid "%s %d: curinodes: %d curblocks: %d with hardlinks\n"
+msgstr "%s %d: akt.iwêz³ów: %d akt.bloków: %d z dowi±zaniami\n"
+
+#: quotaon.c:86
+#, c-format
+msgid "Name must be quotaon or quotaoff not %s\n"
+msgstr "Nazw± musi byæ quotaon, lub quotaoff, nie %s\n"
+
+#: quotaon.c:163
+#, c-format
+msgid ""
+"Usage:\n"
+"\t%s [-g] [-u] [-v] -a\n"
+msgstr ""
+"U¿ycie:\n"
+"\t%s [-g] [-u] [-v] -a\n"
+
+#: quotaon.c:164
+#, c-format
+msgid "\t%s [-g] [-u] [-v] filesys ...\n"
+msgstr "\t%s [-g] [-u] [-v] systemplików ...\n"
+
+#: quotaon.c:177
+#, c-format
+msgid "%s: %s quotas turned off\n"
+msgstr "%s: %s limity wy³±czone\n"
+
+#: quotaon.c:182
+#, c-format
+msgid "quotaon: using %s on "
+msgstr "quotaon: u¿ywam %s dla "
+
+#: quotaon.c:187
+#, c-format
+msgid "%s: %s quotas turned on\n"
+msgstr "%s: %s limity w³±czone\n"
+
+#: quotaon.c:199
+msgid "quotaon: set root_squash on"
+msgstr "quotaon: w³±czono root_squash"
+
+#: quotaon.c:205
+#, c-format
+msgid "%s: %s root_squash turned off\n"
+msgstr "%s: %s wy³±czono root_squash\n"
+
+#: quotaon.c:207
+#, c-format
+msgid "%s: %s root_squash turned on\n"
+msgstr "%s: %s w³±czono root_squash\n"
+
+#: quotaops.c:82
+msgid "day"
+msgstr "dzieñ"
+
+#: quotaops.c:84 repquota.c:314 warnquota.c:155
+#, c-format
+msgid "%d days"
+msgstr "%d dni"
+
+#: quotaops.c:89
+msgid "hour"
+msgstr "godzina"
+
+#: quotaops.c:91
+#, c-format
+msgid "%d hours"
+msgstr "%d godziny"
+
+#: quotaops.c:96
+msgid "minute"
+msgstr "minuta"
+
+#: quotaops.c:98
+#, c-format
+msgid "%d minutes"
+msgstr "%d minuty"
+
+#: quotaops.c:103
+msgid "second"
+msgstr "sekunda"
+
+#: quotaops.c:105
+#, c-format
+msgid "%d seconds"
+msgstr "%d sekundy"
+
+#: quotaops.c:124
+#, c-format
+msgid ""
+"%s: bad units, specify:\n"
+" %s, %s, %s, or %s"
+msgstr ""
+"%s: z³e jednostki, podaj:\n"
+" %s, %s, %s, lub %s"
+
+#: quotaops.c:182
+msgid "edquota: out of memory\n"
+msgstr "edquota: brak pamiêci\n"
+
+#: quotaops.c:191
+msgid "Warning: Quotas are not compiled into this kernel\n"
+msgstr "Uwaga: Quota nie jest wkompilowane w to j±dro\n"
+
+#: quotaops.c:315
+#, c-format
+msgid "Disk quotas for %s %s (%cid %d):\n"
+msgstr "Limity dla %s %s (%cid %d):\n"
+
+#: quotaops.c:319
+msgid ""
+" Filesystem blocks soft hard inodes "
+"soft hard\n"
+msgstr ""
+" System plików bloki miêkki twardy i-wêz³y "
+"miêkki twardy\n"
+
+#: quotaops.c:332
+#, c-format
+msgid "Quotas for %s %s:\n"
+msgstr "Limity dla %s %s:\n"
+
+#: quotaops.c:334
+#, c-format
+msgid "%s: %s %d, limits (soft = %d, hard = %d)\n"
+msgstr "%s: %s %d, limity (miêkki = %d, twardy = %d)\n"
+
+#: quotaops.c:335
+msgid "blocks in use:"
+msgstr "u¿ywanych bloków:"
+
+#: quotaops.c:339
+#, c-format
+msgid "%s %d, limits (soft = %d, hard = %d)\n"
+msgstr "%s %d, limity (miêkki = %d, twardy = %d)\n"
+
+#: quotaops.c:340
+msgid "\tinodes in use:"
+msgstr "\tu¿ywanych iwêz³ów:"
+
+#: quotaops.c:367 quotaops.c:580
+msgid "Can't re-read temp file!!\n"
+msgstr "Nie mogê odczytaæ pliku tymczasowego\n"
+
+#: quotaops.c:385 quotaops.c:596
+#, c-format
+msgid ""
+"bad format:\n"
+"%s\n"
+msgstr ""
+"z³y format:\n"
+"%s\n"
+
+#: quotaops.c:421
+#, c-format
+msgid "%s: cannot change current block allocation\n"
+msgstr "%s: nie mogê zmieniæ aktualnej allokacji bloków\n"
+
+#: quotaops.c:423
+#, c-format
+msgid "%s: cannot change current inode allocation\n"
+msgstr "%s: nie mogê zmieniæ aktualnej allokacji iwêz³ów\n"
+
+#: quotaops.c:434 quotaops.c:608
+#, c-format
+msgid "%s: bad format\n"
+msgstr "%s: z³y format\n"
+
+#: quotaops.c:438 quotaops.c:455 quotaops.c:462 quotaops.c:612
+#, c-format
+msgid "%s: %s: bad format\n"
+msgstr "%s: %s: z³y format\n"
+
+#: quotaops.c:443
+#, c-format
+msgid " blocks in use: %d, limits (soft = %d, hard = %d)"
+msgstr " u¿ywanych bloków: %d, limity (miêkki = %d, twardy = %d)"
+
+#: quotaops.c:446 quotaops.c:620
+#, c-format
+msgid "%s:%s: bad format\n"
+msgstr "%s:%s: z³y format\n"
+
+#: quotaops.c:459
+#, c-format
+msgid "\tinodes in use: %d, limits (soft = %d, hard = %d)"
+msgstr "\tu¿ywanych iwêz³ów: %d, limity (miêkki = %d, twardy = %d)"
+
+#: quotaops.c:499
+#, c-format
+msgid "%s: cannot change current allocation\n"
+msgstr "%s: nie mogê zmieniæ aktualnej allokacji\n"
+
+#: quotaops.c:537 quotaops.c:547
+#, c-format
+msgid "Grace period before enforcing soft limits for %ss:\n"
+msgstr "Okres pob³a¿liwo¶ci przed wymuszeniem miêkkich limitów dla %s:\n"
+
+#: quotaops.c:538 quotaops.c:546
+msgid "Time units may be: days, hours, minutes, or seconds\n"
+msgstr "Jednostkami czasu mog± byæ: days, hours, minutes, seconds\n"
+
+#: quotaops.c:539
+msgid " Filesystem Block grace period Inode grace period\n"
+msgstr ""
+" System plików Pob³a¿liwo¶æ dla bloków Pob³a¿liwo¶æ dla iwêz³ów\n"
+
+#: quotaops.c:550
+#, c-format
+msgid "%s: block grace period: %s, "
+msgstr "%s: okres pob³a¿liwo¶ci dla bloków: %s,"
+
+#: quotaops.c:552
+#, c-format
+msgid "file grace period: %s\n"
+msgstr "okres pob³a¿liwo¶ci dla plików: %s\n"
+
+#: quotaops.c:617
+#, c-format
+msgid " block grace period: %d %s file grace period: %d %s"
+msgstr ""
+" okres pob³a¿liwo¶ci dla bloków: %d %s okres pob³a¿liwo¶ci dla plików: %d %s"
+
+#: quotastats.c:35
+#, c-format
+msgid "Number of dquot lookups: %ld\n"
+msgstr "Liczba poszukiwañ dquot: %ld\n"
+
+#: quotastats.c:36
+#, c-format
+msgid "Number of dquot drops: %ld\n"
+msgstr "Liczba zrzutów dquot: %ld\n"
+
+#: quotastats.c:37
+#, c-format
+msgid "Number of still active inodes with quota : %ld\n"
+msgstr "Liczba aktywnych iwêz³ów dla limitu: %ld\n"
+
+#: quotastats.c:39
+#, c-format
+msgid "Number of dquot reads: %ld\n"
+msgstr "Liczba odczytów dquot: %ld\n"
+
+#: quotastats.c:40
+#, c-format
+msgid "Number of dquot writes: %ld\n"
+msgstr "Liczba zapisów dquot: %ld\n"
+
+#: quotastats.c:41
+#, c-format
+msgid "Number of quotafile syncs: %ld\n"
+msgstr "Liczba synchronizacji pliku limitów: %ld\n"
+
+#: quotastats.c:42
+#, c-format
+msgid "Number of dquot cache hits: %ld\n"
+msgstr "Liczba trafieñ cache'u dquot: %ld\n"
+
+#: quotastats.c:43
+#, c-format
+msgid "Number of allocated dquots: %ld\n"
+msgstr "Liczba zaallokowanych struktur dquot: %ld\n"
+
+#: quotastats.c:44
+#, c-format
+msgid "Number of free dquots: %ld\n"
+msgstr "Liczba wolnych dquot: %ld\n"
+
+#: quotastats.c:45
+#, c-format
+msgid "Number of in use dquot entries (user/group): %ld\n"
+msgstr "Liczba u¿ywanych wpisów dquot (u¿ytkownik/grupa): %ld\n"
+
+#: repquota.c:159
+#, c-format
+msgid ""
+"Usage:\n"
+"\t%s\n"
+"\t%s\n"
+msgstr ""
+"U¿ycie:\n"
+"\t%s\n"
+"\t%s\n"
+
+#: repquota.c:160
+#, fuzzy
+msgid "repquota [-v] [-g] [-u] -a"
+msgstr "repquota [-v] [-g] [-u] systemplików ..."
+
+#: repquota.c:161
+msgid "repquota [-v] [-g] [-u] filesys ..."
+msgstr "repquota [-v] [-g] [-u] systemplików ..."
+
+#: repquota.c:181
+msgid "*** Warning: Quotas are not compiled into this kernel\n"
+msgstr "*** Uwaga: Quota nie s± wkompilowane w to j±dro\n"
+
+#: repquota.c:186
+#, c-format
+msgid "*** Report for %s quotas on %s (%s)\n"
+msgstr "*** Raport dla %s limitów na %s (%s)\n"
+
+#: repquota.c:203
+msgid " Block limits File limits\n"
+msgstr " Limity bloków Limity plików\n"
+
+#: repquota.c:204
+msgid ""
+"User used soft hard grace used soft hard grace\n"
+msgstr ""
+"U¿ytkownik u¿yw. miê. twa. pob. u¿yw. miê. twa. pob.\n"
+
+#: repquota.c:279
+msgid "out of memory for fileusage structures\n"
+msgstr "brak p±miêci dla struktury wykorzystania systemu plików\n"
+
+#: rquota_svc.c:103 rquota_svc.c:182
+msgid "unable to free arguments"
+msgstr "nie mogê usun±æ argumentów"
+
+#: rquota_svc.c:202
+msgid "cannot create udp service."
+msgstr "nie mogê stworzyæ us³ugi udp."
+
+#: rquota_svc.c:206
+msgid "unable to register (RQUOTAPROG, RQUOTAVERS, udp)."
+msgstr "nie mogê zarejestrowaæ (RQUOTAPROG, RQUOTAVERS, udp)."
+
+#: rquota_svc.c:210
+msgid "unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp)."
+msgstr "nie mogê zarejestrowaæ (RQUOTAPROG, EXT_RQUOTAVERS, udp)."
+
+#: rquota_svc.c:216
+msgid "cannot create tcp service."
+msgstr "nie mogê stworzyæ us³ugi tcp."
+
+#: rquota_svc.c:220
+msgid "unable to register (RQUOTAPROG, RQUOTAVERS, tcp)."
+msgstr "nie mogê zarejestrowaæ (RQUOTAPROG, RQUOTAVERS, tcp)."
+
+#: rquota_svc.c:224
+msgid "unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp)."
+msgstr "nie mogê zarejestrowaæ (RQUOTAPROG, EXT_RQOUTAVERS, tcp)."
+
+#: rquota_svc.c:230
+msgid "svc_run returned"
+msgstr "swc_run zwróci³o"
+
+#: set_limits_example.c:17
+#, c-format
+msgid "copy_user_quota_limits: Failed to set userquota for uid %ld : %s\n"
+msgstr ""
+"copy_user_quota_limits: nie mogê ustawiæ limitów u¿ytkownika dla uid %ld : "
+"%s\n"
+
+#: set_limits_example.c:23
+#, c-format
+msgid "copy_user_quota_limits: Failed to get userquota for uid %ld : %s\n"
+msgstr ""
+"copy_user_quota_limits: nie mogê pobraæ limitów u¿ytkownika dla uid %ld : "
+"%s\n"
+
+#: set_limits_example.c:38
+#, c-format
+msgid "copy_group_quota_limits: Failed to set groupquota for uid %ld : %s\n"
+msgstr ""
+"copy_group_quota_limits: nie mogê ustawiæ limitów grupy dla uid %ld : %s\n"
+
+#: set_limits_example.c:44
+#, c-format
+msgid "copy_group_quota_limits: Failed to get groupquota for uid %ld : %s\n"
+msgstr ""
+"copy_group_quota_limits: nie mogê odczytaæ limitór grupy dla uid %ld : %s\n"
+
+#: setquota.c:74
+msgid ""
+"Usage:\n"
+"\tsetquota [-u|-g] [-n] <username|groupname> <filesystem>\n"
+"\t\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit>\n"
+"\tsetquota [-u|-g] [-n] <-p protousername|protogroupname> "
+"<username|groupname> <filesystem>\n"
+msgstr ""
+"U¿ycie:\n"
+"\tsetquota [-u|-g] [-n] <u¿ytkownik|grupa> <systemplików>\n"
+"\t\t<bloki-miêkki> <bloki-twardy> <iwêz³umiêkki> <iwêz³ytwary>\n"
+"\tsetquota [-u|-g] [-n] <-p u_prototyp|g_prototyp> <u¿ytkownik|grupa> "
+"<systemplików>\n"
+
+#: setquota.c:79
+msgid ""
+"Usage:\n"
+"\tsetquota [-u|-g] <username|groupname> <filesystem>\n"
+"\t\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit>\n"
+"\tsetquota [-u|-g] <-p protousername|protogroupname> <username|groupname> "
+"<filesystem>\n"
+msgstr ""
+"U¿ycie:\n"
+"\tsetquota [-u|-g] <u¿ytkownik|grupa> <systemplików>\n"
+"\t\t<bloki-miêkki> <bloki-twardy> <iwêz³y-miêkki> <iwêz³y-twardy>\n"
+"\tsetquota [-u|-g] <-p u_prototyp|g_prototyp> <u¿ytkownik|grupa> "
+"<systemplików>\n"
+
+#: setquota.c:152
+msgid "setquota: permission denied\n"
+msgstr "setquota: brak prawa dostêpu\n"
+
+#: setquota.c:180
+#, c-format
+msgid "Unknown option -%c\n"
+msgstr "Nieznana opcja -%c\n"
+
+#: setquota.c:193
+#, c-format
+msgid "Unknown protoname %s for quotatype %s\n"
+msgstr "Nieznany prototyp %s dla limity typu %s\n"
+
+#: setquota.c:213 setquota.c:231
+#, c-format
+msgid "File system %s not found\n"
+msgstr "Nie znaleziono system plików %s\n"
+
+#: setquota.c:252
+msgid "Invalid number: block-soft\n"
+msgstr "Nieprawid³owa liczba: bloki-miêkki\n"
+
+#: setquota.c:260
+msgid "Invalid number: block-hard\n"
+msgstr "Nieprawid³owa liczba: bloki-twardy\n"
+
+#: setquota.c:268
+msgid "Invalid number: inode-soft\n"
+msgstr "Nieprawid³owa liczba: iwêz³y-miêkki\n"
+
+#: setquota.c:276
+msgid "Invalid number: inode-hard\n"
+msgstr "Nieprawid³owa liczba: iwêz³y-twardy\n"
+
+#: setquota.c:293
+msgid "File system not found\n"
+msgstr "Nie znaleziono system plików\n"
+
+#: warnquota.c:177
+msgid "/usr/lib/sendmail -t"
+msgstr ""
+
+#: warnquota.c:178 warnquota.c:179
+msgid "support@localhost"
+msgstr ""
+
+#: warnquota.c:180
+msgid "Disk Quota usage on system"
+msgstr "Wykorzystanie limitów dyskowych"
+
+#: warnquota.c:182
+msgid "root"
+msgstr ""
+
+#: warnquota.c:184
+msgid ""
+"Hi,\n"
+"\n"
+"We noticed that you are in violation with the quotasystem\n"
+"used on this system. We have found the following violations:\n"
+msgstr ""
+"Cze¶æ!\n"
+"Zauwa¿yli¶my naruszenie zasad systemu limitowania przestrzeni dyskowej,\n"
+"u¿ywanego na tym systemie. Znale¼li¶my nastêpuj±ce naruszenia:\n"
+
+#: warnquota.c:191
+msgid ""
+"\n"
+" Block limits File limits\n"
+msgstr ""
+"\n"
+" Limity bloków Limity plików\n"
+
+#: warnquota.c:192
+msgid ""
+"Filesystem used soft hard grace used soft hard grace\n"
+msgstr ""
+"System plików u¿yw. miêkkie twa. pob³. u¿yw. miê. twa. pob³.\n"
+
+#: warnquota.c:217
+msgid ""
+"\n"
+"We hope that you will cleanup before your grace period expires.\n"
+"\n"
+"Basically, this means that the system thinks you are using more disk space\n"
+"on the above partition(s) than you are allowed. If you do not delete files\n"
+"and get below your quota before the grace period expires, the system will\n"
+"prevent you from creating new files.\n"
+"\n"
+"For additional assistance, please contact us at support@localhost or via\n"
+"phone at (xxx) xxx-xxxx or (xxx) xxx-xxxx.\n"
+msgstr ""
+"\n"
+"Mamy nadziejê, ¿e posprz±tasz przed up³yniêciem okresu pob³a¿liwo¶ci.\n"
+"\n"
+"Oznancza to, i¿ system uwa¿a, ¿e u¿ywasz, na podanych systemach plików,\n"
+"wiêcej powierzchni, ni¿ jeste¶ upowa¿niony. Je¿eli nie posprz±tasz tak, aby\n"
+"znale¼æ siê poni¿ej limitów przed up³yniêciem okresu pob³a¿liwo¶ci, system\n"
+"zabroni Ci tworzyæ nowe pliki.\n"
+"\n"
+"Je¿eli chcesz dowiedzieæ siê wiêcej skontaktuj siê z nami: "
+"support@localhost\n"
diff --git a/pot.c b/pot.c
new file mode 100644
index 0000000..bfacfe2
--- /dev/null
+++ b/pot.c
@@ -0,0 +1,15 @@
+#include "pot.h"
+#include <locale.h>
+
+/*************************************************************************
+ * if you want to turn off gettext without changing sources edit pot.h
+ *************************************************************************/
+
+void gettexton(void)
+{
+#ifdef __GETTEXT__
+ setlocale(LC_ALL, "");
+ bindtextdomain("quota", "/usr/share/locale");
+ textdomain("quota");
+#endif
+}
diff --git a/pot.h b/pot.h
new file mode 100644
index 0000000..b50dc27
--- /dev/null
+++ b/pot.h
@@ -0,0 +1,24 @@
+#ifndef _POT_H
+#define _POT_H
+
+#define __GETTEXT__
+/***************************************************************************
+ * if you want to turn off gettext without changing sources
+ * undefine __GETTEXT__
+ ***************************************************************************/
+
+#ifdef __GETTEXT__
+
+#include <libintl.h>
+
+#define _(x) gettext((x))
+
+void gettexton(void);
+
+#else
+
+#define _(x) (x)
+
+#endif
+
+#endif
diff --git a/quot.8 b/quot.8
new file mode 100644
index 0000000..f72973d
--- /dev/null
+++ b/quot.8
@@ -0,0 +1,45 @@
+.TH QUOT 8
+.SH NAME
+quot \- summarize filesystem ownership
+.SH SYNOPSIS
+.nf
+\f3quot\f1 [ \f3\-acfv\f1 ] [ filesystem... ]
+.fi
+.SH DESCRIPTION
+.IR quot
+displays the number of kilobytes in the named
+.I filesystem
+currently owned by each user.
+.SH OPTIONS
+.TP
+.B \-a
+Generate a report for all mounted filesystems giving the number of
+kilobytes used by each user.
+.TP
+.B \-c
+Display three columns giving file size in kilobytes, number of
+files of that size, and cumulative total of kilobytes
+in that size or smaller file.
+The last row is used as an overflow
+bucket and is the total of all files greater than 500 kilobytes.
+.TP
+.B \-f
+Display count of kilobytes and number of files owned by each user.
+.TP
+.B \-v
+Display three columns containing the number of kilobytes not accessed in
+the last 30, 60, and 90 days.
+.SH FILES
+.PD 0
+.TP 20
+/etc/mtab
+mounted filesystems
+.TP
+/etc/passwd
+to get user names
+.PD
+.SH "SEE ALSO"
+du(1),
+ls(1).
+.SH BUGS
+Currently, only the XFS filesystem type is supported.
diff --git a/quot.c b/quot.c
new file mode 100644
index 0000000..162511d
--- /dev/null
+++ b/quot.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California.
+ * Copyright (C) 2000, 2001 Silicon Graphics, Inc. [SGI]
+ * All rights reserved.
+ *
+ * [Extensions to support XFS are copyright SGI]
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
+#ident "$Copyright: (c) 2000, 2001 Silicon Graphics, Inc. $"
+#ident "$Copyright: All rights reserved. $"
+
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <time.h>
+#include <utmp.h>
+#include <pwd.h>
+
+#include "pot.h"
+#include "quot.h"
+#include "common.h"
+#include "mntopt.h"
+#include "bylabel.h"
+
+#define TSIZE 500
+__uint64_t sizes[TSIZE];
+__uint64_t overflow;
+
+static int fflag;
+static int cflag;
+static int vflag;
+static int aflag;
+static char *progname;
+static time_t now;
+
+static void mounttable(char *);
+static char *username(uid_t);
+static void report(void);
+
+static void usage(void)
+{
+ fprintf(stderr, _("Usage: %s [-acfvV] [filesystem...]\n"), progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int c;
+
+ now = time(0);
+ progname = basename(argv[0]);
+
+ while ((c = getopt(argc, argv, "acfvV")) != EOF) {
+ switch (c) {
+ case 'a':
+ aflag++;
+ break;
+ case 'c':
+ cflag++;
+ break;
+ case 'f':
+ fflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'V':
+ version();
+ exit(0);
+ default:
+ usage();
+ }
+ }
+ if ((aflag && optind != argc) || (!aflag && optind == argc))
+ usage();
+ if (aflag)
+ mounttable(NULL);
+ else {
+ while (optind < argc)
+ mounttable(argv[optind++]);
+ }
+ return 0;
+}
+
+static void mounttable(char *entry)
+{
+ struct mntent *mntp;
+ const char *dev;
+ FILE *mtab;
+ int doit;
+
+ if ((mtab = setmntent(MOUNTED, "r")) == NULL) {
+ fprintf(stderr, _("%s: no " MOUNTED " file\n"), progname);
+ exit(1);
+ }
+ while ((mntp = getmntent(mtab)) != NULL) {
+ doit = 0;
+ dev = get_device_name(mntp->mnt_fsname);
+ if ((entry != NULL) &&
+ (strcmp(entry, mntp->mnt_dir) != 0) && (strcmp(entry, dev) != 0)) {
+ free((char *)dev);
+ continue;
+ }
+
+ /* Currently, only XFS is implemented... */
+ if (strcmp(mntp->mnt_type, MNTTYPE_XFS) == 0) {
+ checkXFS(dev, mntp->mnt_dir);
+ doit = 1;
+ }
+ /* ...additional filesystems types here. */
+ free((char *)dev);
+
+ if (doit)
+ report();
+ if (entry != NULL) {
+ entry = NULL; /* found, bail out */
+ break;
+ }
+ }
+ if (entry != NULL)
+ fprintf(stderr, _("%s: cannot locate block device for %s\n"), progname, entry);
+ endmntent(mtab);
+}
+
+static int qcmp(du_t * p1, du_t * p2)
+{
+ if (p1->blocks > p2->blocks)
+ return -1;
+ if (p1->blocks < p2->blocks)
+ return 1;
+ if (p1->uid > p2->uid)
+ return 1;
+ else if (p1->uid < p2->uid)
+ return -1;
+ return 0;
+}
+
+static void report(void)
+{
+ int i;
+ du_t *dp;
+
+ if (cflag) {
+ __uint64_t t = 0;
+
+ for (i = 0; i < TSIZE - 1; i++)
+ if (sizes[i] > 0) {
+ t += sizes[i] * i;
+ printf(_("%d\t%llu\t%llu\n"), i, sizes[i], t);
+ }
+ printf(_("%d\t%llu\t%llu\n"), TSIZE - 1, sizes[TSIZE - 1], overflow + t);
+ return;
+ }
+ qsort(du, ndu, sizeof(du[0]), (int (*)(const void *, const void *))qcmp);
+ for (dp = du; dp < &du[ndu]; dp++) {
+ char *cp;
+
+ if (dp->blocks == 0)
+ return;
+ printf(_("%8llu "), dp->blocks);
+ if (fflag)
+ printf(_("%8llu "), dp->nfiles);
+ if ((cp = username(dp->uid)) != NULL)
+ printf(_("%-8.8s"), cp);
+ else
+ printf(_("#%-7d"), dp->uid);
+ if (vflag)
+ printf(_(" %8llu %8llu %8llu"),
+ dp->blocks30, dp->blocks60, dp->blocks90);
+ putchar('\n');
+ }
+}
+
+static char *username(uid_t uid)
+{
+ register struct passwd *pw;
+ register uidcache_t *ncp;
+ static uidcache_t nc[NUID];
+ static int entriesleft = NUID;
+
+ /* check cache for name first */
+ ncp = &nc[uid & UIDMASK];
+ if (ncp->uid == uid && ncp->name[0])
+ return ncp->name;
+ if (entriesleft) {
+ /*
+ * If we haven't gone through the passwd file then
+ * fill the cache while seaching for name.
+ * This lets us run through passwd serially.
+ */
+ if (entriesleft == NUID)
+ setpwent();
+ while (((pw = getpwent()) != NULL) && entriesleft) {
+ entriesleft--;
+ ncp = &nc[pw->pw_uid & UIDMASK];
+ if (ncp->name[0] == '\0' || pw->pw_uid == uid) {
+ strncpy(ncp->name, pw->pw_name, UT_NAMESIZE);
+ ncp->uid = uid;
+ }
+ if (pw->pw_uid == uid)
+ return ncp->name;
+ }
+ endpwent();
+ entriesleft = 0;
+ ncp = &nc[uid & UIDMASK];
+ }
+
+ /* Not cached - do it the slow way & insert into cache */
+ if ((pw = getpwuid(uid)) == NULL)
+ return NULL;
+ strncpy(ncp->name, pw->pw_name, UT_NAMESIZE);
+ ncp->uid = uid;
+ return ncp->name;
+}
+
+/*
+ * === XFS specific code follows ===
+ */
+
+static void acctXFS(xfs_bstat_t * p)
+{
+ register du_t *dp;
+ du_t **hp;
+ __uint64_t size;
+
+ if ((p->bs_mode & S_IFMT) == 0)
+ return;
+ size = howmany((p->bs_blocks * p->bs_blksize), 0x400ULL);
+
+ if (cflag) {
+ if (!(S_ISDIR(p->bs_mode) || S_ISREG(p->bs_mode)))
+ return;
+ if (size >= TSIZE) {
+ overflow += size;
+ size = TSIZE - 1;
+ }
+ sizes[(int)size]++;
+ return;
+ }
+ hp = &duhash[p->bs_uid % DUHASH];
+ for (dp = *hp; dp; dp = dp->next)
+ if (dp->uid == p->bs_uid)
+ break;
+ if (dp == 0) {
+ if (ndu >= NDU)
+ return;
+ dp = &du[ndu++];
+ dp->next = *hp;
+ *hp = dp;
+ dp->uid = p->bs_uid;
+ dp->nfiles = 0;
+ dp->blocks = 0;
+ dp->blocks30 = 0;
+ dp->blocks60 = 0;
+ dp->blocks90 = 0;
+ }
+ dp->blocks += size;
+
+ if (now - p->bs_atime.tv_sec > 30 * SEC24HR)
+ dp->blocks30 += size;
+ if (now - p->bs_atime.tv_sec > 60 * SEC24HR)
+ dp->blocks60 += size;
+ if (now - p->bs_atime.tv_sec > 90 * SEC24HR)
+ dp->blocks90 += size;
+ dp->nfiles++;
+}
+
+static void checkXFS(const char *file, char *fsdir)
+{
+ xfs_fsop_bulkreq_t bulkreq;
+ __s64 last = 0;
+ __s32 count;
+ int i;
+ int sts;
+ int fsfd;
+ du_t **dp;
+ xfs_bstat_t *buf;
+
+ /*
+ * Initialize tables between checks; because of the qsort
+ * in report() the hash tables must be rebuilt each time.
+ */
+ for (sts = 0; sts < TSIZE; sts++)
+ sizes[sts] = 0;
+ overflow = 0;
+ for (dp = duhash; dp < &duhash[DUHASH]; dp++)
+ *dp = 0;
+ ndu = 0;
+
+ fsfd = open(fsdir, O_RDONLY);
+ if (fsfd < 0) {
+ fprintf(stderr, _("%s: cannot open %s: %s\n"), progname, fsdir, strerror(errno));
+ exit(1);
+ }
+ printf(_("%s (%s):\n"), file, fsdir);
+ sync();
+
+ buf = (xfs_bstat_t *) smalloc(NBSTAT * sizeof(xfs_bstat_t));
+ memset(buf, 0, NBSTAT * sizeof(xfs_bstat_t));
+
+ bulkreq.lastip = &last;
+ bulkreq.icount = NBSTAT;
+ bulkreq.ubuffer = buf;
+ bulkreq.ocount = &count;
+
+ while ((sts = ioctl(fsfd, XFS_IOC_FSBULKSTAT, &bulkreq)) == 0) {
+ if (count == 0)
+ break;
+ for (i = 0; i < count; i++)
+ acctXFS(&buf[i]);
+ }
+ if (sts < 0) {
+ fprintf(stderr, _("%s: XFS_IOC_FSBULKSTAT ioctl failed: %s\n"),
+ progname, strerror(errno));
+ exit(1);
+ }
+ free(buf);
+ close(fsfd);
+}
diff --git a/quot.h b/quot.h
new file mode 100644
index 0000000..2ba44fc
--- /dev/null
+++ b/quot.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California.
+ * Copyright (C) 2000, 2001 Silicon Graphics, Inc. [SGI]
+ * All rights reserved.
+ *
+ * [Extensions to support XFS are copyright SGI]
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define SEC24HR (60*60*24) /* seconds per day */
+
+typedef struct {
+ uid_t uid;
+ char name[UT_NAMESIZE + 1];
+} uidcache_t;
+
+typedef struct du {
+ struct du *next;
+ __uint64_t blocks;
+ __uint64_t blocks30;
+ __uint64_t blocks60;
+ __uint64_t blocks90;
+ __uint64_t nfiles;
+ uid_t uid;
+} du_t;
+
+#define NDU 60000
+#define DUHASH 8209
+static du_t du[NDU];
+static du_t *duhash[DUHASH];
+static int ndu;
+
+#define NUID 256
+#define UIDMASK (NUID-1)
+
+/*
+ * === Start XFS specific types and definitions ===
+ */
+#include <linux/types.h>
+
+/* Structures returned from ioctl XFS_IOC_FSBULKSTAT */
+typedef struct xfs_bstime {
+ time_t tv_sec; /* seconds */
+ __s32 tv_nsec; /* and nanoseconds */
+} xfs_bstime_t;
+
+typedef struct xfs_bstat {
+ __u64 bs_ino; /* inode number */
+ __u16 bs_mode; /* type and mode */
+ __u16 bs_nlink; /* number of links */
+ __u32 bs_uid; /* user id */
+ __u32 bs_gid; /* group id */
+ __u32 bs_rdev; /* device value */
+ __s32 bs_blksize; /* block size */
+ __s64 bs_size; /* file size */
+ xfs_bstime_t bs_atime; /* access time */
+ xfs_bstime_t bs_mtime; /* modify time */
+ xfs_bstime_t bs_ctime; /* inode change time */
+ int64_t bs_blocks; /* number of blocks */
+ __u32 bs_xflags; /* extended flags */
+ __s32 bs_extsize; /* extent size */
+ __s32 bs_extents; /* number of extents */
+ __u32 bs_gen; /* generation count */
+ __u16 bs_projid; /* project id */
+ unsigned char bs_pad[14]; /* pad space, unused */
+ __u32 bs_dmevmask; /* DMIG event mask */
+ __u16 bs_dmstate; /* DMIG state info */
+ __u16 bs_aextents; /* attribute number of extents */
+} xfs_bstat_t;
+
+/* The user-level BulkStat Request interface structure. */
+typedef struct xfs_fsop_bulkreq {
+ __u64 *lastip; /* last inode # pointer */
+ __s32 icount; /* count of entries in buffer */
+ void *ubuffer; /* user buffer for inode desc. */
+ __s32 *ocount; /* output count pointer */
+} xfs_fsop_bulkreq_t;
+
+#ifndef XFS_IOC_FSBULKSTAT
+#define XFS_IOC_FSBULKSTAT _IOWR('X', 101, struct xfs_fsop_bulkreq)
+#endif
+
+#define NBSTAT 4069 /* XFS bulkstat inodes */
+static void checkXFS(const char *file, char *fsdir);
+
+/*
+ * === End of XFS specific types and definitions ===
+ */
diff --git a/quota.1 b/quota.1
new file mode 100644
index 0000000..fec0b29
--- /dev/null
+++ b/quota.1
@@ -0,0 +1,100 @@
+.TH QUOTA 1
+.SH NAME
+quota \- display disk usage and limits
+.SH SYNOPSIS
+quota [
+.B -n
+] [
+.B -guv | q
+]
+.br
+quota [
+.B -n
+] [
+.B -uv | q
+] user
+.br
+quota [
+.B -n
+] [
+.B -gv | q
+] group
+.SH DESCRIPTION
+.B Quota
+displays users' disk usage and limits.
+By default only the user quotas are printed.
+.PP
+.B Quota
+reports the quotas of all the filesystems listed in
+.B /etc/mtab.
+For filesystems that are NFS-mounted a call to the rpc.rquotad on
+the server machine is performed to get the information.
+.SH OPTIONS
+.TP
+.B \-n
+Print info on numeric arguments e.g. uids and gids instead of users and groups
+.TP
+.B \-g
+Print group quotas for the group
+of which the user is a member.
+The optional
+.TP
+.B \-u
+flag is equivalent to the default.
+.TP
+.B \-v
+will display quotas on filesystems
+where no storage is allocated.
+.TP
+.B -q
+Print a more terse message,
+containing only information
+on filesystems where usage is over quota.
+.LP
+Specifying both
+.B \-g
+and
+.B \-u
+displays both the user quotas and the group quotas (for
+the user).
+.LP
+Only the super-user may use the
+.B \-u
+flag and the optional
+.B user
+argument to view the limits of other users.
+Non-super-users can use the the
+.B \-g
+flag and optional
+.B group
+argument to view only the limits of groups of which they are members.
+.LP
+The
+.B \-q
+flag takes precedence over the
+.B \-v
+flag.
+.SH DIAGNOSTICS
+If
+.B quota
+exits with a non-zero status, one or more filesystems
+are over quota.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP 20
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+default filesystems
+.PD
+.SH SEE ALSO
+.BR quotactl (2),
+.BR fstab (5),
+.BR edquota (8),
+.BR quotacheck (8),
+.BR quotaon (8),
+.BR repquota (8)
diff --git a/quota.c b/quota.c
new file mode 100644
index 0000000..0bb7def
--- /dev/null
+++ b/quota.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California. All
+ * rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Robert Elz at
+ * The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
+#ident "$Copyright: All rights reserved. $"
+#ident "$Id: quota.c,v 1.1 2001/03/23 12:03:26 jkar8572 Exp $"
+
+/*
+ * Disk quota reporting program.
+ */
+#include <sys/types.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef RPC
+#include <rpc/rpc.h>
+#include "rquota.h"
+#endif
+
+#include "quota.h"
+#include "quotaops.h"
+#include "quotasys.h"
+#include "pot.h"
+#include "common.h"
+
+int qflag, vflag, fmt = -1;
+
+void usage(void);
+void showquotas(int type, qid_t id);
+void heading(int type, qid_t id, char *name, char *tag);
+
+int main(int argc, char **argv)
+{
+ int ngroups;
+ gid_t gidset[NGROUPS];
+ int i, ret, gflag = 0, uflag = 0;
+
+ gettexton();
+
+ while ((ret = getopt(argc, argv, "guqvVF:")) != EOF) {
+ switch (ret) {
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'q':
+ qflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'F':
+ if ((fmt = name2fmt(optarg)) == QF_ERROR) /* Error? */
+ exit(1);
+ break;
+ case 'V':
+ version();
+ exit(0);
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ warn_new_kernel(fmt);
+ if (!uflag && !gflag)
+ uflag++;
+
+ if (argc == 0) {
+ if (uflag)
+ showquotas(USRQUOTA, getuid());
+ if (gflag) {
+ ngroups = getgroups(NGROUPS, gidset);
+ if (ngroups < 0)
+ die(1, "quota: getgroups(): %s\n", strerror(errno));
+ for (i = 0; i < ngroups; i++)
+ showquotas(GRPQUOTA, gidset[i]);
+ }
+ exit(0);
+ }
+
+ if (uflag && gflag)
+ usage();
+
+ if (uflag)
+ for (; argc > 0; argc--, argv++)
+ showquotas(USRQUOTA, user2uid(*argv));
+ else if (gflag)
+ for (; argc > 0; argc--, argv++)
+ showquotas(GRPQUOTA, group2gid(*argv));
+ return 0;
+}
+
+void usage(void)
+{
+ fprintf(stderr, "%s\n%s\n%s\n",
+ _("Usage: quota [-guqvV] [-F quotaformat]"),
+ _("\tquota [-qv] [-F quotaformat] -u username ..."),
+ _("\tquota [-qv] [-F quotaformat] -g groupname ..."));
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
+ exit(1);
+}
+
+void showquotas(int type, qid_t id)
+{
+ struct dquot *qlist, *q;
+ char *msgi, *msgb;
+ char timebuf[MAXTIMELEN];
+ char name[MAXNAMELEN];
+ struct quota_handle **handles;
+ int lines = 0;
+ time_t now;
+
+ time(&now);
+ id2name(id, type, name);
+ handles = create_handle_list(0, NULL, type, fmt, 0);
+ qlist = getprivs(id, handles);
+ for (q = qlist; q; q = q->dq_next) {
+ if (!vflag && !q->dq_dqb.dqb_isoftlimit && !q->dq_dqb.dqb_ihardlimit
+ && !q->dq_dqb.dqb_bsoftlimit && !q->dq_dqb.dqb_bhardlimit)
+ continue;
+ msgi = NULL;
+ if (q->dq_dqb.dqb_ihardlimit && q->dq_dqb.dqb_curinodes >= q->dq_dqb.dqb_ihardlimit)
+ msgi = _("File limit reached on");
+ else if (q->dq_dqb.dqb_isoftlimit
+ && q->dq_dqb.dqb_curinodes >= q->dq_dqb.dqb_isoftlimit) {
+ if (q->dq_dqb.dqb_itime > now)
+ msgi = _("In file grace period on");
+ else
+ msgi = _("Over file quota on");
+ }
+ msgb = NULL;
+ if (q->dq_dqb.dqb_bhardlimit
+ && toqb(q->dq_dqb.dqb_curspace) >= q->dq_dqb.dqb_bhardlimit)
+ msgb = _("Block limit reached on");
+ else if (q->dq_dqb.dqb_bsoftlimit
+ && toqb(q->dq_dqb.dqb_curspace) >= q->dq_dqb.dqb_bsoftlimit) {
+ if (q->dq_dqb.dqb_btime > now)
+ msgb = _("In block grace period on");
+ else
+ msgb = _("Over block quota on");
+ }
+ if (qflag) {
+ if ((msgi || msgb) && !lines++)
+ heading(type, id, name, "");
+ if (msgi)
+ printf("\t%s %s\n", msgi, q->dq_h->qh_quotadev);
+ if (msgb)
+ printf("\t%s %s\n", msgb, q->dq_h->qh_quotadev);
+ continue;
+ }
+ if (vflag || q->dq_dqb.dqb_curspace || q->dq_dqb.dqb_curinodes) {
+ if (!lines++)
+ heading(type, id, name, "");
+ if (strlen(q->dq_h->qh_quotadev) > 15)
+ printf("%s\n%15s", q->dq_h->qh_quotadev, "");
+ else
+ printf("%15s", q->dq_h->qh_quotadev);
+ if (msgb)
+ difftime2str(q->dq_dqb.dqb_btime, timebuf);
+ printf("%8Lu%c%7Lu%8Lu%8s", (long long)toqb(q->dq_dqb.dqb_curspace),
+ msgb ? '*' : ' ', (long long)q->dq_dqb.dqb_bsoftlimit,
+ (long long)q->dq_dqb.dqb_bhardlimit, msgb ? timebuf : "");
+ if (msgi)
+ difftime2str(q->dq_dqb.dqb_itime, timebuf);
+ printf("%8Lu%c%7Lu%8Lu%8s\n", (long long)q->dq_dqb.dqb_curinodes,
+ msgi ? '*' : ' ', (long long)q->dq_dqb.dqb_isoftlimit,
+ (long long)q->dq_dqb.dqb_ihardlimit, msgi ? timebuf : "");
+ continue;
+ }
+ }
+ if (!qflag && !lines)
+ heading(type, id, name, _("none"));
+ freeprivs(qlist);
+ dispose_handle_list(handles);
+}
+
+void heading(int type, qid_t id, char *name, char *tag)
+{
+ printf(_("Disk quotas for %s %s (%cid %d): %s\n"), type2name(type),
+ name, *type2name(type), id, tag);
+ if (!qflag && !tag[0]) {
+ printf("%15s%8s %7s%8s%8s%8s %7s%8s%8s\n", _("Filesystem"),
+ _("blocks"), _("quota"), _("limit"), _("grace"),
+ _("files"), _("quota"), _("limit"), _("grace"));
+ }
+}
diff --git a/quota.h b/quota.h
new file mode 100644
index 0000000..8e56826
--- /dev/null
+++ b/quota.h
@@ -0,0 +1,83 @@
+#ifndef _QUOTA_H
+#define _QUOTA_H
+
+#include <sys/types.h>
+
+typedef u_int32_t qid_t; /* Type in which we store ids in memory */
+typedef u_int64_t qsize_t; /* Type in which we store size limitations */
+
+#define MAXQUOTAS 2
+#define USRQUOTA 0 /* element used for user quotas */
+#define GRPQUOTA 1 /* element used for group quotas */
+
+/*
+ * Definitions for the default names of the quotas files.
+ */
+#define INITQFNAMES { \
+ "user", /* USRQUOTA */ \
+ "group", /* GRPQUOTA */ \
+ "undefined", \
+}
+
+/*
+ * Definitions of magics and versions of current quota files
+ */
+#define INITQMAGICS {\
+ 0xd9c01f11, /* USRQUOTA */\
+ 0xd9c01927 /* GRPQUOTA */\
+}
+
+/* Size of blocks in which are counted size limits in generic utility parts */
+#define QUOTABLOCK_BITS 10
+#define QUOTABLOCK_SIZE (1 << QUOTABLOCK_BITS)
+
+/* Conversion routines from and to quota blocks */
+#define qb2kb(x) ((x) << (QUOTABLOCK_BITS-10))
+#define kb2qb(x) ((x) >> (QUOTABLOCK_BITS-10))
+#define toqb(x) (((x) + QUOTABLOCK_SIZE - 1) >> QUOTABLOCK_BITS)
+
+/*
+ * Command definitions for the 'quotactl' system call.
+ * The commands are broken into a main command defined below
+ * and a subcommand that is used to convey the type of
+ * quota that is being manipulated (see above).
+ */
+#define SUBCMDMASK 0x00ff
+#define SUBCMDSHIFT 8
+#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
+
+#define Q_QUOTAON 0x0100 /* enable quotas */
+#define Q_QUOTAOFF 0x0200 /* disable quotas */
+#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
+#define Q_GETSTATS 0x1100 /* get collected stats */
+
+struct dqstats {
+ u_int32_t lookups;
+ u_int32_t drops;
+ u_int32_t reads;
+ u_int32_t writes;
+ u_int32_t cache_hits;
+ u_int32_t allocated_dquots;
+ u_int32_t free_dquots;
+ u_int32_t syncs;
+ u_int32_t version;
+};
+
+/* Ioctl for getting quota size */
+#include <sys/ioctl.h>
+#ifndef FIOQSIZE
+ #if defined(__alpha__) || defined(__powerpc__) || defined(__sh__) || defined(__sparc__) || defined(__sparc64__)
+ #define FIOQSIZE _IOR('f', 128, loff_t)
+ #elif defined(__arm__) || defined(__mc68000__) || defined(__s390__)
+ #define FIOQSIZE 0x545E
+ #elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__ia64__)
+ #define FIOQSIZE 0x5460
+ #elif defined(__mips__) || defined(__mips64__)
+ #define FIOQSIZE 0x6667
+ #endif
+#endif
+
+
+long quotactl __P((int, const char *, qid_t, caddr_t));
+
+#endif /* _QUOTA_ */
diff --git a/quotacheck.8 b/quotacheck.8
new file mode 100644
index 0000000..7270040
--- /dev/null
+++ b/quotacheck.8
@@ -0,0 +1,94 @@
+.TH QUOTACHECK 8
+.SH NAME
+quotacheck \- scan a filesystem for disk usages
+.SH SYNOPSIS
+.B quotacheck
+[-g] [-u] [-v] -a
+.br
+.B quotacheck
+[-g] [-u] [-v] filesys ...
+.SH DESCRIPTION
+.I Quotacheck
+performs a filesystems scan for usage of files and directories, used
+by either user or group.
+XFS filesystems are ignored by
+.IR quotacheck ,
+since the XFS quota system is journaled and therefore inherently consistent.
+.PP
+The output is the quota file for the corresponding filesystem.
+By default the names for these files are:
+.br
+\- A user scan:
+.I quota.user
+.br
+\- A group scan:
+.I quota.group
+.PP
+The resulting file consists of a
+.I struct dqblk
+for each possible id up to the highest existing uid or gid and contains the
+values for the disk file and block usage and possibly excess time for these
+values. ( for definitions of
+.I struct dqblk
+see
+.I \<linux/quota.h\>
+)
+.PP
+.I Quotacheck
+should be run each time the system boots and mounts non-valid filesystems.
+This is most likely to happen after a system crash.
+.PP
+The speed of the scan decreases with the number of directories increasing.
+The time needed doubles when disk usage is doubled as well. A 100 MB partition
+used for 94% is scanned in 1 minute, the same partition used for 50% is
+done in 25 seconds.
+.SH OPTIONS
+.TP
+.B \-v
+This way the program will give some useful information about what it is
+doing, plus some fancy stuff.
+.TP
+.B \-d
+This means debug. It will result in a lot of information which can be used
+in debugging the program. The output is very verbose and the scan
+will not be fast.
+.TP
+.B \-u
+This flag tells the program to scan the disk and to count the files and
+directories used by a certain uid. This is the default action.
+.TP
+.B \-g
+This flag forces the program to count the files and directories
+used by a certain gid.
+.TP
+.B \-a
+Check all of the quotas for the filesystems mentioned in /etc/mtab. Both
+user and group quotas are checked as indicated by the /etc/mtab options.
+.TP
+.B \-R
+When used in conjunction with \fP\-a\fR, all filesystems except the root
+filesystem are checked for quotas.
+.SH NOTE
+.I Quotacheck
+should only be run as Super User. Non-privilidged users are presumably not allowed
+to read all the directories on the given filesystem.
+.SH "SEE ALSO"
+quota(1), quotactl(2), fstab(5), quotaon(8), quotaoff(8), edquota(8),
+repquota(8), fsck(8)
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP 20
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+default filesystems
+.PD
+.SH "AUTHOR"
+Edvard Tuinder \<ed@elm.net\>
+.br
+Marco van Wieringen \<mvw@planets.elm.net\>
+
diff --git a/quotacheck.c b/quotacheck.c
new file mode 100644
index 0000000..5ed85bd
--- /dev/null
+++ b/quotacheck.c
@@ -0,0 +1,849 @@
+/*
+ *
+ * Utility to check disk quotas
+ *
+ * Some parts of this utility are copied from old quotacheck by
+ * Marco van Wieringen <mvw@planets.elm.net> and Edvard Tuinder <ed@elm.ent>
+ *
+ */
+
+#ident "$Id: quotacheck.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $"
+
+#include <dirent.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <getopt.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/statfs.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+
+#if defined(EXT2_DIRECT)
+#include <linux/ext2_fs.h>
+#include <ext2fs/ext2fs.h>
+#endif
+
+#include "pot.h"
+#include "common.h"
+#include "quotaio.h"
+#include "quotasys.h"
+#include "mntopt.h"
+#include "bylabel.h"
+#include "quotacheck.h"
+
+#define LINKSHASHSIZE 16384 /* Size of hashtable for hardlinked inodes */
+#define DQUOTHASHSIZE 32768 /* Size of hashtable for dquots from file */
+
+struct dlinks {
+ ino_t i_num;
+ struct dlinks *next;
+};
+
+struct dirs {
+ char *dir_name;
+ struct dirs *next;
+};
+
+#define BITS_SIZE 4 /* sizeof(bits) == 5 */
+
+dev_t cur_dev; /* Device we are working on */
+int files_done, dirs_done;
+int flags, fmt = -1; /* Options from command line; Quota format to use */
+int uwant, gwant, ucheck, gcheck; /* Does user want to check user/group quota; Do we check user/group quota? */
+char *mntpoint; /* Mountpoint to check */
+struct util_dqinfo old_info[MAXQUOTAS]; /* Loaded infos */
+
+#ifdef DEBUG_MALLOC
+size_t malloc_mem = 0;
+size_t free_mem = 0;
+#endif
+
+struct dquot *dquot_hash[MAXQUOTAS][DQUOTHASHSIZE];
+struct dlinks *links_hash[MAXQUOTAS][DQUOTHASHSIZE];
+
+/*
+ * Ok check each memory allocation.
+ */
+void *xmalloc(size_t size)
+{
+ void *ptr;
+
+#ifdef DEBUG_MALLOC
+ malloc_mem += size;
+#endif
+ ptr = malloc(size);
+ if (!ptr)
+ die(3, "Not enough memory.\n");
+ memset(ptr, 0, size);
+ return (ptr);
+}
+
+void debug(int df, char *fmtstr, ...)
+{
+ va_list args;
+
+ if (!(flags & df))
+ return;
+ va_start(args, fmtstr);
+ vfprintf(stderr, fmtstr, args);
+ va_end(args);
+}
+
+/* Compute hashvalue for given inode number */
+static inline uint hash_ino(uint i_num)
+{
+ return ((i_num ^ (i_num << 16)) * 997) & (LINKSHASHSIZE - 1);
+}
+
+/*
+ * Store a hardlinked inode as we don't want to count it more then once.
+ */
+static int store_dlinks(int type, ino_t i_num)
+{
+ struct dlinks *lptr;
+ uint hash = hash_ino(i_num);
+
+ debug(FL_DEBUG, "Adding hardlink for ino %d\n", i_num);
+
+ for (lptr = links_hash[type][hash]; lptr; lptr = lptr->next)
+ if (lptr->i_num == i_num)
+ return 1;
+
+ lptr = (struct dlinks *)xmalloc(sizeof(struct dlinks));
+
+ lptr->i_num = i_num;
+ lptr->next = links_hash[type][hash];
+ links_hash[type][hash] = lptr;
+ return 0;
+}
+
+/* Hash given id */
+static inline uint hash_dquot(uint id)
+{
+ return ((id ^ (id << 16)) * 997) & (DQUOTHASHSIZE - 1);
+}
+
+/*
+ * Do a lookup of a type of quota for a specific id. Use short cut with
+ * most recently used dquot struct pointer.
+ */
+struct dquot *lookup_dquot(qid_t id, int type)
+{
+ struct dquot *lptr;
+ uint hash = hash_dquot(id);
+
+ for (lptr = dquot_hash[type][hash]; lptr != NODQUOT; lptr = lptr->dq_next)
+ if (lptr->dq_id == id)
+ return lptr;
+ return NODQUOT;
+}
+
+/*
+ * Add a new dquot for a new id to the list.
+ */
+struct dquot *add_dquot(qid_t id, int type)
+{
+ struct dquot *lptr;
+ uint hash = hash_dquot(id);
+
+ debug(FL_DEBUG, "Adding dquot structure type %s for %d\n", type2name(type), (int)id);
+
+ lptr = (struct dquot *)xmalloc(sizeof(struct dquot));
+
+ lptr->dq_id = id;
+ lptr->dq_next = dquot_hash[type][hash];
+ dquot_hash[type][hash] = lptr;
+ lptr->dq_dqb.dqb_btime = lptr->dq_dqb.dqb_itime = (time_t) 0;
+
+ return lptr;
+}
+
+/*
+ * Add a number of blocks and inodes to a quota.
+ */
+static void add_to_quota(int type, ino_t i_num, uid_t i_uid, gid_t i_gid, umode_t i_mode,
+ nlink_t i_nlink, loff_t i_space)
+{
+ qid_t wanted;
+ struct dquot *lptr;
+
+ if (type == USRQUOTA)
+ wanted = i_uid;
+ else
+ wanted = i_gid;
+
+ if ((lptr = lookup_dquot(wanted, type)) == NODQUOT)
+ lptr = add_dquot(wanted, type);
+
+ if (i_nlink != 1)
+ if (store_dlinks(type, i_num)) /* Did we already count this inode? */
+ return;
+ lptr->dq_dqb.dqb_curinodes++;
+ lptr->dq_dqb.dqb_curspace += i_space;
+}
+
+/*
+ * Clean up all list from a previous run.
+ */
+static void remove_list(void)
+{
+ int cnt;
+ uint i;
+ struct dquot *dquot, *dquot_free;
+ struct dlinks *dlink, *dlink_free;
+
+ for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
+ for (i = 0; i < DQUOTHASHSIZE; i++) {
+ dquot = dquot_hash[cnt][i];
+ while (dquot != NODQUOT) {
+ dquot_free = dquot;
+ dquot = dquot->dq_next;
+#ifdef DEBUG_MALLOC
+ free_mem += sizeof(struct dquot);
+#endif
+ free(dquot_free);
+ }
+ dquot_hash[cnt][i] = NODQUOT;
+ }
+ for (i = 0; i < LINKSHASHSIZE; i++) {
+ dlink = links_hash[cnt][i];
+ while (dlink) {
+ dlink_free = dlink;
+ dlink = dlink->next;
+#ifdef DEBUG_MALLOC
+ free_mem += sizeof(struct dlinks);
+#endif
+ free(dlink_free);
+ }
+ links_hash[cnt][i] = NULL;
+ }
+ }
+}
+
+/* Get size used by file */
+static loff_t getqsize(char *fname, struct stat *st)
+{
+ static char ioctl_fail_warn;
+ int fd;
+ loff_t size;
+
+ if (S_ISLNK(st->st_mode)) /* There's no way to do ioctl() on links... */
+ return st->st_blocks << 9;
+ if ((fd = open(fname, O_RDONLY)) == -1)
+ die(2, _("Can't open file %s: %s\n"), fname, strerror(errno));
+ if (ioctl(fd, FIOQSIZE, &size) == -1) {
+ size = st->st_blocks << 9;
+ if (!ioctl_fail_warn) {
+ ioctl_fail_warn = 1;
+ fputs(_("Can't get exact used space... Results might be inaccurate.\n"),
+ stderr);
+ }
+ }
+ close(fd);
+ return size;
+}
+
+/*
+ * Show a blitting cursor as means of visual progress indicator.
+ */
+static inline void blit(void)
+{
+ static short bitc = 0;
+ static const char bits[] = "|/-\\";
+
+ putc(bits[bitc], stdout);
+ putc('\b', stdout);
+ fflush(stdout);
+ bitc++;
+ bitc %= BITS_SIZE;
+}
+
+static void parse_options(int argcnt, char **argstr)
+{
+ int ret;
+ char *slash = strrchr(argstr[0], '/');
+
+ if (slash)
+ slash++;
+ else
+ slash = argstr[0];
+
+ while ((ret = getopt(argcnt, argstr, "VhcvugidnfF:mMRa")) != EOF) {
+ switch (ret) {
+ case 'g':
+ gwant = 1;
+ break;
+ case 'u':
+ uwant = 1;
+ break;
+ case 'd':
+ flags |= FL_DEBUG;
+ setlinebuf(stderr);
+ break;
+ case 'v':
+ flags |= FL_VERBOSE;
+ break;
+ case 'f':
+ flags |= FL_FORCE;
+ break;
+ case 'i':
+ flags |= FL_INTERACTIVE;
+ break;
+ case 'n':
+ flags |= FL_GUESSDQ;
+ break;
+ case 'c':
+ flags |= FL_NEWFILE;
+ break;
+ case 'V':
+ version();
+ exit(0);
+ case 'M':
+ flags |= FL_FORCEREMOUNT;
+ break;
+ case 'm':
+ flags |= FL_NOREMOUNT;
+ break;
+ case 'a':
+ flags |= FL_ALL;
+ break;
+ case 'R':
+ flags |= FL_NOROOT;
+ break;
+ case 'F':
+ if ((fmt = name2fmt(optarg)) == QF_ERROR)
+ exit(1);
+ break;
+ default:
+ usage:
+ printf(_
+ ("Utility for checking and repairing quota files.\n%s [-gucfinvdmMR] -F <quota-format> filesystem|-a\n"),
+slash);
+ printf(_("Bugs to %s\n"), MY_EMAIL);
+ exit(1);
+ }
+ }
+ if (!(uwant | gwant))
+ uwant = 1;
+ if (argcnt == optind) {
+ fputs(_("Bad number of arguments.\n"), stderr);
+ goto usage;
+ }
+ if (fmt == -1) {
+ fputs(_("Quota format must be specified for scanning.\n"), stderr);
+ goto usage;
+ }
+ if (fmt == QF_XFS) {
+ fputs(_("XFS quota format needs no checking.\n"), stderr);
+ exit(0);
+ }
+ if (flags & FL_VERBOSE && flags & FL_DEBUG)
+ flags &= ~FL_VERBOSE;
+ if (!(flags & FL_ALL))
+ mntpoint = argstr[optind];
+ else
+ mntpoint = NULL;
+}
+
+#if defined(EXT2_DIRECT)
+static int ext2_direct_scan(char *device)
+{
+ ino_t i_num;
+ ext2_filsys fs;
+ errcode_t error;
+ ext2_inode_scan scan;
+ struct ext2_inode inode;
+ int inode_buffer_blocks = 0;
+ ext2fs_inode_bitmap inode_used_map;
+ ext2fs_inode_bitmap inode_dir_map;
+
+ if ((error = ext2fs_open(device, 0, 0, 0, unix_io_manager, &fs))) {
+ fprintf(stderr, _("quotacheck: error (%d) while opening %s\n"), (int)error, device);
+ return -1;
+ }
+
+ if ((error = ext2fs_allocate_inode_bitmap(fs, "in-use inode map", &inode_used_map))) {
+ fprintf(stderr, _("quotacheck: error (%d) while allocating inode file bitmap\n"),
+ (int)error);
+ return -1;
+ }
+
+ if ((error = ext2fs_allocate_inode_bitmap(fs, "directory inode map", &inode_dir_map))) {
+ fprintf(stderr,
+ _("quotacheck: error (%d) while allocating inode directory bitmap\n"),
+ (int)error);
+ return -1;
+ }
+
+ if ((error = ext2fs_open_inode_scan(fs, inode_buffer_blocks, &scan))) {
+ fprintf(stderr, _("quotacheck: error (%d) while opening inode scan\n"), (int)error);
+ return -1;
+ }
+
+ if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) {
+ fprintf(stderr, _("quotacheck: error (%d) while starting inode scan\n"), (int)error);
+ return -1;
+ }
+
+ while (i_num) {
+ if (inode.i_links_count) {
+ debug(FL_DEBUG, _("Found i_num %ld\n"), i_num);
+ if (flags & FL_VERBOSE)
+ blit();
+ if (ucheck)
+ add_to_quota(USRQUOTA, i_num, inode.i_uid, inode.i_gid,
+ inode.i_mode, inode.i_links_count,
+ inode.i_blocks << 9);
+ if (gcheck)
+ add_to_quota(GRPQUOTA, i_num, inode.i_uid, inode.i_gid,
+ inode.i_mode, inode.i_links_count,
+ inode.i_blocks << 9);
+ if (S_ISDIR(inode.i_mode))
+ dirs_done++;
+ else
+ files_done++;
+ }
+
+ if ((error = ext2fs_get_next_inode(scan, &i_num, &inode))) {
+ fprintf(stderr, _("Something weird happened while scanning. Error %d\n"),
+ (int)error);
+ return -1;
+ }
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Scan a directory with the readdir systemcall. Stat the files and add the sizes
+ * of the files to the appropriate quotas. When we find a dir we recursivly call
+ * ourself to scan that dir.
+ */
+static int scan_dir(char *pathname)
+{
+ struct dirs *dir_stack = { (struct dirs *)NULL };
+ struct dirs *new_dir;
+ struct dirent *de;
+ struct stat st;
+ loff_t qspace;
+ DIR *dp;
+ int ret;
+
+ if ((dp = opendir(pathname)) == (DIR *) NULL)
+ die(2, "\nCan open directory %s: %s\n", pathname, strerror(errno));
+
+ chdir(pathname);
+ while ((de = readdir(dp)) != (struct dirent *)NULL) {
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+ continue;
+ if (flags & FL_VERBOSE)
+ blit();
+
+ if ((lstat(de->d_name, &st)) == -1) {
+ fprintf(stderr,
+ _
+ ("lstat can't stat `%s/%s': %s\nGuess you'd better run fsck first !\nexiting...\n"),
+ pathname, de->d_name, strerror(errno));
+ goto out;
+ }
+
+ qspace = getqsize(de->d_name, &st);
+ if (ucheck)
+ add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+ st.st_nlink, qspace);
+ if (gcheck)
+ add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+ st.st_nlink, qspace);
+
+ if (S_ISDIR(st.st_mode)) {
+ if (st.st_dev != cur_dev)
+ continue;
+ /*
+ * Add this to the directory stack and check this later on.
+ */
+ debug(FL_DEBUG, _("pushd %s/%s\n"), pathname, de->d_name);
+ new_dir = xmalloc(sizeof(struct dirs));
+
+ new_dir->dir_name = xmalloc(strlen(pathname) + strlen(de->d_name) + 2);
+ sprintf(new_dir->dir_name, "%s/%s", pathname, de->d_name);
+ new_dir->next = dir_stack;
+ dir_stack = new_dir;
+ }
+ else {
+ debug(FL_DEBUG, _("\tAdding %s size %d ino %d links %d\n"), de->d_name,
+ st.st_size, st.st_ino, st.st_nlink);
+ files_done++;
+ }
+ }
+ closedir(dp);
+
+ /*
+ * Traverse the directory stack, and check it.
+ */
+ debug(FL_DEBUG, "Scanning stored directories from directory stack\n");
+ while (dir_stack != (struct dirs *)NULL) {
+ new_dir = dir_stack;
+ dir_stack = dir_stack->next;
+ debug(FL_DEBUG, _("popd %s\nEntering directory %s\n"), new_dir->dir_name,
+ new_dir->dir_name);
+ ret = scan_dir(new_dir->dir_name);
+ dirs_done++;
+#ifdef DEBUG_MALLOC
+ free_mem += sizeof(struct dirs) + strlen(new_dir->dir_name) + 1;
+#endif
+ free(new_dir->dir_name);
+ free(new_dir);
+ if (ret < 0) /* Error while scanning? */
+ goto out;
+ }
+ debug(FL_DEBUG, _("Leaving %s\n"), pathname);
+ return 0;
+ out:
+ for (new_dir = dir_stack; new_dir; new_dir = dir_stack) {
+ dir_stack = dir_stack->next;
+#ifdef DEBUG_MALLOC
+ free_mem += sizeof(struct dirs) + strlen(new_dir->dir_name) + 1;
+#endif
+ free(new_dir->dir_name);
+ free(new_dir);
+ }
+ return -1;
+}
+
+/* Ask user y/n question */
+int ask_yn(char *q, int def)
+{
+ char a[10]; /* Users answer */
+
+ printf("%s [%c]: ", q, def ? 'y' : 'n');
+ fflush(stdout);
+ while (1) {
+ fgets(a, sizeof(a), stdin);
+ if (*a == '\n')
+ return def;
+ if (!strcasecmp(a, "y\n"))
+ return 1;
+ if (!strcasecmp(a, "n\n"))
+ return 0;
+ printf("Illegal answer. Please answer y/n: ");
+ fflush(stdout);
+ }
+}
+
+/* Do checks and buffer quota file into memory */
+static int process_file(char *mnt_fsname, struct mntent *mnt, int type)
+{
+ char *qfname;
+ int fd, ret;
+
+ debug(FL_DEBUG | FL_VERBOSE, _("Going to check %s quota file of %s\n"), type2name(type),
+ mnt->mnt_dir);
+
+ if (kern_quota_on(mnt_fsname, type, (1 << fmt)) > 0) { /* Is quota enabled? */
+ if (!(flags & FL_FORCE)) {
+ if (flags & FL_INTERACTIVE) {
+ printf(_
+ ("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n"),
+type2name(type), mnt->mnt_dir);
+ if (!ask_yn(_("Should I continue"), 0)) {
+ printf(_("As you wish... Canceling check of this file.\n"));
+ return -1;
+ }
+ }
+ else
+ die(6,
+ _
+ ("Quota for %ss is enabled on mountpoint %s so quotacheck might damage the file.\n\
+Please turn quotas off or use -f to force checking.\n"),
+ type2name(type), mnt->mnt_dir);
+ }
+ /* At least sync quotas so damage will be smaller */
+ if (quotactl(QCMD(Q_SYNC, type), mnt_fsname, 0, NULL) < 0)
+ die(4, _("Error while syncing quotas: %s\n"), strerror(errno));
+ }
+
+ qfname = get_qf_name(mnt, type, fmt);
+ if (!qfname) {
+ fprintf(stderr, _("Can't get quotafile name for %s\n"), mnt_fsname);
+ return -1;
+ }
+ if ((fd = open(qfname, O_RDONLY)) < 0) {
+ fprintf(stderr, _("Can't open quotafile %s: %s\n"), qfname, strerror(errno));
+ free(qfname);
+ return -1;
+ }
+
+ memset(old_info + type, 0, sizeof(old_info[type]));
+ ret = 0;
+ switch (fmt) {
+ case QF_TOONEW:
+ fprintf(stderr, _("Too new quotafile format on %s\n"), mnt_fsname);
+ ret = -1;
+ break;
+ case QF_VFSOLD:
+ ret = v1_buffer_file(qfname, fd, type);
+ break;
+ case QF_VFSV0:
+ ret = v2_buffer_file(qfname, fd, type);
+ break;
+ }
+ free(qfname);
+ close(fd);
+ return ret;
+}
+
+/* Backup old quotafile and rename new one to right name */
+static int rename_files(struct mntent *mnt, int type)
+{
+ char *filename, newfilename[PATH_MAX];
+ struct stat st;
+
+ if (!(filename = get_qf_name(mnt, type, fmt)))
+ die(2, _("Can't get name of old quotafile on %s.\n"), mnt->mnt_dir);
+ debug(FL_DEBUG | FL_VERBOSE, _("Data dumped.\nRenaming old quotafile to %s~\n"), filename);
+ if (stat(filename, &st) < 0) { /* File doesn't exist? */
+ if (errno == ENOENT) {
+ debug(FL_DEBUG | FL_VERBOSE, _("Old file not found.\n"));
+ goto rename_new;
+ }
+ fprintf(stderr, _("Error while searching for old quota file %s: %s\n"), filename,
+ strerror(errno));
+ free(filename);
+ return -1;
+ }
+ /* Backup old file */
+ strcpy(newfilename, filename);
+ /* Make backingup safe */
+ sstrncat(newfilename, "~", PATH_MAX);
+ if (newfilename[strlen(newfilename) - 1] != '~')
+ die(8, _("Name of quota file too long. Contact %s.\n"), MY_EMAIL);
+ if (rename(filename, newfilename) < 0) {
+ fprintf(stderr, _("Can't rename old quotafile %s to %s: %s\n"), filename,
+ newfilename, strerror(errno));
+ free(filename);
+ return -1;
+ }
+ debug(FL_DEBUG | FL_VERBOSE, _("Renaming new quotafile\n"));
+ rename_new:
+ /* Rename new file to right name */
+ strcpy(newfilename, filename);
+ sstrncat(newfilename, ".new", PATH_MAX);
+ if (rename(newfilename, filename) < 0) {
+ fprintf(stderr, _("Can't rename new quotafile %s to name %s: %s\n"), newfilename,
+ filename, strerror(errno));
+ free(filename);
+ return -1;
+ }
+ free(filename);
+ return 0;
+}
+
+/*
+ * Dump the quota info that we have in memory now to the appropriate
+ * quota file. As quotafiles doesn't account to quotas we don't have to
+ * bother about accounting new blocks for quota file
+ */
+static int dump_to_file(char *mnt_fsname, struct mntent *mnt, int type)
+{
+ struct dquot *dquot;
+ uint i;
+ struct quota_handle *h;
+
+ debug(FL_DEBUG | FL_VERBOSE, _("Dumping gathered data for %ss.\n"), type2name(type));
+ if (!(h = new_io(mnt, type, fmt))) {
+ fprintf(stderr, _("Can't initialize IO on new quotafile: %s\n"), strerror(errno));
+ return -1;
+ }
+ memcpy(&h->qh_info, old_info + type, sizeof(h->qh_info));
+ mark_quotafile_info_dirty(h);
+ for (i = 0; i < DQUOTHASHSIZE; i++)
+ for (dquot = dquot_hash[type][i]; dquot; dquot = dquot->dq_next) {
+ dquot->dq_h = h;
+ /* Unset grace times if limit is not exceeded; if limit is not set, clear times too... */
+ if (dquot->dq_dqb.dqb_bsoftlimit > toqb(dquot->dq_dqb.dqb_curspace))
+ dquot->dq_dqb.dqb_btime = 0;
+ if (dquot->dq_dqb.dqb_isoftlimit > dquot->dq_dqb.dqb_curinodes)
+ dquot->dq_dqb.dqb_itime = 0;
+ h->qh_ops->commit_dquot(dquot);
+ }
+ if (end_io(h) < 0) {
+ fprintf(stderr, _("Can't finish IO on new quotafile: %s\n"), strerror(errno));
+ return -1;
+ }
+ if (rename_files(mnt, type) < 0)
+ return -1;
+ if (fmt == kern_quota_on(mnt_fsname, type, 1 << fmt)) { /* Quota turned on? */
+ char *filename;
+
+ filename = get_qf_name(mnt, type, fmt);
+ if (quotactl(QCMD(Q_QUOTAOFF, type), mnt_fsname, 0, NULL)
+ || quotactl(QCMD(Q_QUOTAON, type), mnt_fsname, 0, filename))
+ fprintf(stderr,
+ _
+ ("Can't turn %s quotas on %s off and on: %s\nKernel won't know about changes quotacheck did.\n"),
+ type2name(type), mnt_fsname, strerror(errno));
+ free(filename);
+ }
+ return 0;
+}
+
+static void check_dir(char *mnt_fsname, struct mntent *mnt)
+{
+ struct stat st;
+ int remounted = 0;
+ loff_t qspace;
+
+ if (lstat(mnt->mnt_dir, &st) < 0)
+ die(2, _("Can't stat mountpoint %s: %s\n"), mnt, strerror(errno));
+ if (!S_ISDIR(st.st_mode))
+ die(2, _("Mountpoint %s isn't directory?!\n"), mnt);
+ qspace = getqsize(mnt->mnt_dir, &st);
+ cur_dev = st.st_dev;
+ files_done = dirs_done = 0;
+ if (ucheck) {
+ if (process_file(mnt_fsname, mnt, USRQUOTA) >= 0)
+ add_to_quota(USRQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+ st.st_nlink, qspace);
+ else
+ ucheck = 0;
+ }
+ if (gcheck) {
+ if (process_file(mnt_fsname, mnt, GRPQUOTA) >= 0)
+ add_to_quota(GRPQUOTA, st.st_ino, st.st_uid, st.st_gid, st.st_mode,
+ st.st_nlink, qspace);
+ else
+ gcheck = 0;
+ }
+ if (!ucheck && !gcheck) /* Nothing to check? */
+ return;
+ if (!(flags & FL_NOREMOUNT)) {
+ /* Now we try to remount fs read-only to prevent races when scanning filesystem */
+ if (mount
+ (NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY,
+ NULL) < 0 && !(flags & FL_FORCEREMOUNT)) {
+ if (flags & FL_INTERACTIVE) {
+ printf(_
+ ("Can't remount filesystem mounted on %s read-only. Counted values might not be right.\n"),
+mnt->mnt_dir);
+ if (!ask_yn(_("Should I continue"), 0)) {
+ printf(_("As you wish... Canceling check of this file.\n"));
+ goto out;
+ }
+ }
+ else {
+ fprintf(stderr,
+ _
+ ("Can't remount filesystem mounted on %s read-only so counted values might not be right.\n\
+Please stop all programs writing to filesystem or use -F flag to force checking.\n"),
+ mnt->mnt_dir);
+ goto out;
+ }
+ }
+ else
+ remounted = 1;
+ debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted RO\n"));
+ }
+ debug(FL_VERBOSE, _("Scanning %s [%s] "), mnt_fsname, mnt->mnt_dir);
+#if defined(EXT2_DIRECT)
+ if (!strcmp(mnt->mnt_type, MNTTYPE_EXT2) || !strcmp(mnt->mnt_type, MNTTYPE_EXT3)) {
+ if (ext2_direct_scan(mnt->mnt_dir) < 0)
+ goto out;
+ }
+ else if (mnt_fsname) {
+#else
+ if (mnt->mnt_dir) {
+#endif
+ if (scan_dir(mnt->mnt_dir) < 0)
+ goto out;
+ }
+ dirs_done++;
+ if (flags & FL_VERBOSE)
+ fputs(_("done\n"), stderr);
+ debug(FL_DEBUG | FL_VERBOSE, _("Checked %d directories and %d files\n"), dirs_done,
+ files_done);
+ if (remounted) {
+ if (mount(NULL, mnt->mnt_dir, mnt->mnt_type, MS_MGC_VAL | MS_REMOUNT, NULL) < 0)
+ die(4,
+ _
+ ("Can't remount filesystem %s read-write. Can't write new quota files.\n"),
+ mnt->mnt_dir);
+ debug(FL_DEBUG | FL_VERBOSE, _("Filesystem remounted RW.\n"));
+ }
+ if (ucheck)
+ dump_to_file(mnt_fsname, mnt, USRQUOTA);
+ if (gcheck)
+ dump_to_file(mnt_fsname, mnt, GRPQUOTA);
+ out:
+ remove_list();
+}
+
+static void check_all(void)
+{
+ FILE *mntf;
+ struct mntent *mnt;
+ const char *mnt_fslabel;
+ char *devlist[MAXMNTPOINTS];
+ int gotmnt = 0, i;
+
+ if (!(mntf = setmntent(MOUNTED, "r")))
+ die(2, _("Can't open %s: %s\n"), MOUNTED, strerror(errno));
+ while ((mnt = getmntent(mntf))) {
+ if (gotmnt == MAXMNTPOINTS)
+ die(3, _("Too many mountpoints. Please report to: %s\n"), MY_EMAIL);
+ if (!(devlist[gotmnt] = (char *)get_device_name(mnt->mnt_fsname)))
+ continue;
+ for (i = 0; i < gotmnt && strcmp(devlist[i], devlist[gotmnt]); i++);
+ /* We already have this mountpoint? */
+ if (i < gotmnt)
+ continue;
+ gotmnt++;
+ if ((mnt_fslabel = strchr(mnt->mnt_fsname, '=')))
+ mnt_fslabel++;
+ else
+ mnt_fslabel = devlist[gotmnt - 1];
+ if ((flags & FL_ALL && (!(flags & FL_NOROOT) || strcmp(mnt->mnt_dir, "/"))) ||
+ !strcmp(mntpoint, devlist[gotmnt - 1]) || !strcmp(mntpoint, mnt->mnt_dir)) {
+ if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
+ debug(FL_DEBUG | FL_VERBOSE, _("Skipping %s [%s]\n"), mnt_fslabel,
+ mnt->mnt_dir);
+ continue;
+ }
+ if (uwant && hasquota(mnt, USRQUOTA))
+ ucheck = 1;
+ else
+ ucheck = 0;
+ if (gwant && hasquota(mnt, GRPQUOTA))
+ gcheck = 1;
+ else
+ gcheck = 0;
+ check_dir(devlist[gotmnt - 1], mnt);
+ }
+ }
+ endmntent(mntf);
+ if (!(flags & FL_ALL) && !gotmnt)
+ die(1, _("Can't find mountpoint %s.\n"), mntpoint);
+ for (i = 0; i < gotmnt; i++)
+ free(devlist[i]);
+}
+
+int main(int argcnt, char **argstr)
+{
+ gettexton();
+ parse_options(argcnt, argstr);
+ warn_new_kernel(fmt);
+
+ check_all();
+#ifdef DEBUG_MALLOC
+ fprintf(stderr, _("Allocated %d bytes memory\nFree'd %d bytes\nLost %d bytes\n"),
+ malloc_mem, free_mem, malloc_mem - free_mem);
+#endif
+ return 0;
+}
diff --git a/quotacheck.h b/quotacheck.h
new file mode 100644
index 0000000..a20efb3
--- /dev/null
+++ b/quotacheck.h
@@ -0,0 +1,44 @@
+/*
+ *
+ * Header file for quota checking utilities
+ *
+ */
+
+#ifndef _QUOTACHECK_H
+#define _QUOTACHECK_H
+
+#include <sys/types.h>
+
+#include "quota.h"
+#include "quotaio.h"
+
+#define NODQUOT ((struct dquot *)NULL)
+
+#define FL_FORCE 1 /* Force check even if quota enabled */
+#define FL_VERBOSE 2 /* Have verbose input */
+#define FL_DEBUG 4 /* Have very verbose input */
+#define FL_INTERACTIVE 8 /* Ask questions when needed */
+#define FL_GUESSDQ 16 /* When more structures for same user found, use the first */
+#define FL_NEWFILE 32 /* Don't try to read old file. Just create new one. */
+#define FL_FORCEREMOUNT 64 /* Force check even when remounting RO fails */
+#define FL_NOREMOUNT 128 /* Don't try to remount filesystem RO */
+#define FL_ALL 256 /* Scan all mountpoints with quota? */
+#define FL_NOROOT 512 /* Scan all mountpoints except root */
+
+extern int flags; /* Options from command line */
+extern struct util_dqinfo old_info[MAXQUOTAS]; /* Loaded info from file */
+
+#ifdef DEBUG_MALLOC
+extern size_t malloc_mem = 0;
+extern size_t free_mem = 0;
+#endif
+
+void *xmalloc(size_t size);
+void debug(int df, char *fmtstr, ...);
+int ask_yn(char *q, int def);
+struct dquot *lookup_dquot(qid_t id, int type);
+struct dquot *add_dquot(qid_t id, int type);
+int v2_buffer_file(char *filename, int fd, int type);
+int v1_buffer_file(char *filename, int fd, int type);
+
+#endif
diff --git a/quotacheck_v1.c b/quotacheck_v1.c
new file mode 100644
index 0000000..db21c94
--- /dev/null
+++ b/quotacheck_v1.c
@@ -0,0 +1,83 @@
+/*
+ *
+ * Checking routines for old VFS quota format
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quotaio.h"
+#include "quotaio_v1.h"
+#include "quotacheck.h"
+
+/* Load all other dquot structures */
+static void load_dquots(char *filename, int fd, int type)
+{
+ struct v1_disk_dqblk ddqblk;
+ struct util_dqblk *udq;
+ struct dquot *dquot;
+ int err;
+ qid_t id = 0;
+
+ lseek(fd, 0, SEEK_SET);
+ while ((err = read(fd, &ddqblk, sizeof(ddqblk)))) {
+ if (err < 0)
+ die(1, _("Can't read entry for id %u from quotafile %s: %s\n"), (uint) id,
+ filename, strerror(errno));
+ if (err != sizeof(ddqblk)) {
+ fprintf(stderr, _("Entry for id %u is truncated.\n"), (uint) id);
+ break;
+ }
+ dquot = add_dquot(id, type);
+ udq = &dquot->dq_dqb;
+ udq->dqb_bhardlimit = ddqblk.dqb_bhardlimit;
+ udq->dqb_bsoftlimit = ddqblk.dqb_bsoftlimit;
+ udq->dqb_ihardlimit = ddqblk.dqb_ihardlimit;
+ udq->dqb_isoftlimit = ddqblk.dqb_isoftlimit;
+ udq->dqb_btime = ddqblk.dqb_btime;
+ udq->dqb_itime = ddqblk.dqb_itime;
+ id++;
+ }
+}
+
+/* Load first structure - get grace times */
+static int check_info(char *filename, int fd, int type)
+{
+ struct v1_disk_dqblk ddqblk;
+ int err;
+
+ debug(FL_DEBUG, _("Loading first quota entry with grace times.\n"));
+ lseek(fd, 0, SEEK_SET);
+ err = read(fd, &ddqblk, sizeof(ddqblk));
+ if (err < 0)
+ die(1, _("Can't read first entry from quotafile %s: %s\n"), filename,
+ strerror(errno));
+ if (err != sizeof(ddqblk)) {
+ fprintf(stderr,
+ _
+ ("WARNING: Quotafile %s was probably truncated. Can't save quota settings...\n"),
+ filename);
+ return -1;
+ }
+ old_info[type].dqi_bgrace = ddqblk.dqb_btime;
+ old_info[type].dqi_igrace = ddqblk.dqb_itime;
+ debug(FL_DEBUG, _("First entry loaded.\n"));
+ return 0;
+}
+
+int v1_buffer_file(char *filename, int fd, int type)
+{
+ old_info[type].dqi_bgrace = MAX_DQ_TIME;
+ old_info[type].dqi_igrace = MAX_IQ_TIME;
+ if (flags & FL_NEWFILE)
+ return 0;
+ if (check_info(filename, fd, type) < 0)
+ return 0;
+ load_dquots(filename, fd, type);
+ return 0;
+}
diff --git a/quotacheck_v2.c b/quotacheck_v2.c
new file mode 100644
index 0000000..31a558f
--- /dev/null
+++ b/quotacheck_v2.c
@@ -0,0 +1,344 @@
+/*
+ *
+ * Checking routines for new VFS quota format
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <asm/byteorder.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quota.h"
+#include "quotaio.h"
+#include "quotaio_v2.h"
+#include "quotacheck.h"
+
+#define getdqbuf() smalloc(V2_DQBLKSIZE)
+#define freedqbuf(buf) free(buf)
+
+#define SET_BLK(blk) (blkbmp[(blk) >> 3] |= 1 << ((blk) & 7))
+#define GET_BLK(blk) (blkbmp[(blk) >> 3] & (1 << ((blk) & 7)))
+
+typedef char *dqbuf_t;
+
+static const int magics[MAXQUOTAS] = INITQMAGICS; /* Magics we should look for */
+static const int known_versions[MAXQUOTAS] = INITKNOWNVERSIONS; /* Versions we accept */
+static char *blkbmp; /* Bitmap of checked blocks */
+
+static int check_blkref(uint blk, uint blocks)
+{
+ if (blk >= blocks)
+ return -1;
+ if (blk && blk < V2_DQTREEOFF)
+ return -1;
+ return 0;
+}
+
+/* Load and check basic info about quotas */
+static int check_info(char *filename, int fd, int type)
+{
+ struct v2_disk_dqinfo dinfo;
+ uint blocks, dflags, freeblk, freeent;
+ off_t filesize;
+ int err;
+
+ debug(FL_VERBOSE, _("Checking quotafile info...\n"));
+ lseek(fd, V2_DQINFOOFF, SEEK_SET);
+ err = read(fd, &dinfo, sizeof(struct v2_disk_dqinfo));
+
+ if (err < 0) {
+ fprintf(stderr, _("Can't read info from quota file %s: %s\n"), filename, strerror(errno));
+ return -1;
+ }
+ if (err != sizeof(struct v2_disk_dqinfo)) {
+ fprintf(stderr, _("WARNING: Quota file %s was probably truncated. Can't save quota settings...\n"),
+ filename);
+ return -1;
+ }
+
+ blocks = __le32_to_cpu(dinfo.dqi_blocks);
+ freeblk = __le32_to_cpu(dinfo.dqi_free_blk);
+ freeent = __le32_to_cpu(dinfo.dqi_free_entry);
+ dflags = __le32_to_cpu(dinfo.dqi_flags);
+ filesize = lseek(fd, 0, SEEK_END);
+ if (check_blkref(freeblk, blocks) < 0 || dflags & ~V2_DQF_MASK ||
+ check_blkref(freeent, blocks) < 0 || (filesize + V2_DQBLKSIZE - 1) >> V2_DQBLKSIZE_BITS != blocks) {
+ fprintf(stderr, _("WARNING: Quota file info was corrupted.\n"));
+ debug(FL_DEBUG, _("Size of file: %lu\nBlocks: %u Free block: %u Block with free entry: %u Flags: %x\n"),
+ (unsigned long)filesize, blocks, freeblk, freeent, dflags);
+ old_info[type].dqi_bgrace = MAX_DQ_TIME;
+ old_info[type].dqi_igrace = MAX_IQ_TIME;
+ old_info[type].u.v2_mdqi.dqi_blocks =
+ (filesize + V2_DQBLKSIZE - 1) >> V2_DQBLKSIZE_BITS;
+ old_info[type].u.v2_mdqi.dqi_flags = 0;
+ printf(_("Setting grace times and other flags to default values.\nAssuming number of blocks is %u.\n"),
+ old_info[type].u.v2_mdqi.dqi_blocks);
+ }
+ else {
+ old_info[type].dqi_bgrace = __le32_to_cpu(dinfo.dqi_bgrace);
+ old_info[type].dqi_igrace = __le32_to_cpu(dinfo.dqi_igrace);
+ old_info[type].u.v2_mdqi.dqi_blocks = blocks;
+ old_info[type].u.v2_mdqi.dqi_flags = dflags;
+ }
+ old_info[type].u.v2_mdqi.dqi_free_blk = old_info[type].u.v2_mdqi.dqi_free_entry = 0; /* This won't be needed */
+ debug(FL_DEBUG, _("File info done.\n"));
+ return 0;
+}
+
+/* Print error message */
+static void blk_corrupted(int *corrupted, uint * lblk, uint blk, char *fmtstr, ...)
+{
+ va_list args;
+
+ if (!*corrupted) {
+ if (!(flags & (FL_VERBOSE | FL_DEBUG)))
+ fprintf(stderr, _("Corrupted blocks: "));
+ }
+ if (flags & (FL_VERBOSE | FL_DEBUG)) {
+ va_start(args, fmtstr);
+ fprintf(stderr, _("Block %u: "), blk);
+ vfprintf(stderr, fmtstr, args);
+ fputc('\n', stderr);
+ va_end(args);
+ }
+ else if (*lblk != blk) {
+ if (!*corrupted)
+ fprintf(stderr, "%u", blk);
+ else
+ fprintf(stderr, ", %u", blk);
+ }
+ *corrupted = 1;
+ *lblk = blk;
+ fflush(stderr);
+}
+
+/* Convert dist quota format to utility one - copy just needed fields */
+static inline void disk2utildqblk(struct util_dqblk *u, struct v2_disk_dqblk *d)
+{
+ u->dqb_ihardlimit = __le32_to_cpu(d->dqb_ihardlimit);
+ u->dqb_isoftlimit = __le32_to_cpu(d->dqb_isoftlimit);
+ u->dqb_bhardlimit = __le32_to_cpu(d->dqb_bhardlimit);
+ u->dqb_bsoftlimit = __le32_to_cpu(d->dqb_bsoftlimit);
+ u->dqb_itime = __le64_to_cpu(d->dqb_itime);
+ u->dqb_btime = __le64_to_cpu(d->dqb_btime);
+}
+
+/* Check whether given dquot is empty */
+static int empty_dquot(struct v2_disk_dqblk *d)
+{
+ static struct v2_disk_dqblk fakedq;
+
+ return !memcmp(&fakedq, d, sizeof(fakedq));
+}
+
+/* Put one entry info memory */
+static int buffer_entry(dqbuf_t buf, uint blk, int *corrupted, uint * lblk, int cnt, int type)
+{
+ struct util_dqblk mdq, *fdq;
+ qid_t id;
+ struct dquot *cd;
+
+ disk2utildqblk(&mdq, ((struct v2_disk_dqblk *)(((char *)buf) + sizeof(struct v2_disk_dqdbheader))) + cnt);
+ id = __le32_to_cpu(((struct v2_disk_dqblk *)(((char *)buf) + sizeof(struct v2_disk_dqdbheader)))[cnt].dqb_id);
+ cd = lookup_dquot(id, type);
+ if (cd != NODQUOT) {
+ fdq = &cd->dq_dqb;
+ if (mdq.dqb_bhardlimit != fdq->dqb_bhardlimit
+ || mdq.dqb_bsoftlimit != fdq->dqb_bsoftlimit
+ || mdq.dqb_ihardlimit != fdq->dqb_ihardlimit
+ || mdq.dqb_isoftlimit != fdq->dqb_isoftlimit) {
+ blk_corrupted(corrupted, lblk, blk, _("Duplicated entries."));
+ if (flags & FL_GUESSDQ) {
+ if (!(flags & (FL_DEBUG | FL_VERBOSE)))
+ fputc('\n', stderr);
+ fprintf(stderr, _("Found more structures for ID %u. Using values: BHARD: %Ld BSOFT: %Ld IHARD: %Ld ISOFT: %Ld\n"),
+ (uint) id, (long long)fdq->dqb_bhardlimit, (long long)fdq->dqb_bsoftlimit,
+ (long long)fdq->dqb_ihardlimit, (long long)fdq->dqb_isoftlimit);
+ return 0;
+ }
+ else if (flags & FL_INTERACTIVE) {
+ fprintf(stderr, _("\nFound more structures for ID %u. Values: BHARD: %Ld/%Ld BSOFT: %Ld/%Ld IHARD: %Ld/%Ld ISOFT: %Ld/%Ld\n"),
+ (uint) id, (long long)fdq->dqb_bhardlimit, (long long)mdq.dqb_bhardlimit,
+ (long long)fdq->dqb_bsoftlimit, (long long)mdq.dqb_bsoftlimit,
+ (long long)fdq->dqb_ihardlimit, (long long)mdq.dqb_ihardlimit,
+ (long long)fdq->dqb_isoftlimit, (long long)mdq.dqb_isoftlimit);
+ if (ask_yn(_("Should I use new values"), 0)) {
+ fdq->dqb_bhardlimit = mdq.dqb_bhardlimit;
+ fdq->dqb_bsoftlimit = mdq.dqb_bsoftlimit;
+ fdq->dqb_ihardlimit = mdq.dqb_ihardlimit;
+ fdq->dqb_isoftlimit = mdq.dqb_isoftlimit;
+ fdq->dqb_btime = mdq.dqb_btime;
+ fdq->dqb_itime = mdq.dqb_itime;
+ }
+ }
+ else {
+ fprintf(stderr, _("ID %u has more structures. User intervention needed (use -i for interactive mode or -n for automatic answer).\n"),
+ (uint) id);
+ return -1;
+ }
+ }
+ else if (mdq.dqb_itime != fdq->dqb_itime || mdq.dqb_btime != fdq->dqb_btime) {
+ if (fdq->dqb_btime < mdq.dqb_btime)
+ fdq->dqb_btime = mdq.dqb_btime;
+ if (fdq->dqb_itime < mdq.dqb_itime)
+ fdq->dqb_itime = mdq.dqb_itime;
+ }
+ }
+ else {
+ cd = add_dquot(id, type);
+ fdq = &cd->dq_dqb;
+ fdq->dqb_bhardlimit = mdq.dqb_bhardlimit;
+ fdq->dqb_bsoftlimit = mdq.dqb_bsoftlimit;
+ fdq->dqb_ihardlimit = mdq.dqb_ihardlimit;
+ fdq->dqb_isoftlimit = mdq.dqb_isoftlimit;
+ fdq->dqb_btime = mdq.dqb_btime;
+ fdq->dqb_itime = mdq.dqb_itime;
+ }
+ return 0;
+}
+
+static void check_read_blk(int fd, uint blk, dqbuf_t buf)
+{
+ size_t rd;
+
+ lseek(fd, blk << V2_DQBLKSIZE_BITS, SEEK_SET);
+ rd = read(fd, buf, V2_DQBLKSIZE);
+ if (rd < 0)
+ die(2, _("Can't read block %u: %s\n"), blk, strerror(errno));
+ if (rd != V2_DQBLKSIZE) {
+ debug(FL_VERBOSE | FL_DEBUG, _("Block %u is truncated.\n"), blk);
+ memset(buf + rd, 0, V2_DQBLKSIZE - rd);
+ }
+}
+
+static int check_tree_ref(uint blk, uint ref, uint blocks, int check_use, uint * corrupted,
+ uint * lblk)
+{
+ if (check_blkref(ref, blocks) < 0)
+ blk_corrupted(corrupted, lblk, blk, _("Reference to illegal block %u"), ref);
+ if (!ref)
+ return 0;
+ if (!check_use || !GET_BLK(ref))
+ return 0;
+ blk_corrupted(corrupted, lblk, blk, _("Block %u in tree referenced twice"), ref);
+ return -1;
+}
+
+/* Check block with structures */
+static int check_data_blk(int fd, uint blk, int type, uint blocks, uint * corrupted, uint * lblk)
+{
+ dqbuf_t buf = getdqbuf();
+ struct v2_disk_dqdbheader *head = (struct v2_disk_dqdbheader *)buf;
+ int i;
+ struct v2_disk_dqblk *dd = (struct v2_disk_dqblk *)(head + 1);
+
+ SET_BLK(blk);
+ check_read_blk(fd, blk, buf);
+ if (check_blkref(__le32_to_cpu(head->dqdh_next_free), blocks) < 0)
+ blk_corrupted(corrupted, lblk, blk, _("Illegal free block reference to block %u"),
+ __le32_to_cpu(head->dqdh_next_free));
+ if (__le16_to_cpu(head->dqdh_entries) > V2_DQSTRINBLK)
+ blk_corrupted(corrupted, lblk, blk, _("Corrupted number of used entries (%u)"),
+ (uint) __le16_to_cpu(head->dqdh_entries));
+ for (i = 0; i < V2_DQSTRINBLK; i++)
+ if (!empty_dquot(dd + i))
+ if (buffer_entry(buf, blk, corrupted, lblk, i, type) < 0) {
+ freedqbuf(buf);
+ return -1;
+ }
+ freedqbuf(buf);
+ return 0;
+}
+
+/* Check one tree block */
+static int check_tree_blk(int fd, uint blk, int depth, int type, uint blocks, uint * corrupted,
+ uint * lblk)
+{
+ dqbuf_t buf = getdqbuf();
+ u_int32_t *r = (u_int32_t *) buf;
+ int i;
+
+ SET_BLK(blk);
+ check_read_blk(fd, blk, buf);
+ for (i = 0; i < V2_DQBLKSIZE >> 2; i++)
+ if (depth < V2_DQTREEDEPTH - 1) {
+ if (check_tree_ref(blk, __le32_to_cpu(r[i]), blocks, 1, corrupted, lblk) >= 0 &&
+ __le32_to_cpu(r[i])) /* Isn't block OK? */
+ if (check_tree_blk(fd, __le32_to_cpu(r[i]), depth + 1, type, blocks, corrupted, lblk) < 0) {
+ freedqbuf(buf);
+ return -1;
+ }
+ }
+ else if (check_tree_ref(blk, __le32_to_cpu(r[i]), blocks, 0, corrupted, lblk) >= 0 && __le32_to_cpu(r[i]))
+ if (check_data_blk(fd, __le32_to_cpu(r[i]), type, blocks, corrupted, lblk) < 0) {
+ freedqbuf(buf);
+ return -1;
+ }
+ freedqbuf(buf);
+ return 0;
+}
+
+/* Check basic header */
+static int check_header(char *filename, int fd, int type)
+{
+ int err;
+ struct v2_disk_dqheader head;
+
+ debug(FL_DEBUG, _("Checking quotafile headers...\n"));
+ lseek(fd, 0, SEEK_SET);
+ err = read(fd, &head, sizeof(head));
+ if (err < 0)
+ die(1, _("Can't read header from quotafile %s: %s\n"), filename, strerror(errno));
+ if (err != sizeof(head)) {
+ fprintf(stderr, _("WARNING: Quotafile %s was probably truncated. Can't save quota settings...\n"),
+ filename);
+ return -1;
+ }
+ if (__le32_to_cpu(head.dqh_magic) != magics[type] || __le32_to_cpu(head.dqh_version) > known_versions[type])
+ fprintf(stderr, _("WARNING: Quota file %s has corrupted headers\n"), filename);
+ debug(FL_DEBUG, _("Headers checked.\n"));
+ return 0;
+}
+
+/* Load data from file to memory */
+int v2_buffer_file(char *filename, int fd, int type)
+{
+ uint blocks, lastblk = 0;
+ int corrupted = 0, ret = 0;
+
+ old_info[type].dqi_bgrace = MAX_DQ_TIME;
+ old_info[type].dqi_igrace = MAX_IQ_TIME;
+ if (flags & FL_NEWFILE)
+ return 0;
+ if (check_header(filename, fd, type) < 0)
+ return 0;
+ if (check_info(filename, fd, type) < 0)
+ return 0;
+ debug(FL_DEBUG | FL_VERBOSE, _("Headers of file %s checked. Going to load data...\n"),
+ filename);
+ blocks = old_info[type].u.v2_mdqi.dqi_blocks;
+ blkbmp = xmalloc((blocks + 7) >> 3);
+ memset(blkbmp, 0, (blocks + 7) >> 3);
+ if (check_tree_ref(0, V2_DQTREEOFF, blocks, 1, &corrupted, &lastblk) >= 0)
+ ret = check_tree_blk(fd, V2_DQTREEOFF, 0, type, blocks, &corrupted, &lastblk);
+ else
+ fprintf(stderr, _("Can't gather quota data. Tree root node corrupted.\n"));
+#ifdef DEBUG_MALLOC
+ free_mem += (blocks + 7) >> 3;
+#endif
+ free(blkbmp);
+ if (corrupted) {
+ if (!(flags & (FL_VERBOSE | FL_DEBUG)))
+ fputc('\n', stderr);
+ fprintf(stderr, _("WARNING: Some data might be changed due to corruption.\n"));
+ }
+ else
+ debug(FL_DEBUG | FL_VERBOSE, _("Not found any corrupted blocks. Congratulations.\n"));
+ return ret;
+}
diff --git a/quotactl.2 b/quotactl.2
new file mode 100644
index 0000000..006c86e
--- /dev/null
+++ b/quotactl.2
@@ -0,0 +1,231 @@
+.TH QUOTACTL 2
+.SH NAME
+quotactl \- manipulate disk quotas
+.SH SYNOPSIS
+.nf
+.B #include <linux/quota.h>
+.B #include <linux/xqm.h>
+.LP
+.B int quotactl(int cmd, char \(**special, int uid, caddr_t addr)
+.fi
+.SH DESCRIPTION
+.LP
+.IX "filesystem" "quotactl() disk quotas" "" "\fLquotactl()\fP \(em disk quotas"
+.IX "quotactl() disk quotas" "" "\fLquotactl()\fP \(em disk quotas"
+.IX "disk quotas quotactl()" "" "disk quotas \(em \fLquotactl()\fP"
+.LP
+The
+.B quotactl(\|)
+call manipulates disk quotas.
+.I cmd
+indicates a command to be applied to
+.SM UID
+.IR id
+or
+.SM GID
+.IR id .
+To set the type of quota use the
+.IR "QCMD(cmd, type)"
+macro.
+.I special
+is a pointer to a null-terminated string containing the path
+name of the block special device for the filesystem being manipulated.
+.I addr
+is the address of an optional, command specific, data structure
+which is copied in or out of the system. The interpretation of
+.I addr
+is given with each command below.
+.TP 15
+.SB Q_QUOTAON
+Turn on quotas for a filesystem.
+.I addr
+points to the path name of file containing the quotas for the filesystem.
+The quota file must exist; it is normally created with the
+.BR quotacheck (8)
+program. This call is restricted to the super-user.
+.TP
+.SB Q_QUOTAOFF
+Turn off quotas for a filesystem.
+.I addr
+and
+.I uid
+are ignored.
+This call is restricted to the super-user.
+.TP
+.SB Q_GETQUOTA
+Get disk quota limits and current usage for user or group
+.IR id .
+.I addr
+is a pointer to a
+.B dqblk
+structure (defined in
+.BR <linux/quota.h> ).
+Only the super-user may get the quotas of a user other than himself.
+.TP
+.SB Q_SETQUOTA
+Set disk quota limits and current usage for user or group
+.IR id .
+.I addr
+is a pointer to a
+.B dqblk
+structure (defined in
+.BR <linux/quota.h> ).
+This call is restricted to the super-user.
+.TP
+.SB Q_SETQLIM
+Set disk quota limits for user or group
+.IR id .
+.I addr
+is a pointer to a
+.B dqblk
+structure (defined in
+.BR <linux/quota.h> ).
+This call is restricted to the super-user.
+.TP
+.SB Q_SYNC
+Update the on-disk copy of quota usages for a filesystem.
+If
+.I special
+is null then all filesystems with active quotas are sync'ed.
+.I addr
+and
+.I uid
+are ignored.
+.PP
+For XFS filesystems making use of the XFS Quota Manager (XQM), the
+above commands are bypassed and the following commands are used:
+.TP 15
+.SB Q_XQUOTAON
+Turn on quotas for an XFS filesystem.
+XFS provides the ability to turn on/off quota limit enforcement
+with quota accounting.
+Therefore, XFS expects the addr to be a pointer to an unsigned int
+that contains either the flags XFS_QUOTA_UDQ_ACCT and/or
+XFS_QUOTA_UDQ_ENFD (for user quota), or XFS_QUOTA_GDQ_ACCT and/or
+XFS_QUOTA_GDQ_ENFD (for group quota), as defined in
+.BR <linux/xqm.h> .
+This call is restricted to the superuser.
+.TP
+.SB Q_XQUOTAOFF
+Turn off quotas for an XFS filesystem.
+As in Q_QUOTAON, XFS filesystems expect a pointer to an unsigned int
+that specifies whether quota accounting and/or limit enforcement need
+to be turned off.
+This call is restricted to the superuser.
+.TP
+.SB Q_XGETQUOTA
+Get disk quota limits and current usage for user
+.IR uid .
+.I addr
+is a pointer to a
+.B fs_disk_quota
+structure (defined in
+.BR <linux/xqm.h> ).
+Only the superuser may get the quotas of a user other than himself.
+.TP
+.SB Q_XSETQLIM
+Set disk quota limits for user
+.IR uid .
+.I addr
+is a pointer to a
+.B fs_disk_quota
+structure (defined in
+.BR <linux/xqm.h> ).
+This call is restricted to the superuser.
+.TP
+.SB Q_XGETQSTAT
+Returns a
+.B fs_quota_stat
+structure containing XFS filesystem specific quota information.
+This is useful in finding out how much space is spent to store quota
+information, and also to get quotaon/off status of a given local XFS
+filesystem.
+.TP
+.SB Q_XQUOTARM
+Free the disk space taken by disk quotas.
+Quotas must have already been turned off.
+.PP
+There is no command equivalent to
+.B Q_SYNC
+for XFS since
+.IR sync (1)
+writes quota information to disk (in addition to the other filesystem
+metadata it writes out).
+.SH RETURN VALUES
+.LP
+.B quotactl(\|)
+returns:
+.TP
+0
+on success.
+.TP
+\-1
+on failure and sets
+.B errno
+to indicate the error.
+.SH ERRORS
+.TP 15
+.SM EFAULT
+.I addr
+or
+.I special
+are invalid.
+.TP
+.SM EINVAL
+The kernel has not been compiled with the
+.SB QUOTA
+option.
+.IP
+.I cmd
+is invalid.
+.TP
+.SM ENOENT
+The file specified by
+.I special
+or
+.I addr
+does not exist.
+.TP
+.SM ENOTBLK
+.I special
+is not a block device.
+.TP
+.SM EPERM
+The call is privileged and the caller was not the super-user.
+.TP
+.SM ESRCH
+No disc quota is found for the indicated user.
+.IP
+Quotas have not been turned on for this filesystem.
+.TP
+.SM EUSERS
+The quota table is full.
+.LP
+If
+.I cmd
+is
+.BR \s-1Q_QUOTAON\s0 ,
+.B quotactl(\|)
+may set errno to:
+.TP 15
+.SM EACCES
+The quota file pointed to by
+.I addr
+exists but is not a regular file.
+.IP
+The quota file pointed to by
+.I addr
+exists but is not on the
+filesystem pointed to by
+.IR special .
+.TP
+.SM EBUSY
+.SB Q_QUOTAON
+attempted while another
+.SB Q_QUOTAON
+has already taken place.
+.SH "SEE ALSO"
+.BR quota (1),
+.BR getrlimit (2),
+.BR quotacheck (8),
+.BR quotaon (8)
diff --git a/quotaio.c b/quotaio.c
new file mode 100644
index 0000000..0a1927d
--- /dev/null
+++ b/quotaio.c
@@ -0,0 +1,238 @@
+/*
+ *
+ * Generic IO operations on quotafiles
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+
+#include "pot.h"
+#include "bylabel.h"
+#include "common.h"
+#include "quotasys.h"
+#include "quotaio.h"
+
+#include "dqblk_v1.h"
+#include "dqblk_v2.h"
+#include "dqblk_rpc.h"
+#include "dqblk_xfs.h"
+
+static int file_magics[] = INITQMAGICS;
+static int known_versions[] = INITKNOWNVERSIONS;
+
+/* Header in all newer quotafiles */
+struct disk_dqheader {
+ u_int32_t dqh_magic;
+ u_int32_t dqh_version;
+} __attribute__ ((packed));
+
+/*
+ * Detect quotafile format
+ */
+int detect_qf_format(int fd, int type)
+{
+ struct disk_dqheader head;
+ int ret;
+
+ if ((ret = read(fd, &head, sizeof(head))) < 0)
+ die(2, _("Error while reading from quotafile: %s\n"), strerror(errno));
+ if (ret != sizeof(head) || head.dqh_magic != file_magics[type]) /* Short file? Probably old format */
+ return QF_VFSOLD;
+ if (head.dqh_version > known_versions[type]) /* Too new format? */
+ return QF_TOONEW;
+ return QF_VFSV0;
+}
+
+/*
+ * Detect quota format and initialize quota IO
+ */
+struct quota_handle *init_io(struct mntent *mnt, int type, int fmt)
+{
+ char *qfname = NULL;
+ int fd = -1, kernfmt;
+ struct quota_handle *h = smalloc(sizeof(struct quota_handle));
+ const char *mnt_fsname = NULL;
+
+ if (!hasquota(mnt, type))
+ goto out_handle;
+ if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
+ goto out_handle;
+ h->qh_io_flags = 0;
+ h->qh_type = type;
+ sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
+ free((char *)mnt_fsname);
+ if (!strcmp(mnt->mnt_type, MNTTYPE_NFS)) { /* NFS filesystem? */
+ if (fmt != -1 && fmt != QF_RPC) { /* User wanted some other format? */
+ fprintf(stderr, _("Only RPC quota format is allowed on NFS filesystem.\n"));
+ goto out_handle;
+ }
+#ifdef RPC
+ h->qh_fd = -1;
+ h->qh_fmt = QF_RPC;
+ h->qh_ops = &quotafile_ops_rpc;
+ return h;
+#else
+ fprintf(stderr, _("RPC quota format not compiled.\n"));
+ goto out_handle;
+#endif
+ }
+
+ if (!strcmp(mnt->mnt_type, MNTTYPE_XFS)) {
+ h->qh_fd = -1;
+ h->qh_fmt = QF_XFS;
+ h->qh_ops = &quotafile_ops_xfs;
+ memset(&h->qh_info, 0, sizeof(h->qh_info));
+ h->qh_ops->init_io(h);
+ return h;
+ }
+ kernfmt = kern_quota_format(); /* Check kernel quota format */
+ if (kernfmt > 0 && (fmt == -1 || (1 << fmt) & kernfmt) && /* Quota compiled and desired format available? */
+ /* Quota turned on? */
+ (kernfmt = kern_quota_on(h->qh_quotadev, type, fmt == -1 ? kernfmt : (1 << fmt))) != -1) {
+ h->qh_io_flags |= IOFL_QUOTAON;
+ fmt = kernfmt; /* Default is kernel used format */
+ }
+ if (!(qfname = get_qf_name(mnt, type, fmt))) {
+ fprintf(stderr, _("Can't get quotafile name.\n"));
+ goto out_handle;
+ }
+ if (qfname[0]) { /* Has format any quotafile to open? */
+ /* We still need to open file for operations like 'repquota' */
+ if ((fd = open(qfname, O_RDWR)) < 0) {
+ fprintf(stderr, _("Can't open quotafile %s: %s\n"), qfname,
+ strerror(errno));
+ goto out_handle;
+ }
+ flock(fd, LOCK_EX);
+ /* Init handle */
+ h->qh_fd = fd;
+
+ /* Check file format */
+ h->qh_fmt = detect_qf_format(fd, type);
+ if (h->qh_fmt == -2) {
+ fprintf(stderr, _("Quotafile format too new in %s\n"), qfname);
+ goto out_lock;
+ }
+ if (fmt != -1 && h->qh_fmt != fmt) {
+ fprintf(stderr,
+ _
+ ("Quotafile format detected differs from the specified one (or the one kernel uses on the file).\n"));
+ goto out_handle;
+ }
+ }
+ else {
+ h->qh_fd = -1;
+ h->qh_fmt = fmt;
+ }
+
+ if (h->qh_fmt == QF_VFSOLD)
+ h->qh_ops = &quotafile_ops_1;
+ else if (h->qh_fmt == QF_VFSV0)
+ h->qh_ops = &quotafile_ops_2;
+ memset(&h->qh_info, 0, sizeof(h->qh_info));
+
+ if (h->qh_ops->init_io && h->qh_ops->init_io(h) < 0)
+ goto out_lock;
+ return h;
+ out_lock:
+ if (fd != -1)
+ flock(fd, LOCK_UN);
+ out_handle:
+ if (qfname)
+ free(qfname);
+ free(h);
+ return NULL;
+}
+
+/*
+ * Create new quotafile of specified format on given filesystem
+ */
+struct quota_handle *new_io(struct mntent *mnt, int type, int fmt)
+{
+ char *qfname;
+ int fd;
+ struct quota_handle *h;
+ const char *mnt_fsname;
+ char namebuf[PATH_MAX];
+
+ if (fmt == -1)
+ fmt = QF_VFSV0; /* Use the newest format */
+ else if (fmt == QF_RPC || fmt == QF_XFS) {
+ fprintf(stderr, _("Creation of %s quota format is not supported.\n"),
+ fmt == QF_RPC ? "RPC" : "XFS");
+ return NULL;
+ }
+ if (!hasquota(mnt, type) || !(qfname = get_qf_name(mnt, type, fmt)))
+ return NULL;
+ sstrncpy(namebuf, qfname, PATH_MAX);
+ sstrncat(namebuf, ".new", PATH_MAX);
+ free(qfname);
+ if ((fd = open(namebuf, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR)) < 0) {
+ fprintf(stderr, _("Can't create new quotafile %s: %s\n"), namebuf, strerror(errno));
+ return NULL;
+ }
+ if (!(mnt_fsname = get_device_name(mnt->mnt_fsname)))
+ goto out_fd;
+ h = smalloc(sizeof(struct quota_handle));
+
+ h->qh_fd = fd;
+ h->qh_io_flags = 0;
+ sstrncpy(h->qh_quotadev, mnt_fsname, sizeof(h->qh_quotadev));
+ free((char *)mnt_fsname);
+ h->qh_type = type;
+ memset(&h->qh_info, 0, sizeof(h->qh_info));
+ if (fmt == QF_VFSOLD)
+ h->qh_ops = &quotafile_ops_1;
+ else
+ h->qh_ops = &quotafile_ops_2;
+
+ flock(fd, LOCK_EX);
+ if (h->qh_ops->new_io && h->qh_ops->new_io(h) < 0) {
+ flock(fd, LOCK_UN);
+ free(h);
+ goto out_fd;
+ }
+ return h;
+ out_fd:
+ close(fd);
+ return NULL;
+}
+
+/*
+ * Close quotafile and release handle
+ */
+int end_io(struct quota_handle *h)
+{
+ int ret;
+
+ if (h->qh_io_flags & IOFL_INFODIRTY) {
+ if (h->qh_ops->write_info && (ret = h->qh_ops->write_info(h)) >= 0)
+ return ret;
+ h->qh_io_flags &= ~IOFL_INFODIRTY;
+ }
+ if (h->qh_ops->end_io && (ret = h->qh_ops->end_io(h)) >= 0)
+ return ret;
+ flock(h->qh_fd, LOCK_UN);
+ close(h->qh_fd);
+ free(h);
+ return 0;
+}
+
+/*
+ * Create empty quota structure
+ */
+struct dquot *get_empty_dquot(void)
+{
+ struct dquot *dquot = smalloc(sizeof(struct dquot));
+
+ memset(dquot, 0, sizeof(*dquot));
+ dquot->dq_id = -1;
+ return dquot;
+}
diff --git a/quotaio.h b/quotaio.h
new file mode 100644
index 0000000..f5d790c
--- /dev/null
+++ b/quotaio.h
@@ -0,0 +1,141 @@
+/*
+ *
+ * Header of IO operations for quota utilities
+ *
+ */
+
+#ifndef _QUOTAIO_H
+#define _QUOTAIO_H
+
+#include <limits.h>
+#include <sys/types.h>
+
+#include "quota.h"
+#include "mntopt.h"
+#include "dqblk_v1.h"
+#include "dqblk_v2.h"
+#include "dqblk_rpc.h"
+#include "dqblk_xfs.h"
+
+/* Latest known versions */
+#define INITKNOWNVERSIONS {\
+ 0,\
+ 0\
+}
+
+#define QUOTAFORMATS 4
+
+#define INITQFBASENAMES {\
+ "quota",\
+ "aquota",\
+ "",\
+ ""\
+}
+
+/* Values for format handling */
+#define QF_TOONEW -2 /* Quota format is too new to handle */
+#define QF_ERROR -1 /* There was error while detecting format (maybe unknown format...) */
+#define QF_VFSOLD 0 /* Old quota format */
+#define QF_VFSV0 1 /* New quota format - version 0 */
+#define QF_RPC 2 /* RPC should be used on given filesystem */
+#define QF_XFS 3 /* XFS quota format */
+
+/*
+ * Definitions for disk quotas imposed on the average user
+ * (big brother finally hits Linux).
+ *
+ * The following constants define the default amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure). The timer is started when the user crosses
+ * their soft limit, it is reset when they go below their soft limit.
+ */
+#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
+#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
+
+#define IOFL_QUOTAON 0x01 /* Is quota enabled in kernel? */
+#define IOFL_INFODIRTY 0x02 /* Did info change? */
+
+struct quotafile_ops;
+
+/* Generic information about quotafile */
+struct util_dqinfo {
+ time_t dqi_bgrace; /* Block grace time for given quotafile */
+ time_t dqi_igrace; /* Inode grace time for given quotafile */
+ union {
+ struct v2_mem_dqinfo v2_mdqi;
+ struct xfs_mem_dqinfo xfs_mdqi;
+ } u; /* Format specific info about quotafile */
+};
+
+/* Structure for one opened quota file */
+struct quota_handle {
+ int qh_fd; /* Handle of file (-1 when IOFL_QUOTAON) */
+ int qh_io_flags; /* IO flags for file */
+ char qh_quotadev[PATH_MAX]; /* Device file is for */
+ int qh_type; /* Type of quotafile */
+ int qh_fmt; /* Quotafile format */
+ struct quotafile_ops *qh_ops; /* Operations on quotafile */
+ struct util_dqinfo qh_info; /* Generic quotafile info */
+};
+
+/* Utility quota block */
+struct util_dqblk {
+ qsize_t dqb_ihardlimit;
+ qsize_t dqb_isoftlimit;
+ qsize_t dqb_curinodes;
+ qsize_t dqb_bhardlimit;
+ qsize_t dqb_bsoftlimit;
+ qsize_t dqb_curspace;
+ time_t dqb_btime;
+ time_t dqb_itime;
+ union {
+ struct v2_mem_dqblk v2_mdqb;
+ } u; /* Format specific dquot information */
+};
+
+#define DQ_FOUND 0x01 /* Dquot was found in the edquotas file */
+
+/* Structure for one loaded quota */
+struct dquot {
+ struct dquot *dq_next; /* Pointer to next dquot in the list */
+ qid_t dq_id; /* ID dquot belongs to */
+ int dq_flags; /* Some flags for utils */
+ struct quota_handle *dq_h; /* Handle of quotafile dquot belongs to */
+ struct util_dqblk dq_dqb; /* Parsed data of dquot */
+};
+
+/* Structure of quotafile operations */
+struct quotafile_ops {
+ int (*init_io) (struct quota_handle * h); /* Open quotafile */
+ int (*new_io) (struct quota_handle * h); /* Create new quotafile */
+ int (*end_io) (struct quota_handle * h); /* Write all changes and close quotafile */
+ int (*write_info) (struct quota_handle * h); /* Write info about quotafile */
+ struct dquot *(*read_dquot) (struct quota_handle * h, qid_t id); /* Read dquot into memory */
+ int (*commit_dquot) (struct dquot * dquot); /* Write given dquot to disk */
+ int (*scan_dquots) (struct quota_handle * h, int (*process_dquot) (struct dquot * dquot)); /* Scan quotafile and call callback on every structure */
+ int (*report) (struct quota_handle * h, int verbose); /* Function called after 'repquota' to print format specific file information */
+};
+
+static inline void mark_quotafile_info_dirty(struct quota_handle *h)
+{
+ h->qh_io_flags |= IOFL_INFODIRTY;
+}
+
+#define QIO_ENABLED(h) ((h)->qh_io_flags & IOFL_QUOTAON)
+
+/* Detect format of given quotafile */
+int detect_qf_format(int fd, int type);
+
+/* Check quota format used on specified medium and initialize it */
+struct quota_handle *init_io(struct mntent *mnt, int type, int fmt);
+
+/* Create new quotafile of specified format on given filesystem */
+struct quota_handle *new_io(struct mntent *mnt, int type, int fmt);
+
+/* Close quotafile */
+int end_io(struct quota_handle *h);
+
+/* Get empty quota structure */
+struct dquot *get_empty_dquot(void);
+
+#endif /* _QUOTAIO_H */
diff --git a/quotaio_rpc.c b/quotaio_rpc.c
new file mode 100644
index 0000000..0e33390
--- /dev/null
+++ b/quotaio_rpc.c
@@ -0,0 +1,55 @@
+/*
+ * quotaio_rpc.c - quota IO operations for RPC (just wrappers for RPC calls)
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#include "quotaio.h"
+#include "dqblk_rpc.h"
+#include "rquota_client.h"
+
+static struct dquot *rpc_read_dquot(struct quota_handle *h, qid_t id);
+static int rpc_commit_dquot(struct dquot *dquot);
+
+struct quotafile_ops quotafile_ops_rpc = {
+ NULL, /* init_io */
+ NULL, /* new_io */
+ NULL, /* end_io */
+ NULL, /* write_info */
+ rpc_read_dquot,
+ rpc_commit_dquot,
+ NULL /* scan_dquots */
+};
+
+/*
+ * Read a dqblk struct from RPC server - just wrapper function.
+ */
+static struct dquot *rpc_read_dquot(struct quota_handle *h, qid_t id)
+{
+#ifdef RPC
+ struct dquot *dquot = get_empty_dquot();
+
+ dquot->dq_id = id;
+ dquot->dq_h = h;
+ rpc_rquota_get(dquot);
+ return dquot;
+#else
+ errno = ENOTSUP;
+ return NULL;
+#endif
+}
+
+/*
+ * Write a dqblk struct to RPC server - just wrapper function.
+ */
+static int rpc_commit_dquot(struct dquot *dquot)
+{
+#ifdef RPC
+ rpc_rquota_set(QCMD(Q_RPC_SETQUOTA, dquot->dq_h->qh_type), dquot);
+ return 0;
+#else
+ errno = ENOTSUP;
+ return -1;
+#endif
+}
diff --git a/quotaio_v1.c b/quotaio_v1.c
new file mode 100644
index 0000000..e09dc2f
--- /dev/null
+++ b/quotaio_v1.c
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California. All
+ * rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Robert Elz at
+ * The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
+#ident "$Copyright: All rights reserved. $"
+#ident "$Id: quotaio_v1.c,v 1.1 2001/03/23 12:03:28 jkar8572 Exp $"
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quotaio_v1.h"
+#include "dqblk_v1.h"
+#include "quotaio.h"
+
+static int v1_init_io(struct quota_handle *h);
+static int v1_new_io(struct quota_handle *h);
+static int v1_write_info(struct quota_handle *h);
+static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id);
+static int v1_commit_dquot(struct dquot *dquot);
+static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot));
+
+struct quotafile_ops quotafile_ops_1 = {
+ v1_init_io,
+ v1_new_io,
+ NULL, /* end_io */
+ v1_write_info,
+ v1_read_dquot,
+ v1_commit_dquot,
+ v1_scan_dquots,
+ NULL /* report */
+};
+
+/*
+ * Copy dquot from disk to memory
+ */
+static inline void v1_disk2memdqblk(struct util_dqblk *m, struct v1_disk_dqblk *d)
+{
+ m->dqb_ihardlimit = d->dqb_ihardlimit;
+ m->dqb_isoftlimit = d->dqb_isoftlimit;
+ m->dqb_bhardlimit = d->dqb_bhardlimit;
+ m->dqb_bsoftlimit = d->dqb_bsoftlimit;
+ m->dqb_curinodes = d->dqb_curinodes;
+ m->dqb_curspace = d->dqb_curblocks * V1_DQBLK_SIZE;
+ m->dqb_itime = d->dqb_itime;
+ m->dqb_btime = d->dqb_btime;
+}
+
+/*
+ * Copy dquot from memory to disk
+ */
+static inline void v1_mem2diskdqblk(struct v1_disk_dqblk *d, struct util_dqblk *m)
+{
+ d->dqb_ihardlimit = m->dqb_ihardlimit;
+ d->dqb_isoftlimit = m->dqb_isoftlimit;
+ d->dqb_bhardlimit = m->dqb_bhardlimit;
+ d->dqb_bsoftlimit = m->dqb_bsoftlimit;
+ d->dqb_curinodes = m->dqb_curinodes;
+ d->dqb_curblocks = m->dqb_curspace >> V1_DQBLK_SIZE_BITS;
+ d->dqb_itime = m->dqb_itime;
+ d->dqb_btime = m->dqb_btime;
+}
+
+/* Convert kernel quotablock format to utility one */
+static inline void v1_kern2utildqblk(struct util_dqblk *u, struct v1_kern_dqblk *k)
+{
+ u->dqb_ihardlimit = k->dqb_ihardlimit;
+ u->dqb_isoftlimit = k->dqb_isoftlimit;
+ u->dqb_bhardlimit = k->dqb_bhardlimit;
+ u->dqb_bsoftlimit = k->dqb_bsoftlimit;
+ u->dqb_curinodes = k->dqb_curinodes;
+ u->dqb_curspace = k->dqb_curblocks << V1_DQBLK_SIZE_BITS;
+ u->dqb_itime = k->dqb_itime;
+ u->dqb_btime = k->dqb_btime;
+}
+
+/* Convert utility quotablock format to kernel one */
+static inline void v1_util2kerndqblk(struct v1_kern_dqblk *k, struct util_dqblk *u)
+{
+ k->dqb_ihardlimit = u->dqb_ihardlimit;
+ k->dqb_isoftlimit = u->dqb_isoftlimit;
+ k->dqb_bhardlimit = u->dqb_bhardlimit;
+ k->dqb_bsoftlimit = u->dqb_bsoftlimit;
+ k->dqb_curinodes = u->dqb_curinodes;
+ k->dqb_curblocks = (u->dqb_curspace + V1_DQBLK_SIZE - 1) >> V1_DQBLK_SIZE_BITS;
+ k->dqb_itime = u->dqb_itime;
+ k->dqb_btime = u->dqb_btime;
+}
+
+/*
+ * Open quotafile
+ */
+static int v1_init_io(struct quota_handle *h)
+{
+ if (QIO_ENABLED(h)) {
+ struct v1_kern_dqblk kdqblk;
+
+ if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) <
+ 0) return -1;
+ h->qh_info.dqi_bgrace = kdqblk.dqb_btime;
+ h->qh_info.dqi_igrace = kdqblk.dqb_itime;
+ }
+ else {
+ struct v1_disk_dqblk ddqblk;
+
+ lseek(h->qh_fd, 0, SEEK_SET);
+ if (read(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
+ return -1;
+ h->qh_info.dqi_bgrace = ddqblk.dqb_btime;
+ h->qh_info.dqi_igrace = ddqblk.dqb_itime;
+ }
+ return 0;
+}
+
+/*
+ * Initialize new quotafile
+ */
+static int v1_new_io(struct quota_handle *h)
+{
+ struct v1_disk_dqblk ddqblk;
+
+ /* Write at least roots dquot with grace times */
+ memset(&ddqblk, 0, sizeof(ddqblk));
+ ddqblk.dqb_btime = MAX_DQ_TIME;
+ ddqblk.dqb_itime = MAX_IQ_TIME;
+ h->qh_info.dqi_bgrace = MAX_DQ_TIME;
+ h->qh_info.dqi_igrace = MAX_IQ_TIME;
+ lseek(h->qh_fd, 0, SEEK_SET);
+ if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
+ return -1;
+ return 0;
+}
+
+/*
+ * Write information (grace times to file)
+ */
+static int v1_write_info(struct quota_handle *h)
+{
+ if (QIO_ENABLED(h)) {
+ struct v1_kern_dqblk kdqblk;
+
+ if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) <
+ 0) return -1;
+ kdqblk.dqb_btime = h->qh_info.dqi_bgrace;
+ kdqblk.dqb_itime = h->qh_info.dqi_igrace;
+ if (quotactl(QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, 0, (void *)&kdqblk) <
+ 0) return -1;
+ }
+ else {
+ struct v1_disk_dqblk ddqblk;
+
+ lseek(h->qh_fd, 0, SEEK_SET);
+ if (read(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
+ return -1;
+ ddqblk.dqb_btime = h->qh_info.dqi_bgrace;
+ ddqblk.dqb_itime = h->qh_info.dqi_igrace;
+ lseek(h->qh_fd, 0, SEEK_SET);
+ if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Read a dqblk struct from the quotafile.
+ * User can use 'errno' to detect error.
+ */
+static struct dquot *v1_read_dquot(struct quota_handle *h, qid_t id)
+{
+ struct v1_disk_dqblk ddqblk;
+ struct dquot *dquot = get_empty_dquot();
+
+ dquot->dq_id = id;
+ dquot->dq_h = h;
+ if (QIO_ENABLED(h)) { /* Does kernel use the file? */
+ struct v1_kern_dqblk kdqblk;
+
+ if (quotactl(QCMD(Q_V1_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) <
+ 0) {
+ free(dquot);
+ return NULL;
+ }
+ v1_kern2utildqblk(&dquot->dq_dqb, &kdqblk);
+ }
+ else {
+ lseek(h->qh_fd, (long)V1_DQOFF(id), SEEK_SET);
+ switch (read(h->qh_fd, &ddqblk, sizeof(ddqblk))) {
+ case 0: /* EOF */
+ /*
+ * Convert implicit 0 quota (EOF) into an
+ * explicit one (zero'ed dqblk)
+ */
+ memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk));
+
+ break;
+ case sizeof(struct v1_disk_dqblk): /* OK */
+ v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk);
+
+ break;
+ default: /* ERROR */
+ free(dquot);
+ return NULL;
+ }
+ }
+ return dquot;
+}
+
+/*
+ * Write a dqblk struct to the quotafile.
+ * User can process use 'errno' to detect error
+ */
+static int v1_commit_dquot(struct dquot *dquot)
+{
+ struct v1_disk_dqblk ddqblk;
+ struct quota_handle *h = dquot->dq_h;
+
+ if (QIO_ENABLED(h)) { /* Kernel uses same file? */
+ struct v1_kern_dqblk kdqblk;
+
+ v1_util2kerndqblk(&kdqblk, &dquot->dq_dqb);
+ if (quotactl
+ (QCMD(Q_V1_SETQUOTA, h->qh_type), h->qh_quotadev, dquot->dq_id,
+ (void *)&kdqblk) < 0)
+ return -1;
+ }
+ else {
+ v1_mem2diskdqblk(&ddqblk, &dquot->dq_dqb);
+ lseek(h->qh_fd, (long)V1_DQOFF(dquot->dq_id), SEEK_SET);
+ if (write(h->qh_fd, &ddqblk, sizeof(ddqblk)) != sizeof(ddqblk))
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Scan all dquots in file and call callback on each
+ */
+static int v1_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot))
+{
+ int rd;
+ struct v1_disk_dqblk ddqblk;
+ struct dquot *dquot = get_empty_dquot();
+ qid_t id = 0;
+
+ if (QIO_ENABLED(h)) /* Kernel uses same file? */
+ if (quotactl(QCMD(Q_SYNC, h->qh_type), h->qh_quotadev, 0, NULL) < 0)
+ die(4, _("Can't sync quotas on device %s: %s\n"), h->qh_quotadev,
+ strerror(errno));
+ memset(dquot, 0, sizeof(*dquot));
+ dquot->dq_h = h;
+ lseek(h->qh_fd, 0, SEEK_SET);
+ while ((rd = read(h->qh_fd, &ddqblk, sizeof(ddqblk))) == sizeof(ddqblk)) {
+ if (
+ (ddqblk.dqb_ihardlimit | ddqblk.dqb_isoftlimit | ddqblk.dqb_bhardlimit | ddqblk.
+ dqb_bsoftlimit | ddqblk.dqb_curblocks | ddqblk.dqb_curinodes | ddqblk.
+ dqb_itime | ddqblk.dqb_btime) == 0)
+ continue;
+ v1_disk2memdqblk(&dquot->dq_dqb, &ddqblk);
+ dquot->dq_id = id++;
+ if ((rd = process_dquot(dquot)) < 0) {
+ free(dquot);
+ return rd;
+ }
+ }
+ if (!rd) /* EOF? */
+ return 0;
+ return -1; /* Some read error... */
+}
diff --git a/quotaio_v1.h b/quotaio_v1.h
new file mode 100644
index 0000000..f36ed63
--- /dev/null
+++ b/quotaio_v1.h
@@ -0,0 +1,39 @@
+/*
+ * Headerfile for old quotafile format
+ */
+
+#ifndef _QUOTAIO_V1_H
+#define _QUOTAIO_V1_H
+
+#include <sys/types.h>
+
+#define V1_DQBLK_SIZE_BITS 10
+#define V1_DQBLK_SIZE (1 << V1_DQBLK_SIZE_BITS) /* Size of one quota block in bytes in old format */
+
+#define V1_DQOFF(__id) ((loff_t) ((__id) * sizeof(struct v1_disk_dqblk)))
+
+/* Structure of quota on disk */
+struct v1_disk_dqblk {
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_curblocks; /* current block count */
+ u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive files */
+} __attribute__ ((packed));
+
+/* Structure used for communication with kernel */
+struct v1_kern_dqblk {
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk blks alloc */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk blks */
+ u_int32_t dqb_curblocks; /* current block count */
+ u_int32_t dqb_ihardlimit; /* maximum # allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ time_t dqb_btime; /* time limit for excessive disk use */
+ time_t dqb_itime; /* time limit for excessive files */
+};
+
+#endif
diff --git a/quotaio_v2.c b/quotaio_v2.c
new file mode 100644
index 0000000..f200b3a
--- /dev/null
+++ b/quotaio_v2.c
@@ -0,0 +1,734 @@
+/*
+ * Implementation of new quotafile format
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <asm/byteorder.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quotaio_v2.h"
+#include "dqblk_v2.h"
+#include "quotaio.h"
+
+typedef char *dqbuf_t;
+
+static int v2_init_io(struct quota_handle *h);
+static int v2_new_io(struct quota_handle *h);
+static int v2_write_info(struct quota_handle *h);
+static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id);
+static int v2_commit_dquot(struct dquot *dquot);
+static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot));
+static int v2_report(struct quota_handle *h, int verbose);
+
+struct quotafile_ops quotafile_ops_2 = {
+ v2_init_io,
+ v2_new_io,
+ NULL, /* end_io */
+ v2_write_info,
+ v2_read_dquot,
+ v2_commit_dquot,
+ v2_scan_dquots,
+ v2_report
+};
+
+#define getdqbuf() smalloc(V2_DQBLKSIZE)
+#define freedqbuf(buf) free(buf)
+
+/*
+ * Copy dquot from disk to memory
+ */
+static inline void v2_disk2memdqblk(struct util_dqblk *m, struct v2_disk_dqblk *d)
+{
+ m->dqb_ihardlimit = __le32_to_cpu(d->dqb_ihardlimit);
+ m->dqb_isoftlimit = __le32_to_cpu(d->dqb_isoftlimit);
+ m->dqb_bhardlimit = __le32_to_cpu(d->dqb_bhardlimit);
+ m->dqb_bsoftlimit = __le32_to_cpu(d->dqb_bsoftlimit);
+ m->dqb_curinodes = __le32_to_cpu(d->dqb_curinodes);
+ m->dqb_curspace = __le64_to_cpu(d->dqb_curspace);
+ m->dqb_itime = __le64_to_cpu(d->dqb_itime);
+ m->dqb_btime = __le64_to_cpu(d->dqb_btime);
+}
+
+/*
+ * Copy dquot from memory to disk
+ */
+static inline void v2_mem2diskdqblk(struct v2_disk_dqblk *d, struct util_dqblk *m)
+{
+ d->dqb_ihardlimit = __cpu_to_le32(m->dqb_ihardlimit);
+ d->dqb_isoftlimit = __cpu_to_le32(m->dqb_isoftlimit);
+ d->dqb_bhardlimit = __cpu_to_le32(m->dqb_bhardlimit);
+ d->dqb_bsoftlimit = __cpu_to_le32(m->dqb_bsoftlimit);
+ d->dqb_curinodes = __cpu_to_le32(m->dqb_curinodes);
+ d->dqb_curspace = __cpu_to_le64(m->dqb_curspace);
+ d->dqb_itime = __cpu_to_le64(m->dqb_itime);
+ d->dqb_btime = __cpu_to_le64(m->dqb_btime);
+}
+
+/*
+ * Copy dqinfo from disk to memory
+ */
+static inline void v2_disk2memdqinfo(struct util_dqinfo *m, struct v2_disk_dqinfo *d)
+{
+ m->dqi_bgrace = __le32_to_cpu(d->dqi_bgrace);
+ m->dqi_igrace = __le32_to_cpu(d->dqi_igrace);
+ m->u.v2_mdqi.dqi_flags = __le32_to_cpu(d->dqi_flags) & V2_DQF_MASK;
+ m->u.v2_mdqi.dqi_blocks = __le32_to_cpu(d->dqi_blocks);
+ m->u.v2_mdqi.dqi_free_blk = __le32_to_cpu(d->dqi_free_blk);
+ m->u.v2_mdqi.dqi_free_entry = __le32_to_cpu(d->dqi_free_entry);
+}
+
+/*
+ * Copy dqinfo from memory to disk
+ */
+static inline void v2_mem2diskdqinfo(struct v2_disk_dqinfo *d, struct util_dqinfo *m)
+{
+ d->dqi_bgrace = __cpu_to_le32(m->dqi_bgrace);
+ d->dqi_igrace = __cpu_to_le32(m->dqi_igrace);
+ d->dqi_flags = __cpu_to_le32(m->u.v2_mdqi.dqi_flags & V2_DQF_MASK);
+ d->dqi_blocks = __cpu_to_le32(m->u.v2_mdqi.dqi_blocks);
+ d->dqi_free_blk = __cpu_to_le32(m->u.v2_mdqi.dqi_free_blk);
+ d->dqi_free_entry = __cpu_to_le32(m->u.v2_mdqi.dqi_free_entry);
+}
+
+/* Convert kernel quotablock format to utility one */
+static inline void v2_kern2utildqblk(struct util_dqblk *u, struct v2_kern_dqblk *k)
+{
+ u->dqb_ihardlimit = k->dqb_ihardlimit;
+ u->dqb_isoftlimit = k->dqb_isoftlimit;
+ u->dqb_bhardlimit = k->dqb_bhardlimit;
+ u->dqb_bsoftlimit = k->dqb_bsoftlimit;
+ u->dqb_curinodes = k->dqb_curinodes;
+ u->dqb_curspace = k->dqb_curspace;
+ u->dqb_itime = k->dqb_itime;
+ u->dqb_btime = k->dqb_btime;
+}
+
+/* Convert utility quotablock format to kernel one */
+static inline void v2_util2kerndqblk(struct v2_kern_dqblk *k, struct util_dqblk *u)
+{
+ k->dqb_ihardlimit = u->dqb_ihardlimit;
+ k->dqb_isoftlimit = u->dqb_isoftlimit;
+ k->dqb_bhardlimit = u->dqb_bhardlimit;
+ k->dqb_bsoftlimit = u->dqb_bsoftlimit;
+ k->dqb_curinodes = u->dqb_curinodes;
+ k->dqb_curspace = u->dqb_curspace;
+ k->dqb_itime = u->dqb_itime;
+ k->dqb_btime = u->dqb_btime;
+}
+
+/* Is given dquot empty? */
+static int empty_dquot(struct v2_disk_dqblk *d)
+{
+ static struct v2_disk_dqblk fakedquot;
+
+ return !memcmp(d, &fakedquot, sizeof(fakedquot));
+}
+
+/*
+ * Open quotafile
+ */
+static int v2_init_io(struct quota_handle *h)
+{
+ if (QIO_ENABLED(h)) {
+ struct v2_kern_dqinfo kdqinfo;
+
+ if (quotactl(QCMD(Q_V2_GETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) <
+ 0) return -1;
+ h->qh_info.dqi_bgrace = kdqinfo.dqi_bgrace;
+ h->qh_info.dqi_igrace = kdqinfo.dqi_igrace;
+ h->qh_info.u.v2_mdqi.dqi_flags = kdqinfo.dqi_flags;
+ h->qh_info.u.v2_mdqi.dqi_blocks = kdqinfo.dqi_blocks;
+ h->qh_info.u.v2_mdqi.dqi_free_blk = kdqinfo.dqi_free_blk;
+ h->qh_info.u.v2_mdqi.dqi_free_entry = kdqinfo.dqi_free_entry;
+ }
+ else {
+ struct v2_disk_dqinfo ddqinfo;
+
+ lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET);
+ if (read(h->qh_fd, &ddqinfo, sizeof(ddqinfo)) != sizeof(ddqinfo))
+ return -1;
+ v2_disk2memdqinfo(&h->qh_info, &ddqinfo);
+ }
+ return 0;
+}
+
+/*
+ * Initialize new quotafile
+ */
+static int v2_new_io(struct quota_handle *h)
+{
+ int file_magics[] = INITQMAGICS;
+ int known_versions[] = INIT_V2_VERSIONS;
+ struct v2_disk_dqheader ddqheader;
+ struct v2_disk_dqinfo ddqinfo;
+
+ /* Write basic quota header */
+ ddqheader.dqh_magic = __cpu_to_le32(file_magics[h->qh_type]);
+ ddqheader.dqh_version = __cpu_to_le32(known_versions[h->qh_type]);
+ lseek(h->qh_fd, 0, SEEK_SET);
+ if (write(h->qh_fd, &ddqheader, sizeof(ddqheader)) != sizeof(ddqheader))
+ return -1;
+ /* Write information about quotafile */
+ h->qh_info.dqi_bgrace = MAX_DQ_TIME;
+ h->qh_info.dqi_igrace = MAX_IQ_TIME;
+ h->qh_info.u.v2_mdqi.dqi_flags = 0;
+ h->qh_info.u.v2_mdqi.dqi_blocks = V2_DQTREEOFF + 1;
+ h->qh_info.u.v2_mdqi.dqi_free_blk = 0;
+ h->qh_info.u.v2_mdqi.dqi_free_entry = 0;
+ v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
+ lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET);
+ if (write(h->qh_fd, &ddqinfo, sizeof(ddqinfo)) != sizeof(ddqinfo))
+ return -1;
+ return 0;
+}
+
+/*
+ * Write information (grace times to file)
+ */
+static int v2_write_info(struct quota_handle *h)
+{
+ if (QIO_ENABLED(h)) {
+ struct v2_kern_dqinfo kdqinfo;
+
+ kdqinfo.dqi_bgrace = h->qh_info.dqi_bgrace;
+ kdqinfo.dqi_igrace = h->qh_info.dqi_igrace;
+ kdqinfo.dqi_flags = h->qh_info.u.v2_mdqi.dqi_flags;
+ kdqinfo.dqi_blocks = h->qh_info.u.v2_mdqi.dqi_blocks;
+ kdqinfo.dqi_free_blk = h->qh_info.u.v2_mdqi.dqi_free_blk;
+ kdqinfo.dqi_free_entry = h->qh_info.u.v2_mdqi.dqi_free_entry;
+ if (quotactl(QCMD(Q_V2_SETINFO, h->qh_type), h->qh_quotadev, 0, (void *)&kdqinfo) <
+ 0) return -1;
+ }
+ else {
+ struct v2_disk_dqinfo ddqinfo;
+
+ v2_mem2diskdqinfo(&ddqinfo, &h->qh_info);
+ lseek(h->qh_fd, V2_DQINFOOFF, SEEK_SET);
+ if (write(h->qh_fd, &ddqinfo, sizeof(ddqinfo)) != sizeof(ddqinfo))
+ return -1;
+ }
+ return 0;
+}
+
+/* Read given block */
+static void read_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
+{
+ int err;
+
+ lseek(h->qh_fd, blk << V2_DQBLKSIZE_BITS, SEEK_SET);
+ err = read(h->qh_fd, buf, V2_DQBLKSIZE);
+ if (err < 0)
+ die(2, "Can't read block %u: %s\n", blk, strerror(errno));
+ else if (err != V2_DQBLKSIZE)
+ memset(buf + err, 0, V2_DQBLKSIZE - err);
+}
+
+/* Write block */
+static int write_blk(struct quota_handle *h, uint blk, dqbuf_t buf)
+{
+ int err;
+
+ lseek(h->qh_fd, blk << V2_DQBLKSIZE_BITS, SEEK_SET);
+ err = write(h->qh_fd, buf, V2_DQBLKSIZE);
+ if (err < 0 && errno != ENOSPC)
+ die(2, "Can't write block (%u): %s\n", blk, strerror(errno));
+ if (err != V2_DQBLKSIZE)
+ return -ENOSPC;
+ return 0;
+}
+
+/* Get free block in file (either from free list or create new one) */
+static int get_free_dqblk(struct quota_handle *h)
+{
+ dqbuf_t buf = getdqbuf();
+ struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+ int blk;
+
+ if (info->dqi_free_blk) {
+ blk = info->dqi_free_blk;
+ read_blk(h, blk, buf);
+ info->dqi_free_blk = __le32_to_cpu(dh->dqdh_next_free);
+ }
+ else {
+ memset(buf, 0, V2_DQBLKSIZE);
+ if (write_blk(h, info->dqi_blocks, buf) < 0) { /* Assure block allocation... */
+ freedqbuf(buf);
+ fprintf(stderr, "Can't allocate new quota block (out of disk space).\n");
+ return -ENOSPC;
+ }
+ blk = info->dqi_blocks++;
+ }
+ mark_quotafile_info_dirty(h);
+ freedqbuf(buf);
+ return blk;
+}
+
+/* Put given block to free list */
+static void put_free_dqblk(struct quota_handle *h, dqbuf_t buf, uint blk)
+{
+ struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+
+ dh->dqdh_next_free = __cpu_to_le32(info->dqi_free_blk);
+ dh->dqdh_prev_free = __cpu_to_le32(0);
+ dh->dqdh_entries = __cpu_to_le16(0);
+ info->dqi_free_blk = blk;
+ mark_quotafile_info_dirty(h);
+ write_blk(h, blk, buf);
+}
+
+/* Remove given block from the list of blocks with free entries */
+static void remove_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
+{
+ dqbuf_t tmpbuf = getdqbuf();
+ struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
+ uint nextblk = __le32_to_cpu(dh->dqdh_next_free), prevblk =
+
+ __le32_to_cpu(dh->dqdh_prev_free);
+
+ if (nextblk) {
+ read_blk(h, nextblk, tmpbuf);
+ ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
+ write_blk(h, nextblk, tmpbuf);
+ }
+ if (prevblk) {
+ read_blk(h, prevblk, tmpbuf);
+ ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
+ write_blk(h, prevblk, tmpbuf);
+ }
+ else {
+ h->qh_info.u.v2_mdqi.dqi_free_entry = nextblk;
+ mark_quotafile_info_dirty(h);
+ }
+ freedqbuf(tmpbuf);
+ dh->dqdh_next_free = dh->dqdh_prev_free = __cpu_to_le32(0);
+ write_blk(h, blk, buf); /* No matter whether write succeeds block is out of list */
+}
+
+/* Insert given block to the beginning of list with free entries */
+static void insert_free_dqentry(struct quota_handle *h, dqbuf_t buf, uint blk)
+{
+ dqbuf_t tmpbuf = getdqbuf();
+ struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+
+ dh->dqdh_next_free = __cpu_to_le32(info->dqi_free_entry);
+ dh->dqdh_prev_free = __cpu_to_le32(0);
+ write_blk(h, blk, buf);
+ if (info->dqi_free_entry) {
+ read_blk(h, info->dqi_free_entry, tmpbuf);
+ ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = __cpu_to_le32(blk);
+ write_blk(h, info->dqi_free_entry, tmpbuf);
+ }
+ freedqbuf(tmpbuf);
+ info->dqi_free_entry = blk;
+ mark_quotafile_info_dirty(h);
+}
+
+/* Find space for dquot */
+static uint find_free_dqentry(struct quota_handle *h, struct dquot *dquot, int *err)
+{
+ int blk, i;
+ struct v2_disk_dqdbheader *dh;
+ struct v2_disk_dqblk *ddquot;
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+ dqbuf_t buf;
+
+ *err = 0;
+ buf = getdqbuf();
+ dh = (struct v2_disk_dqdbheader *)buf;
+ ddquot = V2_GETENTRIES(buf);
+ if (info->dqi_free_entry) {
+ blk = info->dqi_free_entry;
+ read_blk(h, blk, buf);
+ }
+ else {
+ blk = get_free_dqblk(h);
+ if (blk < 0) {
+ freedqbuf(buf);
+ *err = blk;
+ return 0;
+ }
+ memset(buf, 0, V2_DQBLKSIZE);
+ info->dqi_free_entry = blk;
+ mark_quotafile_info_dirty(h);
+ }
+ if (__le16_to_cpu(dh->dqdh_entries) + 1 >= V2_DQSTRINBLK) /* Block will be full? */
+ remove_free_dqentry(h, buf, blk);
+ dh->dqdh_entries = __cpu_to_le16(__le16_to_cpu(dh->dqdh_entries) + 1);
+ /* Find free structure in block */
+ for (i = 0; i < V2_DQSTRINBLK && !empty_dquot(ddquot + i); i++);
+ if (i == V2_DQSTRINBLK)
+ die(2, "find_free_dqentry(): Data block full but it shouldn't.\n");
+ write_blk(h, blk, buf);
+ dquot->dq_dqb.u.v2_mdqb.dqb_off =
+ (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) +
+
+ i * sizeof(struct v2_disk_dqblk);
+ freedqbuf(buf);
+ return blk;
+}
+
+/* Insert reference to structure into the trie */
+static int do_insert_tree(struct quota_handle *h, struct dquot *dquot, uint * treeblk, int depth)
+{
+ dqbuf_t buf;
+ int newson = 0, newact = 0;
+ u_int32_t *ref;
+ uint newblk;
+ int ret = 0;
+
+ buf = getdqbuf();
+ if (!*treeblk) {
+ ret = get_free_dqblk(h);
+ if (ret < 0)
+ goto out_buf;
+ *treeblk = ret;
+ memset(buf, 0, V2_DQBLKSIZE);
+ newact = 1;
+ }
+ else
+ read_blk(h, *treeblk, buf);
+ ref = (u_int32_t *) buf;
+ newblk = __le32_to_cpu(ref[V2_GETIDINDEX(dquot->dq_id, depth)]);
+ if (!newblk)
+ newson = 1;
+ if (depth == V2_DQTREEDEPTH - 1) {
+ if (newblk)
+ die(2, "Inserting already present quota entry (block %u).\n",
+ ref[V2_GETIDINDEX(dquot->dq_id, depth)]);
+ newblk = find_free_dqentry(h, dquot, &ret);
+ }
+ else
+ ret = do_insert_tree(h, dquot, &newblk, depth + 1);
+ if (newson && ret >= 0) {
+ ref[V2_GETIDINDEX(dquot->dq_id, depth)] = __cpu_to_le32(newblk);
+ write_blk(h, *treeblk, buf);
+ }
+ else if (newact && ret < 0)
+ put_free_dqblk(h, buf, *treeblk);
+ out_buf:
+ freedqbuf(buf);
+ return ret;
+}
+
+/* Wrapper for inserting quota structure into tree */
+static inline void dq_insert_tree(struct quota_handle *h, struct dquot *dquot)
+{
+ int tmp = V2_DQTREEOFF;
+
+ if (do_insert_tree(h, dquot, &tmp, 0) < 0)
+ die(2, "Can't write quota (id %u): %s\n", (uint) dquot->dq_id, strerror(errno));
+}
+
+/* Write dquot to file */
+static void v2_write_dquot(struct dquot *dquot)
+{
+ ssize_t ret;
+ struct v2_disk_dqblk ddquot;
+
+ if (!dquot->dq_dqb.u.v2_mdqb.dqb_off)
+ dq_insert_tree(dquot->dq_h, dquot);
+ lseek(dquot->dq_h->qh_fd, dquot->dq_dqb.u.v2_mdqb.dqb_off, SEEK_SET);
+ v2_mem2diskdqblk(&ddquot, &dquot->dq_dqb);
+ ddquot.dqb_id = __cpu_to_le32(dquot->dq_id);
+ ret = write(dquot->dq_h->qh_fd, (char *)&ddquot, sizeof(struct v2_disk_dqblk));
+ if (ret != sizeof(struct v2_disk_dqblk)) {
+ if (ret > 0)
+ errno = ENOSPC;
+ die(2, "Quota write failed (id %u): %s\n", (uint) dquot->dq_id, strerror(errno));
+ }
+}
+
+/* Free dquot entry in data block */
+static void free_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk)
+{
+ struct v2_disk_dqdbheader *dh;
+ dqbuf_t buf = getdqbuf();
+
+ if (dquot->dq_dqb.u.v2_mdqb.dqb_off >> V2_DQBLKSIZE_BITS != blk)
+ die(2, "Quota structure has offset to other block (%u) than it should (%u).\n", blk,
+ (uint) (dquot->dq_dqb.u.v2_mdqb.dqb_off >> V2_DQBLKSIZE_BITS));
+ read_blk(h, blk, buf);
+ dh = (struct v2_disk_dqdbheader *)buf;
+ dh->dqdh_entries = __cpu_to_le16(__le16_to_cpu(dh->dqdh_entries) - 1);
+ if (!__le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */
+ remove_free_dqentry(h, buf, blk);
+ put_free_dqblk(h, buf, blk);
+ }
+ else {
+ memset(buf + (dquot->dq_dqb.u.v2_mdqb.dqb_off & ((1 << V2_DQBLKSIZE_BITS) - 1)), 0,
+ sizeof(struct v2_disk_dqblk));
+
+ if (__le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK - 1) /* First free entry? */
+ insert_free_dqentry(h, buf, blk); /* This will also write data block */
+ else
+ write_blk(h, blk, buf);
+ }
+ dquot->dq_dqb.u.v2_mdqb.dqb_off = 0;
+ freedqbuf(buf);
+}
+
+/* Remove reference to dquot from tree */
+static void remove_tree(struct quota_handle *h, struct dquot *dquot, uint * blk, int depth)
+{
+ dqbuf_t buf = getdqbuf();
+ uint newblk;
+ u_int32_t *ref = (u_int32_t *) buf;
+
+ read_blk(h, *blk, buf);
+ newblk = __le32_to_cpu(ref[V2_GETIDINDEX(dquot->dq_id, depth)]);
+ if (depth == V2_DQTREEDEPTH - 1) {
+ free_dqentry(h, dquot, newblk);
+ newblk = 0;
+ }
+ else
+ remove_tree(h, dquot, &newblk, depth + 1);
+ if (!newblk) {
+ int i;
+
+ ref[V2_GETIDINDEX(dquot->dq_id, depth)] = __cpu_to_le32(0);
+ for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++); /* Block got empty? */
+ if (i == V2_DQBLKSIZE) {
+ put_free_dqblk(h, buf, *blk);
+ *blk = 0;
+ }
+ else
+ write_blk(h, *blk, buf);
+ }
+ freedqbuf(buf);
+}
+
+/* Delete dquot from tree */
+static void v2_delete_dquot(struct dquot *dquot)
+{
+ uint tmp = V2_DQTREEOFF;
+
+ if (!dquot->dq_dqb.u.v2_mdqb.dqb_off) /* Even not allocated? */
+ return;
+ remove_tree(dquot->dq_h, dquot, &tmp, 0);
+}
+
+/* Find entry in block */
+static loff_t find_block_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk)
+{
+ dqbuf_t buf = getdqbuf();
+ int i;
+ struct v2_disk_dqblk *ddquot = V2_GETENTRIES(buf);
+
+ read_blk(h, blk, buf);
+ if (dquot->dq_id)
+ for (i = 0; i < V2_DQSTRINBLK && __le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id;
+ i++);
+ else { /* ID 0 as a bit more complicated searching... */
+ for (i = 0; i < V2_DQSTRINBLK; i++)
+ if (!__le32_to_cpu(ddquot[i].dqb_id) && !empty_dquot(ddquot + i))
+ break;
+ }
+ if (i == V2_DQSTRINBLK)
+ die(2, "Quota for id %u referenced but not present.\n", dquot->dq_id);
+ freedqbuf(buf);
+ return (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) +
+
+ i * sizeof(struct v2_disk_dqblk);
+}
+
+/* Find entry for given id in the tree */
+static loff_t find_tree_dqentry(struct quota_handle *h, struct dquot *dquot, uint blk, int depth)
+{
+ dqbuf_t buf = getdqbuf();
+ loff_t ret = 0;
+ u_int32_t *ref = (u_int32_t *) buf;
+
+ read_blk(h, blk, buf);
+ ret = 0;
+ blk = __le32_to_cpu(ref[V2_GETIDINDEX(dquot->dq_id, depth)]);
+ if (!blk) /* No reference? */
+ goto out_buf;
+ if (depth < V2_DQTREEDEPTH - 1)
+ ret = find_tree_dqentry(h, dquot, blk, depth + 1);
+ else
+ ret = find_block_dqentry(h, dquot, blk);
+ out_buf:
+ freedqbuf(buf);
+ return ret;
+}
+
+/* Find entry for given id in the tree - wrapper function */
+static inline loff_t find_dqentry(struct quota_handle *h, struct dquot *dquot)
+{
+ return find_tree_dqentry(h, dquot, V2_DQTREEOFF, 0);
+}
+
+/*
+ * Read dquot (either from disk or from kernel)
+ * User can use errno to detect error when NULL is returned
+ */
+static struct dquot *v2_read_dquot(struct quota_handle *h, qid_t id)
+{
+ loff_t offset;
+ ssize_t ret;
+ struct v2_disk_dqblk ddquot;
+ struct dquot *dquot = get_empty_dquot();
+
+ dquot->dq_id = id;
+ dquot->dq_h = h;
+ dquot->dq_dqb.u.v2_mdqb.dqb_off = 0;
+ memset(&dquot->dq_dqb, 0, sizeof(struct util_dqblk));
+
+ if (QIO_ENABLED(h)) {
+ struct v2_kern_dqblk kdqblk;
+
+ if (quotactl(QCMD(Q_V2_GETQUOTA, h->qh_type), h->qh_quotadev, id, (void *)&kdqblk) <
+ 0) {
+ free(dquot);
+ return NULL;
+ }
+ v2_kern2utildqblk(&dquot->dq_dqb, &kdqblk);
+ return dquot;
+ }
+ offset = find_dqentry(h, dquot);
+ if (offset > 0) {
+ dquot->dq_dqb.u.v2_mdqb.dqb_off = offset;
+ lseek(h->qh_fd, offset, SEEK_SET);
+ ret = read(h->qh_fd, (char *)&ddquot, sizeof(struct v2_disk_dqblk));
+ if (ret != sizeof(struct v2_disk_dqblk)) {
+ if (ret > 0)
+ errno = EIO;
+ die(2, "Can't read quota structure for id %u: %s\n", dquot->dq_id,
+ strerror(errno));
+ }
+ v2_disk2memdqblk(&dquot->dq_dqb, &ddquot);
+ }
+ return dquot;
+}
+
+/*
+ * Commit changes of dquot to disk - it might also mean deleting it when quota became fake one and user has no blocks...
+ * User can process use 'errno' to detect error
+ */
+static int v2_commit_dquot(struct dquot *dquot)
+{
+ struct util_dqblk *b = &dquot->dq_dqb;
+
+ if (QIO_ENABLED(dquot->dq_h)) {
+ struct v2_kern_dqblk kdqblk;
+
+ v2_util2kerndqblk(&kdqblk, &dquot->dq_dqb);
+ if (quotactl
+ (QCMD(Q_V2_SETQUOTA, dquot->dq_h->qh_type), dquot->dq_h->qh_quotadev,
+ dquot->dq_id, (void *)&kdqblk) < 0)
+ return -1;
+ }
+ if (!b->dqb_curspace && !b->dqb_curinodes && !b->dqb_bsoftlimit && !b->dqb_isoftlimit
+ && !b->dqb_bhardlimit && !b->dqb_ihardlimit)
+ v2_delete_dquot(dquot);
+ else
+ v2_write_dquot(dquot);
+ return 0;
+}
+
+/*
+ * Scan all dquots in file and call callback on each
+ */
+#define set_bit(bmp, ind) ((bmp)[(ind) >> 3] |= (1 << ((ind) & 7)))
+#define get_bit(bmp, ind) ((bmp)[(ind) >> 3] & (1 << ((ind) & 7)))
+
+static int report_block(struct dquot *dquot, uint blk, char *bitmap,
+ int (*process_dquot) (struct dquot *))
+{
+ dqbuf_t buf = getdqbuf();
+ struct v2_disk_dqdbheader *dh;
+ struct v2_disk_dqblk *ddata;
+ int entries, i;
+
+ set_bit(bitmap, blk);
+ read_blk(dquot->dq_h, blk, buf);
+ dh = (struct v2_disk_dqdbheader *)buf;
+ ddata = V2_GETENTRIES(buf);
+ entries = __le16_to_cpu(dh->dqdh_entries);
+ for (i = 0; i < V2_DQSTRINBLK; i++)
+ if (!empty_dquot(ddata + i)) {
+ v2_disk2memdqblk(&dquot->dq_dqb, ddata + i);
+ dquot->dq_id = __le32_to_cpu(ddata[i].dqb_id);
+ if (process_dquot(dquot) < 0)
+ break;
+ }
+ freedqbuf(buf);
+ return entries;
+}
+
+static int report_tree(struct dquot *dquot, uint blk, int depth, char *bitmap,
+ int (*process_dquot) (struct dquot *))
+{
+ int entries = 0, i;
+ dqbuf_t buf = getdqbuf();
+ u_int32_t *ref = (u_int32_t *) buf;
+
+ read_blk(dquot->dq_h, blk, buf);
+ if (depth == V2_DQTREEDEPTH - 1) {
+ for (i = 0; i < V2_DQBLKSIZE >> 2; i++) {
+ blk = __le32_to_cpu(ref[i]);
+ if (blk && !get_bit(bitmap, blk))
+ entries += report_block(dquot, blk, bitmap, process_dquot);
+ }
+ }
+ else {
+ for (i = 0; i < V2_DQBLKSIZE >> 2; i++)
+ if ((blk = __le32_to_cpu(ref[i])))
+ entries +=
+ report_tree(dquot, blk, depth + 1, bitmap, process_dquot);
+ }
+ freedqbuf(buf);
+ return entries;
+}
+
+static uint find_set_bits(char *bmp, int blocks)
+{
+ uint i, used = 0;
+
+ for (i = 0; i < blocks; i++)
+ if (get_bit(bmp, i))
+ used++;
+ return used;
+}
+
+static int v2_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot))
+{
+ char *bitmap;
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+ struct dquot *dquot = get_empty_dquot();
+
+ if (QIO_ENABLED(h)) /* Kernel uses same file? */
+ if (quotactl(QCMD(Q_SYNC, h->qh_type), h->qh_quotadev, 0, NULL) < 0)
+ die(4, _("Can't sync quotas on device %s: %s\n"), h->qh_quotadev,
+ strerror(errno));
+ dquot->dq_h = h;
+ bitmap = smalloc((info->dqi_blocks + 7) >> 3);
+ memset(bitmap, 0, (info->dqi_blocks + 7) >> 3);
+ info->dqi_used_entries = report_tree(dquot, V2_DQTREEOFF, 0, bitmap, process_dquot);
+ info->dqi_data_blocks = find_set_bits(bitmap, info->dqi_blocks);
+ free(bitmap);
+ free(dquot);
+ return 0;
+}
+
+/* Report information about quotafile */
+static int v2_report(struct quota_handle *h, int verbose)
+{
+ struct v2_mem_dqinfo *info = &h->qh_info.u.v2_mdqi;
+
+ if (verbose)
+ printf
+ ("Statistics:\nTotal blocks: %u\nData blocks: %u\nEntries: %u\nUsed average: %f\n",
+ info->dqi_blocks, info->dqi_data_blocks, info->dqi_used_entries,
+ ((float)info->dqi_used_entries) / info->dqi_data_blocks);
+ return 0;
+}
diff --git a/quotaio_v2.h b/quotaio_v2.h
new file mode 100644
index 0000000..2657343
--- /dev/null
+++ b/quotaio_v2.h
@@ -0,0 +1,88 @@
+/*
+ *
+ * Header file for disk format of new quotafile format
+ *
+ */
+
+#ifndef _QUOTAIO_V2_H
+#define _QUOTAIO_V2_H
+
+#include <sys/types.h>
+#include "quota.h"
+
+#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
+#define V2_DQBLKSIZE_BITS 10
+#define V2_DQBLKSIZE (1 << V2_DQBLKSIZE_BITS) /* Size of block with quota structures */
+#define V2_DQTREEOFF 1 /* Offset of tree in file in blocks */
+#define V2_DQTREEDEPTH 4 /* Depth of quota tree */
+#define V2_DQSTRINBLK ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk)) /* Number of entries in one blocks */
+#define V2_GETIDINDEX(id, depth) (((id) >> ((V2_DQTREEDEPTH-(depth)-1)*8)) & 0xff)
+#define V2_GETENTRIES(buf) ((struct v2_disk_dqblk *)(((char *)(buf)) + sizeof(struct v2_disk_dqdbheader)))
+#define INIT_V2_VERSIONS { 0, 0}
+
+struct v2_disk_dqheader {
+ u_int32_t dqh_magic; /* Magic number identifying file */
+ u_int32_t dqh_version; /* File version */
+} __attribute__ ((packed));
+
+/* Flags for version specific files */
+#define V2_DQF_MASK 0x0000 /* Mask for all valid ondisk flags */
+
+/* Header with type and version specific information */
+struct v2_disk_dqinfo {
+ u_int32_t dqi_bgrace; /* Time before block soft limit becomes hard limit */
+ u_int32_t dqi_igrace; /* Time before inode soft limit becomes hard limit */
+ u_int32_t dqi_flags; /* Flags for quotafile (DQF_*) */
+ u_int32_t dqi_blocks; /* Number of blocks in file */
+ u_int32_t dqi_free_blk; /* Number of first free block in the list */
+ u_int32_t dqi_free_entry; /* Number of block with at least one free entry */
+} __attribute__ ((packed));
+
+/*
+ * Structure of header of block with quota structures. It is padded to 16 bytes so
+ * there will be space for exactly 18 quota-entries in a block
+ */
+struct v2_disk_dqdbheader {
+ u_int32_t dqdh_next_free; /* Number of next block with free entry */
+ u_int32_t dqdh_prev_free; /* Number of previous block with free entry */
+ u_int16_t dqdh_entries; /* Number of valid entries in block */
+ u_int16_t dqdh_pad1;
+ u_int32_t dqdh_pad2;
+} __attribute__ ((packed));
+
+/* Structure of quota for one user on disk */
+struct v2_disk_dqblk {
+ u_int32_t dqb_id; /* id this quota applies to */
+ u_int32_t dqb_ihardlimit; /* absolute limit on allocated inodes */
+ u_int32_t dqb_isoftlimit; /* preferred inode limit */
+ u_int32_t dqb_curinodes; /* current # allocated inodes */
+ u_int32_t dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
+ u_int32_t dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
+ u_int64_t dqb_curspace; /* current space occupied (in bytes) */
+ u_int64_t dqb_btime; /* time limit for excessive disk use */
+ u_int64_t dqb_itime; /* time limit for excessive inode use */
+} __attribute__ ((packed));
+
+/* Structure of quota for communication with kernel */
+struct v2_kern_dqblk {
+ unsigned int dqb_ihardlimit;
+ unsigned int dqb_isoftlimit;
+ unsigned int dqb_curinodes;
+ unsigned int dqb_bhardlimit;
+ unsigned int dqb_bsoftlimit;
+ qsize_t dqb_curspace;
+ time_t dqb_btime;
+ time_t dqb_itime;
+};
+
+/* Structure of quotafile info for communication with kernel */
+struct v2_kern_dqinfo {
+ unsigned int dqi_bgrace;
+ unsigned int dqi_igrace;
+ unsigned int dqi_flags;
+ unsigned int dqi_blocks;
+ unsigned int dqi_free_blk;
+ unsigned int dqi_free_entry;
+};
+
+#endif
diff --git a/quotaio_xfs.c b/quotaio_xfs.c
new file mode 100644
index 0000000..dc20f55
--- /dev/null
+++ b/quotaio_xfs.c
@@ -0,0 +1,277 @@
+/*
+ * Implementation of XFS quota manager.
+ */
+
+#ident "Copyright (c) 2001 Silicon Graphics, Inc."
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+#include "pot.h"
+#include "common.h"
+#include "bylabel.h"
+#include "quotaio.h"
+#include "quotasys.h"
+#include "dqblk_xfs.h"
+
+static int xfs_init_io(struct quota_handle *h);
+static int xfs_write_info(struct quota_handle *h);
+static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id);
+static int xfs_commit_dquot(struct dquot *dquot);
+static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot));
+static int xfs_report(struct quota_handle *h, int verbose);
+
+struct quotafile_ops quotafile_ops_xfs = {
+ xfs_init_io,
+ NULL, /* new_io */
+ NULL, /* end_io */
+ xfs_write_info,
+ xfs_read_dquot,
+ xfs_commit_dquot,
+ xfs_scan_dquots,
+ xfs_report
+};
+
+/*
+ * Convert XFS kernel quota format to utility format
+ */
+static inline void xfs_kern2utildqblk(struct util_dqblk *u, struct xfs_kern_dqblk * k)
+{
+ u->dqb_ihardlimit = k->d_ino_hardlimit;
+ u->dqb_isoftlimit = k->d_ino_softlimit;
+ u->dqb_bhardlimit = k->d_blk_hardlimit >> 1;
+ u->dqb_bsoftlimit = k->d_blk_softlimit >> 1;
+ u->dqb_curinodes = k->d_icount;
+ u->dqb_curspace = k->d_bcount << 9;
+ u->dqb_itime = k->d_itimer;
+ u->dqb_btime = k->d_btimer;
+}
+
+/*
+ * Convert utility quota format to XFS kernel format
+ */
+static inline void xfs_util2kerndqblk(struct xfs_kern_dqblk *k, struct util_dqblk *u)
+{
+ memset(k, 0, sizeof(struct xfs_kern_dqblk));
+ k->d_ino_hardlimit = u->dqb_ihardlimit;
+ k->d_ino_softlimit = u->dqb_isoftlimit;
+ k->d_blk_hardlimit = u->dqb_bhardlimit << 1;
+ k->d_blk_softlimit = u->dqb_bsoftlimit << 1;
+ k->d_icount = u->dqb_curinodes;
+ k->d_bcount = u->dqb_curspace >> 9;
+ k->d_itimer = u->dqb_itime;
+ k->d_btimer = u->dqb_btime;
+}
+
+/*
+ * Initialize quota information
+ */
+static int xfs_init_io(struct quota_handle *h)
+{
+ struct xfs_mem_dqinfo info;
+ int qcmd;
+
+ qcmd = QCMD(Q_XFS_GETQSTAT, 0);
+ memset(&info, 0, sizeof(struct xfs_mem_dqinfo));
+ if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&info) < 0)
+ return -1;
+ h->qh_info.dqi_bgrace = info.qs_btimelimit;
+ h->qh_info.dqi_igrace = info.qs_itimelimit;
+ h->qh_info.u.xfs_mdqi = info;
+ return 0;
+}
+
+/*
+ * Write information (grace times)
+ */
+static int xfs_write_info(struct quota_handle *h)
+{
+ struct xfs_kern_dqblk xdqblk;
+ int qcmd;
+
+ memset(&xdqblk, 0, sizeof(struct xfs_kern_dqblk));
+
+ xdqblk.d_btimer = h->qh_info.dqi_bgrace;
+ xdqblk.d_itimer = h->qh_info.dqi_igrace;
+ xdqblk.d_fieldmask |= FS_DQ_TIMER_MASK;
+ qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type);
+ if (quotactl(qcmd, h->qh_quotadev, 0, (void *)&xdqblk) < 0)
+ return -1;
+ return 0;
+}
+
+/*
+ * Read a dqblk struct from the quota manager
+ */
+static struct dquot *xfs_read_dquot(struct quota_handle *h, qid_t id)
+{
+ struct dquot *dquot = get_empty_dquot();
+ struct xfs_kern_dqblk xdqblk;
+ int qcmd;
+
+ dquot->dq_id = id;
+ dquot->dq_h = h;
+ qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type);
+ if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) {
+ ;
+ }
+ else {
+ xfs_kern2utildqblk(&dquot->dq_dqb, &xdqblk);
+ return dquot;
+ }
+ free(dquot);
+ return NULL;
+}
+
+/*
+ * Write a dqblk struct to the XFS quota manager
+ */
+static int xfs_commit_dquot(struct dquot *dquot)
+{
+ struct quota_handle *h = dquot->dq_h;
+ struct xfs_kern_dqblk xdqblk;
+ qid_t id = dquot->dq_id;
+ int qcmd;
+
+ xfs_util2kerndqblk(&xdqblk, &dquot->dq_dqb);
+ xdqblk.d_fieldmask |= FS_DQ_LIMIT_MASK;
+ qcmd = QCMD(Q_XFS_SETQLIM, h->qh_type);
+ if (quotactl(qcmd, h->qh_quotadev, id, (void *)&xdqblk) < 0) {
+ ;
+ }
+ else {
+ return 0;
+ }
+ return -1;
+}
+
+/*
+ * xfs_scan_dquots helper - processes a single dquot
+ */
+static int xfs_scan_dquot(struct quota_handle *h,
+ struct xfs_kern_dqblk *d,
+ struct dquot *dq, int (*process_dquot) (struct dquot * dquot))
+{
+ int qcmd = QCMD(Q_XFS_GETQUOTA, h->qh_type);
+
+ memset(d, 0, sizeof(struct xfs_kern_dqblk));
+
+ if (quotactl(qcmd, h->qh_quotadev, dq->dq_id, (void *)d) < 0) {
+ return 0;
+ }
+ if (d->d_blk_hardlimit == 0 &&
+ d->d_blk_softlimit == 0 &&
+ d->d_ino_hardlimit == 0 &&
+ d->d_ino_softlimit == 0 && d->d_bcount == 0 && d->d_icount == 0) return 0;
+ xfs_kern2utildqblk(&dq->dq_dqb, d);
+ return process_dquot(dq);
+}
+
+/*
+ * Scan all known dquots and call callback on each
+ */
+static int xfs_scan_dquots(struct quota_handle *h, int (*process_dquot) (struct dquot * dquot))
+{
+ struct dquot *dq;
+ struct xfs_kern_dqblk d;
+ int rd = 0;
+
+ dq = get_empty_dquot();
+ dq->dq_h = h;
+ if (h->qh_type == USRQUOTA) {
+ struct passwd *usr;
+
+ setpwent();
+ while ((usr = getpwent()) != NULL) {
+ dq->dq_id = usr->pw_uid;
+ if ((rd = xfs_scan_dquot(h, &d, dq, process_dquot)) < 0)
+ break;
+ }
+ endpwent();
+ }
+ else { /* GRPQUOTA */
+ struct group *grp;
+
+ setgrent();
+ while ((grp = getgrent()) != NULL) {
+ dq->dq_id = grp->gr_gid;
+ if ((rd = xfs_scan_dquot(h, &d, dq, process_dquot)) < 0)
+ break;
+ }
+ endgrent();
+ }
+
+ free(dq);
+ return rd;
+}
+
+/*
+ * Report information about XFS quota on given filesystem
+ */
+static int xfs_report(struct quota_handle *h, int verbose)
+{
+ u_int16_t sbflags;
+ struct xfs_mem_dqinfo *info = &h->qh_info.u.xfs_mdqi;
+
+ if (!verbose)
+ return 0;
+
+ /* quotaon/off flags */
+ printf(_("*** Status for %s quotas on device %s\n"), type2name(h->qh_type), h->qh_quotadev);
+
+#define XQM_ON(flag) ((info->qs_flags & (flag)) ? _("ON") : _("OFF"))
+ if (h->qh_type == USRQUOTA) {
+ printf(_("Accounting: %s Enforcement: %s\n"),
+ XQM_ON(XFS_QUOTA_UDQ_ACCT), XQM_ON(XFS_QUOTA_UDQ_ENFD));
+ }
+ else { /* qh_type == USRQUOTA */
+ printf(_("Accounting: %s Enforcement: %s\n"),
+ XQM_ON(XFS_QUOTA_GDQ_ACCT), XQM_ON(XFS_QUOTA_GDQ_ENFD));
+ }
+#undef XQM_ON
+
+ /*
+ * If this is the root file system, it is possible that quotas are
+ * on ondisk, but not incore. Those flags will be in the HI 8 bits.
+ */
+#define XQM_ONDISK(flag) ((sbflags & (flag)) ? _("ON") : _("OFF"))
+ if ((sbflags = (info->qs_flags & 0xff00) >> 8) != 0) {
+ if (h->qh_type == USRQUOTA) {
+ printf(_("Accounting [ondisk]: %s "
+ "Enforcement [ondisk]: %s\n"),
+ XQM_ONDISK(XFS_QUOTA_UDQ_ACCT), XQM_ONDISK(XFS_QUOTA_UDQ_ENFD));
+ }
+ else { /* qh_type == USRQUOTA */
+ printf(_("Accounting [ondisk]: %s "
+ "Enforcement [ondisk]: %s\n"),
+ XQM_ONDISK(XFS_QUOTA_GDQ_ACCT), XQM_ONDISK(XFS_QUOTA_GDQ_ENFD));
+ }
+#undef XQM_ONDISK
+ }
+
+ /* user and group quota file status information */
+ if (h->qh_type == USRQUOTA) {
+ if (info->qs_uquota.qfs_ino == -1 || info->qs_uquota.qfs_ino == 0)
+ printf(_("Inode: none\n"));
+ else
+ printf(_("Inode: #%Lu (%Lu blocks, %u extents)\n"),
+ (unsigned long long)info->qs_uquota.qfs_ino,
+ (unsigned long long)info->qs_uquota.qfs_nblks,
+ info->qs_uquota.qfs_nextents);
+ }
+ else { /* qh_type == GRPQUOTA */
+ if (info->qs_gquota.qfs_ino == -1)
+ printf(_("Inode: none\n"));
+ else
+ printf(_("Inode: #%Lu (%Lu blocks, %u extents)\n"),
+ (unsigned long long)info->qs_gquota.qfs_ino,
+ (unsigned long long)info->qs_gquota.qfs_nblks,
+ info->qs_gquota.qfs_nextents);
+ }
+ return 0;
+}
diff --git a/quotaio_xfs.h b/quotaio_xfs.h
new file mode 100644
index 0000000..e854452
--- /dev/null
+++ b/quotaio_xfs.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2000 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 _QUOTAIO_XFS_H
+#define _QUOTAIO_XFS_H
+
+#include <linux/types.h>
+
+#define XQM_CMD(cmd) ( ('X'<<8)+(cmd) )
+#define IS_XQM_CMD(cmd) ( ((int)(cmd)>>8) == 'X' )
+
+/*
+ * Disk quota - quotactl(2) commands for XFS Quota Manager (XQM).
+ */
+#define Q_XQUOTAON XQM_CMD(0x1) /* enable quota accounting/enforcement */
+#define Q_XQUOTAOFF XQM_CMD(0x2) /* disable quota accounting/enforcement */
+#define Q_XGETQUOTA XQM_CMD(0x3) /* get disk limits & usage */
+#define Q_XSETQLIM XQM_CMD(0x4) /* set disk limits only */
+#define Q_XGETQSTAT XQM_CMD(0x5) /* returns fs_quota_stat_t struct */
+#define Q_XQUOTARM XQM_CMD(0x6) /* free quota files' space */
+
+/*
+ * fs_disk_quota structure:
+ *
+ * This contains the current quota information regarding a user/proj/group.
+ * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of
+ * 512 bytes.
+ */
+#define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */
+typedef struct fs_disk_quota {
+ __s8 d_version; /* version of this structure */
+ __s8 d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */
+ __u16 d_fieldmask; /* field specifier */
+ __u32 d_id; /* user, project, or group ID */
+ __u64 d_blk_hardlimit; /* absolute limit on disk blks */
+ __u64 d_blk_softlimit; /* preferred limit on disk blks */
+ __u64 d_ino_hardlimit; /* maximum # allocated inodes */
+ __u64 d_ino_softlimit; /* preferred inode limit */
+ __u64 d_bcount; /* # disk blocks owned by the user */
+ __u64 d_icount; /* # inodes owned by the user */
+ __s32 d_itimer; /* zero if within inode limits */
+ /* if not, we refuse service */
+ __s32 d_btimer; /* similar to above; for disk blocks */
+ __u16 d_iwarns; /* # warnings issued wrt num inodes */
+ __u16 d_bwarns; /* # warnings issued wrt disk blocks */
+ __s32 d_padding2; /* padding2 - for future use */
+ __u64 d_rtb_hardlimit; /* absolute limit on realtime blks */
+ __u64 d_rtb_softlimit; /* preferred limit on RT disk blks */
+ __u64 d_rtbcount; /* # realtime blocks owned */
+ __s32 d_rtbtimer; /* similar to above; for RT disk blks */
+ __u16 d_rtbwarns; /* # warnings issued wrt RT disk blks */
+ __s16 d_padding3; /* padding3 - for future use */
+ char d_padding4[8]; /* yet more padding */
+} fs_disk_quota_t;
+
+/*
+ * These fields are sent to Q_XSETQLIM to specify fields that need to change.
+ */
+#define FS_DQ_ISOFT (1<<0)
+#define FS_DQ_IHARD (1<<1)
+#define FS_DQ_BSOFT (1<<2)
+#define FS_DQ_BHARD (1<<3)
+#define FS_DQ_RTBSOFT (1<<4)
+#define FS_DQ_RTBHARD (1<<5)
+#define FS_DQ_LIMIT_MASK (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \
+ FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD)
+/*
+ * These timers can only be set in super user's dquot. For others, timers are
+ * automatically started and stopped. Superusers timer values set the limits
+ * for the rest. In case these values are zero, the DQ_{F,B}TIMELIMIT values
+ * defined below are used.
+ * These values also apply only to the d_fieldmask field for Q_XSETQLIM.
+ */
+#define FS_DQ_BTIMER (1<<6)
+#define FS_DQ_ITIMER (1<<7)
+#define FS_DQ_RTBTIMER (1<<8)
+#define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER)
+
+/*
+ * The following constants define the default amount of time given a user
+ * before the soft limits are treated as hard limits (usually resulting
+ * in an allocation failure). These may be modified by the quotactl(2)
+ * system call with the Q_XSETQLIM command.
+ */
+#define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */
+#define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */
+
+/*
+ * Various flags related to quotactl(2). Only relevant to XFS filesystems.
+ */
+#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */
+#define XFS_QUOTA_UDQ_ENFD (1<<1) /* user quota limits enforcement */
+#define XFS_QUOTA_GDQ_ACCT (1<<2) /* group quota accounting */
+#define XFS_QUOTA_GDQ_ENFD (1<<3) /* group quota limits enforcement */
+
+#define XFS_USER_QUOTA (1<<0) /* user quota type */
+#define XFS_PROJ_QUOTA (1<<1) /* (IRIX) project quota type */
+#define XFS_GROUP_QUOTA (1<<2) /* group quota type */
+
+/*
+ * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system.
+ * Provides a centralized way to get meta infomation about the quota subsystem.
+ * eg. space taken up for user and group quotas, number of dquots currently
+ * incore.
+ */
+#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */
+
+/*
+ * Some basic infomation about 'quota files'.
+ */
+typedef struct fs_qfilestat {
+ __u64 qfs_ino; /* inode number */
+ __u64 qfs_nblks; /* number of BBs 512-byte-blks */
+ __u32 qfs_nextents; /* number of extents */
+} fs_qfilestat_t;
+
+typedef struct fs_quota_stat {
+ __s8 qs_version; /* version number for future changes */
+ __u16 qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
+ __s8 qs_pad; /* unused */
+ fs_qfilestat_t qs_uquota; /* user quota storage information */
+ fs_qfilestat_t qs_gquota; /* group quota storage information */
+ __u32 qs_incoredqs; /* number of dquots incore */
+ __s32 qs_btimelimit; /* limit for blks timer */
+ __s32 qs_itimelimit; /* limit for inodes timer */
+ __s32 qs_rtbtimelimit; /* limit for rt blks timer */
+ __u16 qs_bwarnlimit; /* limit for num warnings */
+ __u16 qs_iwarnlimit; /* limit for num warnings */
+} fs_quota_stat_t;
+
+#endif /* _QUOTAIO_XFS_H */
diff --git a/quotaon.8 b/quotaon.8
new file mode 100644
index 0000000..c243763
--- /dev/null
+++ b/quotaon.8
@@ -0,0 +1,168 @@
+.TH QUOTAON 8
+.UC 4
+.SH NAME
+quotaon, quotaoff \- turn filesystem quotas on and off
+.SH SYNOPSIS
+.B /usr/sbin/quotaon
+[
+.B \-vug
+]
+.IR filesystem .\|.\|.
+.br
+.B /usr/sbin/quotaon
+[
+.B \-avug
+]
+.LP
+.B /usr/sbin/quotaoff
+[
+.B \-vugdo
+]
+[
+.B \-x
+.I state
+]
+.IR filesystem .\|.\|.
+.br
+.B /usr/sbin/quotaoff
+[
+.B \-avugdo
+]
+.SH DESCRIPTION
+.SS quotaon
+.IX "quotaon command" "" "\fLquotaon\fP \(em turn filesystem quotas on"
+.IX "user quotas" "quotaon command" "" "\fLquotaon\fP \(em turn filesystem quotas on"
+.IX "disk quotas" "quotaon command" "" "\fLquotaon\fP \(em turn filesystem quotas on"
+.IX "quotas" "quotaon command" "" "\fLquotaon\fP \(em turn filesystem quotas on"
+.IX "filesystem" "quotaon command" "" "\fLquotaon\fP \(em turn filesystem quotas on"
+.LP
+.B quotaon
+announces to the system that disk quotas should be enabled on one or
+more filesystems. The filesystem quota files must be present in the root
+directory of the specified filesystem and be named either
+.IR aquota.user
+(for version 2 user quota),
+.IR quota.user
+(for version 1 user quota),
+.IR aquota.group
+(for version 2 group quota), or
+.IR quota.group
+(for version 1 group quota).
+.PP
+XFS filesystems are a special case - XFS considers quota
+information as filesystem metadata and uses journaling to provide
+a higher level guarantee of consistency.
+There are two components to the XFS disk quota system:
+accounting and limit enforcement.
+Except in the case of the root filesystem, XFS filesystems require
+that quota accounting be turned on at mount time.
+It is possible to enable and disable limit enforcement on any XFS
+filesystem after quota accounting is already turned on.
+The default is to turn on both accounting and enforcement.
+.PP
+The XFS quota implementation does not maintain quota information in
+user-visible files, but rather stores this information internally.
+.SS quotaoff
+.IX "quotaoff command" "" "\fLquotaoff\fP \(em turn filesystem quotas off"
+.IX "user quotas" "quotaoff command" "" "\fLquotaoff\fP \(em turn filesystem quotas off"
+.IX "disk quotas" "quotaoff command" "" "\fLquotaoff\fP \(em turn filesystem quotas off"
+.IX "quotas" "quotaoff command" "" "\fLquotaoff\fP \(em turn filesystem quotas off"
+.IX "filesystem" "quotaoff command" "" "\fLquotaoff\fP \(em turn filesystem quotas off"
+.LP
+.B quotaoff
+announces to the system that the specified filesystems should
+have any disk quotas turned off.
+.SH OPTIONS
+.SS quotaon
+.TP
+.B \-a
+All filesystems in
+.B /etc/fstab
+marked read-write with quotas will have their quotas turned on.
+This is normally used at boot time to enable quotas.
+.TP
+.B \-v
+Display a message for each filesystem where quotas are turned on.
+.TP
+.B \-u
+Manipulate user quotas. This is the default.
+.TP
+.B \-g
+Manipulate group quotas.
+.SS quotaoff
+.TP
+.B \-a
+Force all filesystems in
+.B /etc/fstab
+to have their quotas disabled.
+.TP
+.B \-v
+Display a message for each filesystem affected.
+.TP
+.B \-u
+Manipulate user quotas. This is the default.
+.TP
+.B \-g
+Manipulate group quotas.
+.TP
+.B \-x delete
+Free up the space used to hold quota information (maintained
+internally) within XFS.
+This option is only applicable to XFS, and is silently
+ignored for other filesystem types.
+It can only be used on a filesystem with quota previously turned off.
+.TP
+.B \-x enforce
+Switch off limit enforcement for XFS filesystems (perform
+quota accounting only).
+This option is only applicable to XFS, and is silently
+ignored for other filesystem types.
+.LP
+.SH "XFS EXAMPLES"
+.TP 0
+.B "Turning on quotas on a non-root XFS filesystem"
+Use
+.IR mount (8)
+or
+.B /etc/fstab
+option quota to enable both accounting and limit enforcement.
+.B quotaon
+utility cannot be used for this purpose.
+.TP
+.B "Turning on quotas on an XFS root filesystem"
+Use
+.BR "quotaon -v /" ,
+and
+.IR reboot (8).
+This procedure will enable both accounting and limit enforcement.
+.TP
+.B "Turning off quota limit enforcement on any XFS filesystem"
+Make sure that quota accounting and enforcement are both turned on using
+.BR "repquota -s" .
+Use
+.B "quotaoff -vo"
+to disable limit enforcement.
+This may be done while the filesystem is mounted.
+.TP
+.BR "Turning on quota limit enforcement on any XFS filesystem"
+Make sure that quota accounting is turned on using
+.BR "repquota -s" .
+Use
+.BR "quotaon -v" .
+This may be done while the filesystem is mounted.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/fstab
+default filesystems
+.PD
+.SH "SEE ALSO"
+.BR quotactl (2),
+.BR fstab (5),
+.BR repquota (8).
diff --git a/quotaon.c b/quotaon.c
new file mode 100644
index 0000000..6e8d17b
--- /dev/null
+++ b/quotaon.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California. All
+ * rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Robert Elz at
+ * The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California $"
+#ident "$Copyright: All rights reserved. $"
+#ident "$Id: quotaon.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $"
+
+/*
+ * Turn quota on/off for a filesystem.
+ */
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "quotaon.h"
+
+int aflag; /* all file systems */
+int gflag; /* operate on group quotas */
+int uflag; /* operate on user quotas */
+int vflag; /* verbose */
+int kqf; /* kernel quota format */
+
+static void usage(char *whoami)
+{
+ fprintf(stderr, _("Usage:\n\t%s [-guv] [-x state] -a\n"), whoami);
+ fprintf(stderr, _("\t%s [-guv] [-x state] filesys ...\n"), whoami);
+ exit(1);
+}
+
+/*
+ * Check to see if target appears in list of size cnt.
+ */
+static int oneof(char *target, char *list[], int cnt)
+{
+ int i;
+
+ for (i = 0; i < cnt; i++)
+ if (strcmp(target, list[i]) == 0)
+ return (i);
+ return (-1);
+}
+
+/*
+ * For both VFS quota formats, need to pass in the quota file;
+ * for XFS quota manager, pass on the -x command line option.
+ */
+static int newstate(struct mntent *mnt, int offmode, int type, char *extra)
+{
+ int flags, ret;
+ newstate_t *statefunc;
+ const char *mnt_fsname = get_device_name(mnt->mnt_fsname);
+
+ if (!mnt_fsname)
+ return -1;
+ flags = offmode ? STATEFLAG_OFF : STATEFLAG_ON;
+ if (vflag > 1)
+ flags |= STATEFLAG_VERYVERBOSE;
+ else if (vflag)
+ flags |= STATEFLAG_VERBOSE;
+ if (aflag)
+ flags |= STATEFLAG_ALL;
+
+ if (kqf & (1 << QF_XFS) &&
+ ((offmode
+ && (kern_quota_on(mnt_fsname, USRQUOTA, 1 << QF_XFS)
+ || kern_quota_on(mnt_fsname, GRPQUOTA, 1 << QF_XFS)))
+ || (!offmode && kern_quota_on(mnt_fsname, type, 1 << QF_XFS))))
+ ret = xfs_newstate(mnt, type, extra, flags);
+ else {
+ extra = get_qf_name(mnt, type, kqf);
+ statefunc = (kqf & (1 << QF_VFSV0)) ? v1_newstate : v2_newstate;
+ ret = statefunc(mnt, type, extra, flags);
+ free(extra);
+ }
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *fp;
+ struct mntent *mnt;
+ long argnum, done = 0;
+ char *whoami, *xarg = NULL;
+ int c, offmode = 0, errs = 0;
+
+ gettexton();
+
+ whoami = basename(argv[0]);
+ if (strcmp(whoami, "quotaoff") == 0)
+ offmode++;
+ else if (strcmp(whoami, "quotaon") != 0)
+ die(1, _("Name must be quotaon or quotaoff not %s\n"), whoami);
+
+ while ((c = getopt(argc, argv, "afvugx:V")) != EOF) {
+ switch (c) {
+ case 'a':
+ aflag++;
+ break;
+ case 'f':
+ offmode++;
+ break;
+ case 'g':
+ gflag++;
+ break;
+ case 'u':
+ uflag++;
+ break;
+ case 'v':
+ vflag++;
+ break;
+ case 'x':
+ xarg = optarg;
+ break;
+ case 'V':
+ version();
+ exit(0);
+ default:
+ usage(whoami);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc <= 0 && !aflag)
+ usage(whoami);
+ if (!gflag && !uflag) {
+ gflag++;
+ uflag++;
+ }
+
+ kqf = kern_quota_format();
+
+ fp = setmntent(MNTTAB, "r");
+ while ((mnt = getmntent(fp))) {
+ if (aflag) {
+ if (hasmntopt(mnt, MNTOPT_NOAUTO))
+ continue;
+ }
+ else {
+ if ((argnum = oneof(mnt->mnt_dir, argv, argc)) >= 0 ||
+ (argnum = oneof(mnt->mnt_fsname, argv, argc)) >= 0)
+ done |= 1 << argnum;
+ else
+ continue;
+ }
+
+ if (gflag)
+ errs += newstate(mnt, offmode, GRPQUOTA, xarg);
+ if (uflag)
+ errs += newstate(mnt, offmode, USRQUOTA, xarg);
+ }
+ endmntent(fp);
+
+ for (c = 0; c < argc; c++)
+ if ((done & (1 << c)) == 0)
+ fprintf(stderr, _("%s not found in fstab\n"), argv[c]);
+ return errs;
+}
+
+/*
+ * Enable/disable VFS quota on given filesystem
+ */
+static int quotaonoff(char *quotadev, char *quotafile, int type, int flags)
+{
+ int qcmd;
+
+ if (flags & STATEFLAG_OFF) {
+ qcmd = QCMD(Q_QUOTAOFF, type);
+ if (quotactl(qcmd, quotadev, 0, (void *)0) < 0) {
+ fprintf(stderr, "quotaoff: ");
+ perror(quotadev);
+ return 1;
+ }
+ if (flags & STATEFLAG_VERBOSE)
+ printf(_("%s: %s quotas turned off\n"), quotadev, type2name(type));
+ return 0;
+ }
+ qcmd = QCMD(Q_QUOTAON, type);
+ if (quotactl(qcmd, quotadev, 0, (void *)quotafile) < 0) {
+ fprintf(stderr, _("quotaon: using %s on "), quotafile);
+ perror(quotadev);
+ return 1;
+ }
+ if (flags & STATEFLAG_VERBOSE)
+ printf(_("%s: %s quotas turned on\n"), quotadev, type2name(type));
+ return 0;
+}
+
+/*
+ * Enable/disable rsquash on given filesystem
+ */
+static int quotarsquashonoff(const char *quotadev, int type, int flags)
+{
+#if defined(MNTOPT_RSQUASH)
+ int mode = (flags & STATEFLAG_OFF) ? 0 : 1;
+ int qcmd = QCMD(Q_V1_RSQUASH, type);
+
+ if (quotactl(qcmd, quotadev, 0, (void *)&mode) < 0) {
+ fprintf(stderr, _("quotaon: set root_squash on"));
+ perror(quotadev);
+ return 1;
+ }
+ if ((flags & STATEFLAG_VERBOSE) && (flags & STATEFLAG_OFF))
+ printf(_("%s: %s root_squash turned off\n"), quotadev, type2name(type));
+ else if ((flags & STATEFLAG_VERBOSE) && (flags & STATEFLAG_ON))
+ printf(_("%s: %s root_squash turned on\n"), quotadev, type2name(type));
+#endif
+ return 0;
+}
+
+/*
+ * Enable/disable quota/rootsquash on given filesystem (version 1)
+ */
+int v1_newstate(struct mntent *mnt, int type, char *file, int flags)
+{
+ int errs = 0;
+ const char *dev = get_device_name(mnt->mnt_fsname);
+
+ if (!dev)
+ return 1;
+ if ((flags & STATEFLAG_OFF) && hasmntopt(mnt, MNTOPT_RSQUASH))
+ errs += quotarsquashonoff(dev, type, flags);
+ if (hasquota(mnt, type))
+ errs += quotaonoff((char *)dev, file, type, flags);
+ if ((flags & STATEFLAG_ON) && hasmntopt(mnt, MNTOPT_RSQUASH))
+ errs += quotarsquashonoff(dev, type, flags);
+ free((char *)dev);
+ return errs;
+}
+
+/*
+ * Enable/disable quota on given filesystem (version 2 quota)
+ */
+int v2_newstate(struct mntent *mnt, int type, char *file, int flags)
+{
+ const char *dev = get_device_name(mnt->mnt_fsname);
+ int err = 1;
+
+ if (!dev)
+ return err;
+ if (hasquota(mnt, type))
+ err = quotaonoff((char *)dev, file, type, flags);
+ free((char *)dev);
+ return err;
+}
diff --git a/quotaon.h b/quotaon.h
new file mode 100644
index 0000000..ced9b2a
--- /dev/null
+++ b/quotaon.h
@@ -0,0 +1,22 @@
+/*
+ * Common types, macros, and routines for enabling/disabling
+ * quota for each of the various Linux quota formats.
+ */
+
+#include "pot.h"
+#include "quota.h"
+#include "quotasys.h"
+#include "bylabel.h"
+#include "common.h"
+#include "quotaio.h"
+
+#define STATEFLAG_ON 0x01
+#define STATEFLAG_OFF 0x02
+#define STATEFLAG_ALL 0x04
+#define STATEFLAG_VERBOSE 0x08
+#define STATEFLAG_VERYVERBOSE 0x10
+
+typedef int (newstate_t) (struct mntent * mnt, int type, char *file, int flags);
+extern int v1_newstate(struct mntent *mnt, int type, char *file, int flags);
+extern int v2_newstate(struct mntent *mnt, int type, char *file, int flags);
+extern int xfs_newstate(struct mntent *mnt, int type, char *file, int flags);
diff --git a/quotaon_xfs.c b/quotaon_xfs.c
new file mode 100644
index 0000000..a3c0480
--- /dev/null
+++ b/quotaon_xfs.c
@@ -0,0 +1,206 @@
+/*
+ * State changes for the XFS Quota Manager.
+ */
+
+#ident "Copyright (c) 2001 Silicon Graphics, Inc."
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "quotaon.h"
+#include "dqblk_xfs.h"
+
+#define QOFF 1
+#define ACCT 2
+#define ENFD 3
+
+/*
+ * Ensure we don't attempt to go into a dodgey state.
+ */
+
+static int xfs_state_check(int qcmd, int type, int flags, char *dev, int root, int *xopts)
+{
+ struct xfs_mem_dqinfo info;
+ int state;
+
+ /* we never want to operate via -a in XFS quota */
+ if (flags & STATEFLAG_ALL)
+ return 0; /* noop */
+
+ if (quotactl(QCMD(Q_XFS_GETQSTAT, 0), dev, 0, (void *)&info) < 0) {
+ fprintf(stderr, flags & STATEFLAG_ON ? "quotaon: " : "quotaoff: ");
+ perror(dev);
+ return -1;
+ }
+
+ /* establish current state before any transition */
+ state = QOFF;
+ if (type == USRQUOTA) {
+ if (info.qs_flags & XFS_QUOTA_UDQ_ACCT)
+ state = ACCT;
+ if (info.qs_flags & XFS_QUOTA_UDQ_ENFD)
+ state = ENFD;
+ }
+ else { /* GRPQUOTA */
+ if (info.qs_flags & XFS_QUOTA_GDQ_ACCT)
+ state = ACCT;
+ if (info.qs_flags & XFS_QUOTA_GDQ_ENFD)
+ state = ENFD;
+ }
+
+ switch (state) {
+ case QOFF:
+ switch (qcmd) {
+ case Q_XFS_QUOTARM:
+ return 1;
+ case Q_XFS_QUOTAON:
+ if (root) {
+ *xopts |= (type == USRQUOTA) ?
+ XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
+ printf(_("Enabling %s quota on root filesystem"
+ " (reboot to take effect)\n"), type2name(type));
+ return 1;
+ }
+ fprintf(stderr, _("Enable XFS %s quota during mount\n"),
+ type2name(type));
+ return -1;
+ case Q_XFS_QUOTAOFF:
+ return 0; /* noop */
+ }
+ break;
+ case ACCT:
+ switch (qcmd) {
+ case Q_XFS_QUOTARM:
+ fprintf(stderr, _("Cannot delete %s quota on %s - "
+ "switch quota accounting off first\n"),
+ type2name(type), dev);
+ return -1;
+ case Q_XFS_QUOTAON:
+ if (root) {
+ *xopts |= (type == USRQUOTA) ?
+ XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
+ printf(_("Enabling %s quota on root filesystem"
+ " (reboot to take effect)\n"), type2name(type));
+ return 1;
+ }
+ printf(_("Enabling %s quota accounting on %s\n"), type2name(type), dev);
+ *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
+ return 1;
+ case Q_XFS_QUOTAOFF:
+ printf(_("Disabling %s quota accounting on %s\n"),
+ type2name(type), dev);
+ *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
+ return 1;
+ }
+ break;
+
+ case ENFD:
+ switch (qcmd) {
+ case Q_XFS_QUOTARM:
+ fprintf(stderr, _("Cannot delete %s quota on %s - "
+ "switch quota enforcement off first\n"),
+ type2name(type), dev);
+ return -1;
+ case Q_XFS_QUOTAON:
+ fprintf(stderr, _("Enforcing %s quota already on %s\n"),
+ type2name(type), dev);
+ return -1;
+ case Q_XFS_QUOTAOFF:
+ printf(_("Disabling %s quota enforcement on %s\n"),
+ type2name(type), dev);
+ *xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ENFD : XFS_QUOTA_GDQ_ENFD;
+ return 1;
+ }
+ break;
+ }
+ fprintf(stderr, _("Unexpected XFS quota state sought on %s\n"), dev);
+ return -1;
+}
+
+static int xfs_onoff(char *dev, int type, int flags, int rootfs, int *xopts)
+{
+ int qoff, qcmd;
+
+ qoff = (flags & STATEFLAG_OFF);
+ qcmd = qoff ? Q_XFS_QUOTAOFF : Q_XFS_QUOTAON;
+ if (xfs_state_check(qcmd, type, flags, dev, rootfs, xopts) < 0)
+ return 1;
+
+ if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) {
+ fprintf(stderr, qoff ? "quotaoff: " : "quotaon: ");
+ perror(dev);
+ return 1;
+ }
+ if ((flags & STATEFLAG_VERBOSE) && qoff)
+ printf(_("%s: %s quotas turned off\n"), dev, type2name(type));
+ else if ((flags & STATEFLAG_VERBOSE) && !qoff)
+ printf(_("%s: %s quotas turned on\n"), dev, type2name(type));
+ return 0;
+}
+
+static int xfs_delete(char *dev, int type, int flags, int rootfs, int *xopts)
+{
+ int qcmd, check;
+
+ qcmd = Q_XFS_QUOTARM;
+ check = xfs_state_check(qcmd, type, flags, dev, rootfs, xopts);
+ if (check != 1)
+ return (check < 0);
+
+ if (quotactl(QCMD(qcmd, type), dev, 0, (void *)xopts) < 0) {
+ fprintf(stderr, _("Failed to delete quota: "));
+ perror(dev);
+ return 1;
+ }
+
+ if (flags & STATEFLAG_VERBOSE)
+ printf(_("%s: deleted %s quota blocks\n"), dev, type2name(type));
+ return 0;
+}
+
+/*
+ * Change state for given filesystem - on/off, acct/enfd, & delete.
+ * Must consider existing state and also whether or not this is the
+ * root filesystem.
+ * We are passed in the new requested state through "type" & "xarg".
+ */
+int xfs_newstate(struct mntent *mnt, int type, char *xarg, int flags)
+{
+ int err = 1;
+ int xopts = 0;
+ int rootfs = !strcmp(mnt->mnt_dir, "/");
+ const char *dev = get_device_name(mnt->mnt_fsname);
+
+ if (!dev)
+ return err;
+
+ if (xarg == NULL) { /* both acct & enfd on/off */
+ xopts |= (type == USRQUOTA) ?
+ (XFS_QUOTA_UDQ_ACCT | XFS_QUOTA_UDQ_ENFD) :
+ (XFS_QUOTA_GDQ_ACCT | XFS_QUOTA_GDQ_ENFD);
+ err = xfs_onoff((char *)dev, type, flags, rootfs, &xopts);
+ }
+ else if (strcmp(xarg, "account") == 0) {
+ /* only useful if we want root accounting only */
+ if (!rootfs || !(flags & STATEFLAG_ON))
+ goto done;
+ xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ACCT : XFS_QUOTA_GDQ_ACCT;
+ err = xfs_onoff((char *)dev, type, flags, rootfs, &xopts);
+ }
+ else if (strcmp(xarg, "enforce") == 0) {
+ xopts |= (type == USRQUOTA) ? XFS_QUOTA_UDQ_ENFD : XFS_QUOTA_GDQ_ENFD;
+ err = xfs_onoff((char *)dev, type, flags, rootfs, &xopts);
+ }
+ else if (strcmp(xarg, "delete") == 0) {
+ xopts |= (type == USRQUOTA) ? XFS_USER_QUOTA : XFS_GROUP_QUOTA;
+ err = xfs_delete((char *)dev, type, flags, rootfs, &xopts);
+ }
+ else
+ die(1, _("Invalid argument \"%s\"\n"), xarg);
+ done:
+ free((char *)dev);
+ return err;
+}
diff --git a/quotaops.c b/quotaops.c
new file mode 100644
index 0000000..82bfb43
--- /dev/null
+++ b/quotaops.c
@@ -0,0 +1,476 @@
+/*
+ * Copyright (c) 1980, 1990 Regents of the University of California. All
+ * rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Robert Elz at
+ * The University of Melbourne.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 3. All advertising
+ * materials mentioning features or use of this software must display the
+ * following acknowledgement: This product includes software developed by the
+ * University of California, Berkeley and its contributors. 4. Neither the
+ * name of the University nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ident "$Copyright: (c) 1980, 1990 Regents of the University of California. $"
+#ident "$Copyright: All rights reserved. $"
+#ident "$Id: quotaops.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $"
+
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <paths.h>
+#include <unistd.h>
+
+#if defined(RPC)
+#include "rquota.h"
+#endif
+
+#include "mntopt.h"
+#include "quotaops.h"
+#include "pot.h"
+#include "bylabel.h"
+#include "common.h"
+#include "quotasys.h"
+#include "quotaio.h"
+
+/*
+ * Convert ASCII input times to seconds.
+ */
+static int cvtatos(time_t time, char *units, time_t * seconds)
+{
+ if (memcmp(units, "second", 6) == 0)
+ *seconds = time;
+ else if (memcmp(units, "minute", 6) == 0)
+ *seconds = time * 60;
+ else if (memcmp(units, "hour", 4) == 0)
+ *seconds = time * 60 * 60;
+ else if (memcmp(units, "day", 3) == 0)
+ *seconds = time * 24 * 60 * 60;
+ else {
+ fprintf(stderr, _("%s: bad units, specify:\n %s, %s, %s, or %s"), units,
+ "days", "hours", "minutes", "seconds");
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Collect the requested quota information.
+ */
+struct dquot *getprivs(qid_t id, struct quota_handle **handles)
+{
+ struct dquot *q, *qtail = NULL, *qhead = NULL;
+ int i;
+
+ for (i = 0; handles[i]; i++) {
+ if (!(q = handles[i]->qh_ops->read_dquot(handles[i], id))) {
+ fprintf(stderr, _("Error while getting quota from %s for %u: %s\n"),
+ handles[i]->qh_quotadev, id, strerror(errno));
+ continue;
+ }
+ if (qhead == NULL)
+ qhead = q;
+ else
+ qtail->dq_next = q;
+ qtail = q;
+ q->dq_next = NULL; /* This should be already set, but just for sure... */
+ }
+ return qhead;
+}
+
+/*
+ * Store the requested quota information.
+ */
+int putprivs(struct dquot *qlist)
+{
+ struct dquot *q;
+
+ for (q = qlist; q; q = q->dq_next) {
+ if (q->dq_h->qh_ops->commit_dquot(q) == -1) {
+ fprintf(stderr, _("Can't write quota for %u on %s: %s\n"), q->dq_id,
+ q->dq_h->qh_quotadev, strerror(errno));
+ continue;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Take a list of priviledges and get it edited.
+ */
+int editprivs(char *tmpfile)
+{
+ long omask;
+ int pid, stat;
+
+ omask = sigblock(sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGHUP));
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ return -1;
+ }
+ if (pid == 0) {
+ char *ed;
+
+ sigsetmask(omask);
+ setgid(getgid());
+ setuid(getuid());
+ if ((ed = getenv("VISUAL")) == (char *)0)
+ if ((ed = getenv("EDITOR")) == (char *)0)
+ ed = _PATH_VI;
+ execlp(ed, ed, tmpfile, 0);
+ die(1, _("Can't exec %s\n"), ed);
+ }
+ waitpid(pid, &stat, 0);
+ sigsetmask(omask);
+
+ return 0;
+}
+
+/*
+ * Convert a dquot list to an ASCII file.
+ */
+int writeprivs(struct dquot *qlist, int outfd, char *name, int quotatype)
+{
+ struct dquot *q;
+ FILE *fd;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, SEEK_SET);
+ if (!(fd = fdopen(dup(outfd), "w")))
+ die(1, _("Can't duplicate descriptor of file to write to: %s\n"), strerror(errno));
+
+#if defined(ALT_FORMAT)
+ fprintf(fd, _("Disk quotas for %s %s (%cid %d):\n"),
+ type2name(quotatype), name, *type2name(quotatype), name2id(name, quotatype));
+
+ fprintf(fd,
+ _
+ (" Filesystem blocks soft hard inodes soft hard\n"));
+
+ for (q = qlist; q; q = q->dq_next) {
+ fprintf(fd, " %-24s %10Lu %10Lu %10Lu %10Lu %8Lu %8Lu\n",
+ q->dq_h->qh_quotadev,
+ (long long)toqb(q->dq_dqb.dqb_curspace),
+ (long long)q->dq_dqb.dqb_bsoftlimit,
+ (long long)q->dq_dqb.dqb_bhardlimit,
+ (long long)q->dq_dqb.dqb_curinodes,
+ (long long)q->dq_dqb.dqb_isoftlimit, (long long)q->dq_dqb.dqb_ihardlimit);
+ }
+#else
+ fprintf(fd, _("Quotas for %s %s:\n"), type2name(quotatype), name);
+ for (q = qlist; q; q = q->dq_next) {
+ fprintf(fd, _("%s: %s %d, limits (soft = %d, hard = %d)\n"),
+ q->dq_h->qh_quotadev, _("blocks in use:"),
+ (int)toqb(q->dq_dqb.dqb_curspace),
+ q->dq_dqb.dqb_bsoftlimit, q->dq_dqb.dqb_bhardlimit);
+ fprintf(fd, _("%s %d, limits (soft = %d, hard = %d)\n"),
+ _("\tinodes in use:"), q->dq_dqb.dqb_curinodes,
+ q->dq_dqb.dqb_isoftlimit, q->dq_dqb.dqb_ihardlimit);
+ }
+#endif
+ fclose(fd);
+ return 0;
+}
+
+/* Merge changes on one dev to proper structure in the list */
+static void merge_to_list(struct dquot *qlist, char *dev, u_int64_t blocks, u_int64_t bsoft,
+ u_int64_t bhard, u_int64_t inodes, u_int64_t isoft, u_int64_t ihard)
+{
+ struct dquot *q;
+
+ for (q = qlist; q; q = q->dq_next) {
+ if (strcmp(dev, q->dq_h->qh_quotadev))
+ continue;
+
+ /*
+ * Cause time limit to be reset when the quota is
+ * next used if previously had no soft limit or were
+ * under it, but now have a soft limit and are over
+ * it.
+ */
+ if (bsoft && (toqb(q->dq_dqb.dqb_curspace) >= bsoft) &&
+ (q->dq_dqb.dqb_bsoftlimit == 0 ||
+ toqb(q->dq_dqb.dqb_curspace) < q->dq_dqb.dqb_bsoftlimit))
+ q->dq_dqb.dqb_btime = 0;
+
+ if (isoft && (q->dq_dqb.dqb_curinodes >= isoft) &&
+ (q->dq_dqb.dqb_isoftlimit == 0 ||
+ q->dq_dqb.dqb_curinodes < q->dq_dqb.dqb_isoftlimit)) q->dq_dqb.dqb_itime = 0;
+
+ q->dq_dqb.dqb_bsoftlimit = bsoft;
+ q->dq_dqb.dqb_bhardlimit = bhard;
+ q->dq_dqb.dqb_isoftlimit = isoft;
+ q->dq_dqb.dqb_ihardlimit = ihard;
+ q->dq_flags |= DQ_FOUND;
+
+ if (blocks != toqb(q->dq_dqb.dqb_curspace))
+ fprintf(stderr, _("WARNING: %s: cannot change current block allocation\n"),
+ q->dq_h->qh_quotadev);
+ if (inodes != q->dq_dqb.dqb_curinodes)
+ fprintf(stderr, _("WARNING: %s: cannot change current inode allocation\n"),
+ q->dq_h->qh_quotadev);
+ }
+}
+
+/*
+ * Merge changes to an ASCII file into a dquot list.
+ */
+int readprivs(struct dquot *qlist, int infd)
+{
+ FILE *fd;
+ int cnt;
+ long long blocks, bsoft, bhard, inodes, isoft, ihard;
+ struct dquot *q;
+
+#if defined(ALT_FORMAT)
+ char fsp[BUFSIZ], line[BUFSIZ];
+#else
+ char *fsp, line1[BUFSIZ], line2[BUFSIZ];
+#endif
+
+ lseek(infd, 0, SEEK_SET);
+ if (!(fd = fdopen(dup(infd), "r")))
+ die(1, _("Can't duplicate descriptor of temp file: %s\n"), strerror(errno));
+
+#if defined(ALT_FORMAT)
+ /*
+ * Discard title lines, then read lines to process.
+ */
+ fgets(line, sizeof(line), fd);
+ fgets(line, sizeof(line), fd);
+
+ while (fgets(line, sizeof(line), fd)) {
+ cnt = sscanf(line, "%s %Lu %Lu %Lu %Lu %Lu %Lu",
+ fsp, &blocks, &bsoft, &bhard, &inodes, &isoft, &ihard);
+
+ if (cnt != 7) {
+ fprintf(stderr, _("Bad format:\n%s\n"), line);
+ return -1;
+ }
+
+ merge_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
+ }
+#else
+ /*
+ * Discard title line, then read pairs of lines to process.
+ */
+ fgets(line1, sizeof(line1), fd);
+ while (fgets(line1, sizeof(line1), fd) && fgets(line2, sizeof(line2), fd)) {
+ if (!(fsp = strtok(line1, " \t:"))) {
+ fprintf(stderr, _("%s: bad format\n"), line1);
+ return -1;
+ }
+ if (!(cp = strtok(NULL, "\n"))) {
+ fprintf(stderr, _("%s: %s: bad format\n"), fsp, &fsp[strlen(fsp) + 1]);
+ return -1;
+ }
+
+ cnt = sscanf(cp, _(" blocks in use: %Lu, limits (soft = %Lu, hard = %Lu)"),
+ &blocks, &bsoft, &bhard);
+ if (cnt != 3) {
+ fprintf(stderr, _("%s:%s: bad format\n"), fsp, cp);
+ return -1;
+ }
+
+ if (!(cp = strtok(line2, "\n"))) {
+ fprintf(stderr, _("%s: %s: bad format\n"), fsp, line2);
+ return -1;
+ }
+
+ cnt = sscanf(cp, _("\tinodes in use: %Lu, limits (soft = %Lu, hard = %Lu)"),
+ &inodes, &isoft, &ihard);
+ if (cnt != 3) {
+ fprintf(stderr, _("%s: %s: bad format\n"), fsp, line2);
+ return -1;
+ }
+
+ merge_to_list(qlist, fsp, blocks, bsoft, bhard, inodes, isoft, ihard);
+ }
+#endif
+ fclose(fd);
+
+ /*
+ * Disable quotas for any filesystems that have not been found.
+ */
+ for (q = qlist; q; q = q->dq_next) {
+ if (q->dq_flags & DQ_FOUND) {
+ q->dq_flags &= ~DQ_FOUND;
+ continue;
+ }
+ q->dq_dqb.dqb_bsoftlimit = 0;
+ q->dq_dqb.dqb_bhardlimit = 0;
+ q->dq_dqb.dqb_isoftlimit = 0;
+ q->dq_dqb.dqb_ihardlimit = 0;
+ }
+ return 0;
+}
+
+/*
+ * Convert a dquot list to an ASCII file of grace times.
+ */
+int writetimes(struct quota_handle **handles, int outfd)
+{
+ FILE *fd;
+ char itimebuf[MAXTIMELEN], btimebuf[MAXTIMELEN];
+ int i;
+
+ if (!handles[0])
+ return 0;
+
+ ftruncate(outfd, 0);
+ lseek(outfd, 0, SEEK_SET);
+ if ((fd = fdopen(dup(outfd), "w")) == NULL)
+ die(1, _("Can't duplicate descriptor of file to edit: %s\n"), strerror(errno));
+
+#if defined(ALT_FORMAT)
+ fprintf(fd, _("Grace period before enforcing soft limits for %ss:\n"),
+ type2name(handles[0]->qh_type));
+ fprintf(fd, _("Time units may be: days, hours, minutes, or seconds\n"));
+ fprintf(fd, _(" Filesystem Block grace period Inode grace period\n"));
+
+ for (i = 0; handles[i]; i++) {
+ time2str(handles[i]->qh_info.dqi_bgrace, btimebuf, 0);
+ time2str(handles[i]->qh_info.dqi_igrace, itimebuf, 0);
+ fprintf(fd, " %-12s %22s %22s\n", handles[i]->qh_quotadev, btimebuf, itimebuf);
+ }
+#else
+ fprintf(fd, _("Time units may be: days, hours, minutes, or seconds\n"));
+ fprintf(fd, _("Grace period before enforcing soft limits for %ss:\n"),
+ type2name(handles[0]->qh_type));
+ for (i = 0; handles[i]; i++) {
+ time2str(handles[i]->qh_info.dqi_bgrace, btimebuf, 0);
+ time2str(handles[i]->qh_info.dqi_igrace, itimebuf, 0);
+ fprintf(fd, _("%s: block grace period: %s, file grace period: %s\n"),
+ handles[i]->qh_quotadev, btimebuf, itimebuf);
+ }
+#endif
+
+ fclose(fd);
+ return 0;
+}
+
+/*
+ * Merge changes of grace times in an ASCII file into a dquot list.
+ */
+int readtimes(struct quota_handle **handles, int infd)
+{
+ FILE *fd;
+ int itime, btime, i, cnt;
+ time_t iseconds, bseconds;
+
+#if defined(ALT_FORMAT)
+ char fsp[BUFSIZ], bunits[10], iunits[10], line[BUFSIZ];
+#else
+ char *fsp, bunits[10], iunits[10], line1[BUFSIZ];
+#endif
+
+ if (!handles[0])
+ return 0;
+ lseek(infd, 0, SEEK_SET);
+ if (!(fd = fdopen(dup(infd), "r"))) {
+ fprintf(stderr, _("Can't reopen temp file: %s\n"), strerror(errno));
+ return -1;
+ }
+
+ /* Set all grace times to default values */
+ for (i = 0; handles[i]; i++) {
+ handles[i]->qh_info.dqi_bgrace = MAX_DQ_TIME;
+ handles[i]->qh_info.dqi_igrace = MAX_IQ_TIME;
+ mark_quotafile_info_dirty(handles[i]);
+ }
+#if defined(ALT_FORMAT)
+ /*
+ * Discard three title lines, then read lines to process.
+ */
+ fgets(line, sizeof(line), fd);
+ fgets(line, sizeof(line), fd);
+ fgets(line, sizeof(line), fd);
+
+ while (fgets(line, sizeof(line), fd)) {
+ cnt = sscanf(line, "%s %d %s %d %s", fsp, &btime, bunits, &itime, iunits);
+ if (cnt != 5) {
+ fprintf(stderr, _("bad format:\n%s\n"), line);
+ return -1;
+ }
+#else
+ /*
+ * Discard two title lines, then read lines to process.
+ */
+ fgets(line1, sizeof(line1), fd);
+ fgets(line1, sizeof(line1), fd);
+
+ while (fgets(line1, sizeof(line1), fd)) {
+ if (!(fsp = strtok(line1, " \t:"))) {
+ fprintf(stderr, _("%s: bad format\n"), line1);
+ return -1;
+ }
+ if (!(cp = strtok(NULL, "\n"))) {
+ fprintf(stderr, _("%s: %s: bad format\n"), fsp, &fsp[strlen(fsp) + 1]);
+ return -1;
+ }
+ cnt = sscanf(cp, _(" block grace period: %d %s file grace period: %d %s"),
+ &btime, bunits, &itime, iunits);
+ if (cnt != 4) {
+ fprintf(stderr, _("%s:%s: bad format\n"), fsp, cp);
+ return -1;
+ }
+#endif
+ if (cvtatos(btime, bunits, &bseconds) < 0)
+ return -1;
+ if (cvtatos(itime, iunits, &iseconds) < 0)
+ return -1;
+ for (i = 0; handles[i]; i++) {
+ if (strcmp(fsp, handles[i]->qh_quotadev))
+ continue;
+ handles[i]->qh_info.dqi_bgrace = bseconds;
+ handles[i]->qh_info.dqi_igrace = iseconds;
+ mark_quotafile_info_dirty(handles[i]);
+ break;
+ }
+ }
+ fclose(fd);
+
+ return 0;
+}
+
+/*
+ * Free a list of dquot structures.
+ */
+void freeprivs(struct dquot *qlist)
+{
+ struct dquot *q, *nextq;
+
+ for (q = qlist; q; q = nextq) {
+ nextq = q->dq_next;
+ free(q);
+ }
+}
diff --git a/quotaops.h b/quotaops.h
new file mode 100644
index 0000000..da28bde
--- /dev/null
+++ b/quotaops.h
@@ -0,0 +1,16 @@
+#ifndef _QUOTAOPS_H
+#define _QUOTAOPS_H
+
+#include "quotaio.h"
+
+__BEGIN_DECLS extern struct dquot *getprivs __P((qid_t id, struct quota_handle ** handles));
+extern int putprivs __P((struct dquot * qlist));
+extern int editprivs __P((char *tmpfile));
+extern int writeprivs __P((struct dquot * qlist, int outfd, char *name, int quotatype));
+extern int readprivs __P((struct dquot * qlist, int infd));
+extern int writetimes __P((struct quota_handle ** handles, int outfd));
+extern int readtimes __P((struct quota_handle ** handles, int infd));
+extern void freeprivs __P((struct dquot * qlist));
+
+__END_DECLS
+#endif /* _QUOTAOPS_H */
diff --git a/quotastats.c b/quotastats.c
new file mode 100644
index 0000000..6b67222
--- /dev/null
+++ b/quotastats.c
@@ -0,0 +1,59 @@
+/*
+ * QUOTA An implementation of the diskquota system for the LINUX operating
+ * system. QUOTA is implemented using the BSD systemcall interface
+ * as the means of communication with the user level. Should work for
+ * all filesystems because of integration into the VFS layer of the
+ * operating system. This is based on the Melbourne quota system wich
+ * uses both user and group quota files.
+ *
+ * Program to query for the internal statistics.
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * Version: $Id: quotastats.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "pot.h"
+#include "quota.h"
+
+static inline int get_stats(struct dqstats *dqstats)
+{
+ return quotactl(QCMD(Q_GETSTATS, 0), (char *)NULL, 0, (caddr_t) dqstats);
+}
+
+static inline int print_stats(struct dqstats *dqstats)
+{
+ fprintf(stdout, _("Number of dquot lookups: %ld\n"), (long)dqstats->lookups);
+ fprintf(stdout, _("Number of dquot drops: %ld\n"), (long)dqstats->drops);
+ fprintf(stdout, _("Number of still active inodes with quota : %ld\n"),
+ (long)(dqstats->lookups - dqstats->drops));
+ fprintf(stdout, _("Number of dquot reads: %ld\n"), (long)dqstats->reads);
+ fprintf(stdout, _("Number of dquot writes: %ld\n"), (long)dqstats->writes);
+ fprintf(stdout, _("Number of quotafile syncs: %ld\n"), (long)dqstats->syncs);
+ fprintf(stdout, _("Number of dquot cache hits: %ld\n"), (long)dqstats->cache_hits);
+ fprintf(stdout, _("Number of allocated dquots: %ld\n"), (long)dqstats->allocated_dquots);
+ fprintf(stdout, _("Number of free dquots: %ld\n"), (long)dqstats->free_dquots);
+ fprintf(stdout, _("Number of in use dquot entries (user/group): %ld\n"),
+ (long)(dqstats->allocated_dquots - dqstats->free_dquots));
+ return (0);
+}
+
+int main(int argc, char **argv)
+{
+ struct dqstats dqstats;
+
+ gettexton();
+
+ if (!get_stats(&dqstats))
+ print_stats(&dqstats);
+ return 0;
+}
diff --git a/quotasys.c b/quotasys.c
new file mode 100644
index 0000000..d4d5f80
--- /dev/null
+++ b/quotasys.c
@@ -0,0 +1,442 @@
+/*
+ *
+ * Interactions of quota with system - filenames, fstab and so on...
+ *
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <pwd.h>
+#include <grp.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pot.h"
+#include "bylabel.h"
+#include "common.h"
+#include "quotasys.h"
+#include "quotaio.h"
+#include "dqblk_v1.h"
+#include "dqblk_v2.h"
+#include "dqblk_xfs.h"
+
+#define min(x,y) (((x) < (y)) ? (x) : (y))
+#define CORRECT_FSTYPE(type) \
+((!strcmp(type, MNTTYPE_EXT2)) || \
+(!strcmp(type, MNTTYPE_EXT3)) || \
+(!strcmp(type, MNTTYPE_MINIX)) || \
+(!strcmp(type, MNTTYPE_UFS)) || \
+(!strcmp(type, MNTTYPE_UDF)) || \
+(!strcmp(type, MNTTYPE_REISER)) || \
+(!strcmp(type, MNTTYPE_XFS)))
+
+static char extensions[MAXQUOTAS + 2][20] = INITQFNAMES;
+static char *basenames[] = INITQFBASENAMES;
+
+/*
+ * Convert type of quota to written representation
+ */
+char *type2name(int type)
+{
+ return extensions[type];
+}
+
+/*
+ * Convert name to uid
+ */
+uid_t user2uid(char *name)
+{
+ struct passwd *entry;
+ uid_t ret;
+ char *errch;
+
+ ret = strtol(name, &errch, 0);
+ if (!*errch) /* Is name number - we got directly uid? */
+ return ret;
+ if (!(entry = getpwnam(name))) {
+ fprintf(stderr, _("User %s doesn't exist.\n"), name);
+ exit(1);
+ }
+ return entry->pw_uid;
+}
+
+/*
+ * Convert group name to gid
+ */
+gid_t group2gid(char *name)
+{
+ struct group *entry;
+ gid_t ret;
+ char *errch;
+
+ ret = strtol(name, &errch, 0);
+ if (!*errch) /* Is name number - we got directly gid? */
+ return ret;
+ if (!(entry = getgrnam(name))) {
+ fprintf(stderr, _("Group %s doesn't exist.\n"), name);
+ exit(1);
+ }
+ return entry->gr_gid;
+}
+
+/*
+ * Convert name to id
+ */
+int name2id(char *name, int qtype)
+{
+ if (qtype == USRQUOTA)
+ return user2uid(name);
+ else
+ return group2gid(name);
+}
+
+/*
+ * Convert uid to name
+ */
+void uid2user(uid_t id, char *buf)
+{
+ struct passwd *entry;
+
+ if (!(entry = getpwuid(id)))
+ sprintf(buf, "#%u", (uint) id);
+ else
+ sstrncpy(buf, entry->pw_name, MAXNAMELEN);
+}
+
+/*
+ * Convert gid to name
+ */
+void gid2group(gid_t id, char *buf)
+{
+ struct group *entry;
+
+ if (!(entry = getgrgid(id)))
+ sprintf(buf, "#%u", (uint) id);
+ else
+ sstrncpy(buf, entry->gr_name, MAXNAMELEN);
+}
+
+/*
+ * Convert id to user/groupname
+ */
+void id2name(int id, int qtype, char *buf)
+{
+ if (qtype == USRQUOTA)
+ uid2user(id, buf);
+ else
+ gid2group(id, buf);
+}
+
+/*
+ * Convert quota format name to number
+ */
+int name2fmt(char *str)
+{
+ if (!strcmp(str, _("vfsold"))) /* Old quota format */
+ return QF_VFSOLD;
+ if (!strcmp(str, _("vfsv0"))) /* New quota format */
+ return QF_VFSV0;
+ if (!strcmp(str, _("rpc"))) /* RPC quota calls */
+ return QF_RPC;
+ fprintf(stderr, _("Unknown quota format: %s\nSupported formats are:\n\
+ vfsold - original quota format\n\
+ vfsv0 - new quota format\n\
+ rpc - use RPC calls\n"), str);
+ return QF_ERROR;
+}
+
+/*
+ * Convert time difference of seconds and current time
+ */
+void difftime2str(time_t seconds, char *buf)
+{
+ time_t now;
+
+ buf[0] = 0;
+ if (!seconds)
+ return;
+ time(&now);
+ if (seconds <= now) {
+ strcpy(buf, _("none"));
+ return;
+ }
+ time2str(seconds - now, buf, TF_ROUND);
+}
+
+/*
+ * Convert time to printable form
+ */
+void time2str(time_t seconds, char *buf, int flags)
+{
+ uint minutes, hours, days;
+
+ minutes = (seconds + 30) / 60; /* Rounding */
+ hours = minutes / 60;
+ minutes %= 60;
+ days = hours / 24;
+ hours %= 24;
+ if (flags & TF_ROUND) {
+ if (days >= 2)
+ sprintf(buf, _("%ddays"), days);
+ else
+ sprintf(buf, _("%02d:%02d"), hours + days * 24, minutes);
+ }
+ else {
+ if (minutes || (!minutes && !hours && !days))
+ sprintf(buf, _("%uminutes"), (uint) (seconds + 30) / 60);
+ else if (hours)
+ sprintf(buf, _("%uhours"), hours + days * 24);
+ else
+ sprintf(buf, _("%udays"), days);
+ }
+}
+
+/*
+ * Check to see if a particular quota is to be enabled (filesystem mounted with proper option)
+ */
+int hasquota(struct mntent *mnt, int type)
+{
+ char *option;
+
+ if (!CORRECT_FSTYPE(mnt->mnt_type))
+ return 0;
+
+ option = hasmntopt(mnt, MNTOPT_USRQUOTA);
+ if ((type == USRQUOTA) && (option || !strcmp(mnt->mnt_type, MNTTYPE_XFS)))
+ return 1;
+ option = hasmntopt(mnt, MNTOPT_GRPQUOTA);
+ if ((type == GRPQUOTA) && (option || !strcmp(mnt->mnt_type, MNTTYPE_XFS)))
+ return 1;
+ option = hasmntopt(mnt, MNTOPT_QUOTA);
+ if ((type == USRQUOTA) && (option || !strcmp(mnt->mnt_type, MNTTYPE_XFS)))
+ return 1;
+ return 0;
+}
+
+/* Check whether quotafile for given format exists - return its name in namebuf */
+static int check_fmtfile_exists(struct mntent *mnt, int type, int fmt, char *namebuf)
+{
+ struct stat buf;
+
+ sprintf(namebuf, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]);
+ if (!stat(namebuf, &buf))
+ return 1;
+ if (errno != ENOENT) {
+ fprintf(stderr, "Can't stat quotafile %s: %s\n", namebuf, strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Get quotafile name for given entry; "" means format has no quota
+ * Note that formats without quotafile *must* be detected prior to calling this function
+ */
+char *get_qf_name(struct mntent *mnt, int type, int fmt)
+{
+ char *option, *pathname, has_quota_file_definition = 0;
+ char qfullname[PATH_MAX] = "";
+
+ if ((type == USRQUOTA) && (option = hasmntopt(mnt, MNTOPT_USRQUOTA))) {
+ if (*(pathname = option + strlen(MNTOPT_USRQUOTA)) == '=')
+ has_quota_file_definition = 1;
+ }
+ else if ((type == GRPQUOTA) && (option = hasmntopt(mnt, MNTOPT_GRPQUOTA))) {
+ if (*(pathname = option + strlen(MNTOPT_GRPQUOTA)) == '=')
+ has_quota_file_definition = 1;
+ }
+ else if ((type == USRQUOTA) && (option = hasmntopt(mnt, MNTOPT_QUOTA))) {
+ if (*(pathname = option + strlen(MNTOPT_QUOTA)) == '=')
+ has_quota_file_definition = 1;
+ }
+ else
+ return NULL;
+
+ if (has_quota_file_definition) {
+ if ((option = strchr(++pathname, ',')))
+ strncpy(qfullname, pathname, min((option - pathname), sizeof(qfullname)));
+ else
+ strncpy(qfullname, pathname, sizeof(qfullname));
+ }
+ else if (fmt == -1) { /* Should guess quota format? */
+ int ret;
+
+ if ((ret = check_fmtfile_exists(mnt, type, QF_VFSV0, qfullname)) == -1)
+ return NULL;
+ if (ret)
+ fmt = QF_VFSV0;
+ else {
+ if ((ret = check_fmtfile_exists(mnt, type, QF_VFSOLD, qfullname)) == -1)
+ return NULL;
+ if (ret)
+ fmt = QF_VFSOLD;
+ }
+ if (fmt == -1)
+ return NULL;
+ }
+ else if (basenames[fmt][0]) /* Any name specified? */
+ sprintf(qfullname, "%s/%s.%s", mnt->mnt_dir, basenames[fmt], extensions[type]);
+
+ return sstrdup(qfullname);
+}
+
+/*
+ * Create NULL terminated list of quotafile handles from given list of mountpoints
+ * List of zero length means scan all entries in /etc/mtab
+ */
+struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
+ char local_only)
+{
+ FILE *mntf;
+ struct mntent *mnt;
+ int i, gotmnt = 0;
+ static struct quota_handle *hlist[MAXMNTPOINTS];
+ const char *dev;
+
+ if (!(mntf = setmntent(MOUNTED, "r")))
+ die(2, _("Can't open %s: %s\n"), MOUNTED, strerror(errno));
+ while ((mnt = getmntent(mntf))) {
+ if (!(dev = get_device_name(mnt->mnt_fsname)))
+ continue;
+ for (i = 0; i < gotmnt && strcmp(dev, hlist[i]->qh_quotadev); i++);
+ /* We already have this device? (can happen when filesystem is mounted multiple times */
+ if (i < gotmnt)
+ continue;
+ for (i = 0; i < count; i++)
+ /* Is this what we want? */
+ if (!strcmp(dev, mntpoints[i]) || !strcmp(mnt->mnt_dir, mntpoints[i]))
+ break;
+ free((char *)dev);
+ if (!count || i < count) {
+ if (strcmp(mnt->mnt_type, MNTTYPE_NFS)) { /* No NFS? */
+ if (gotmnt == MAXMNTPOINTS)
+ die(3, _("Too many mountpoints. Please report to: %s\n"),
+ MY_EMAIL);
+ if (!(hlist[gotmnt] = init_io(mnt, type, fmt)))
+ continue;
+ gotmnt++;
+ }
+ else if (!local_only) { /* Use NFS? */
+#ifdef RPC
+ if (gotmnt == MAXMNTPOINTS)
+ die(3, _("Too many mountpoints. Please report to: %s\n"),
+ MY_EMAIL);
+ if (!(hlist[gotmnt] = init_io(mnt, type, 0)))
+ continue;
+ gotmnt++;
+#endif
+ }
+ }
+ }
+ endmntent(mntf);
+ hlist[gotmnt] = NULL;
+ if (count && gotmnt != count)
+ die(1, _("Not all specified mountpoints are using quota.\n"));
+ return hlist;
+}
+
+/*
+ * Free given list of handles
+ */
+int dispose_handle_list(struct quota_handle **hlist)
+{
+ int i, ret;
+
+ for (i = 0; hlist[i]; i++)
+ if ((ret = end_io(hlist[i])))
+ fprintf(stderr, _("Error while releasing file on %s\n"),
+ hlist[i]->qh_quotadev);
+ return 0;
+}
+
+/*
+ * Check kernel quota version
+ */
+
+#define KERN_KNOWN_QUOTA_VERSION (6*10000 + 5*100 + 0)
+
+int kern_quota_format(void)
+{
+ struct dqstats stats;
+ int ret = 0;
+ struct stat st;
+
+ if (!stat("/proc/fs/xfs/stat", &st))
+ ret |= (1 << QF_XFS);
+ if (quotactl(QCMD(Q_GETSTATS, 0), NULL, 0, (void *)&stats) < 0) {
+ if (errno == ENOSYS || errno == ENOTSUP) /* Quota not compiled? */
+ return QF_ERROR;
+ if (errno == EINVAL || errno == EFAULT || errno == EPERM) /* Old quota compiled? */
+ return ret | (1 << QF_VFSOLD);
+ die(4, "Error while detecting kernel quota version: %s\n", strerror(errno));
+ }
+ /* We might do some more generic checks in future but this should be enough for now */
+ if (stats.version > KERN_KNOWN_QUOTA_VERSION) /* Newer kernel than we know? */
+ return QF_TOONEW;
+ return ret | (1 << QF_VFSV0); /* New format supported */
+}
+
+/*
+ * Warn about too new kernel
+ */
+void warn_new_kernel(int fmt)
+{
+ if (fmt == -1 && kern_quota_format() == QF_TOONEW)
+ fprintf(stderr,
+ _
+ ("Warning: Kernel quota is newer than supported. Quotafile used by utils need not be the one used by kernel.\n"));
+}
+
+/* Check whether old quota is turned on on given device */
+static int v1_kern_quota_on(const char *dev, int type)
+{
+ char tmp[1024]; /* Just temporary buffer */
+
+ if (!quotactl(QCMD(Q_V1_GETQUOTA, type), dev, 0, tmp)) /* OK? */
+ return 1;
+ return 0;
+}
+
+/* Check whether new quota is turned on on given device */
+static int v2_kern_quota_on(const char *dev, int type)
+{
+ char tmp[1024]; /* Just temporary buffer */
+
+ if (!quotactl(QCMD(Q_V2_GETINFO, type), dev, 0, tmp)) /* OK? */
+ return 1;
+ return 0;
+}
+
+/* Check whether XFS quota is turned on on given device */
+static int xfs_kern_quota_on(const char *dev, int type)
+{
+ struct xfs_mem_dqinfo info;
+
+ if (!quotactl(QCMD(Q_XFS_GETQSTAT, type), dev, 0, (void *)&info)) {
+ if (type == USRQUOTA && info.qs_flags & XFS_QUOTA_UDQ_ACCT)
+ return 1;
+ else if (type == GRPQUOTA && info.qs_flags & XFS_QUOTA_GDQ_ACCT)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check whether is quota turned on on given device for given type
+ */
+int kern_quota_on(const char *dev, int type, int fmt)
+{
+ /* Check whether quota is turned on... */
+ if ((fmt & (1 << QF_VFSV0)) && v2_kern_quota_on(dev, type)) /* New quota format */
+ return QF_VFSV0;
+ if ((fmt & (1 << QF_XFS)) && xfs_kern_quota_on(dev, type)) /* XFS quota format */
+ return QF_XFS;
+ if ((fmt & (1 << QF_VFSOLD)) && v1_kern_quota_on(dev, type)) /* Old quota format */
+ return QF_VFSOLD;
+ return -1;
+}
diff --git a/quotasys.h b/quotasys.h
new file mode 100644
index 0000000..e0380fb
--- /dev/null
+++ b/quotasys.h
@@ -0,0 +1,75 @@
+/*
+ *
+ * Headerfile of quota interactions with system - filenames, fstab...
+ *
+ */
+
+#ifndef _QUOTASYS_H
+#define _QUOTASYS_H
+
+#include <sys/types.h>
+#include "mntopt.h"
+
+#define MAXNAMELEN 64 /* Maximal length of user/group name */
+#define MAXTIMELEN 40 /* Maximal length of time string */
+#define MAXMNTPOINTS 128 /* Maximal number of processed mountpoints per one run */
+
+/* Flags for formatting time */
+#define TF_ROUND 0x1 /* Should be printed time rounded? */
+
+/*
+ * Exported functions
+ */
+/* Convert quota type to written form */
+char *type2name(int);
+
+/* Convert username to uid */
+uid_t user2uid(char *);
+
+/* Convert groupname to gid */
+gid_t group2gid(char *);
+
+/* Convert user/groupname to id */
+int name2id(char *name, int qtype);
+
+/* Convert uid to username */
+void uid2user(uid_t, char *);
+
+/* Convert gid to groupname */
+void gid2group(gid_t, char *);
+
+/* Convert id to user/group name */
+void id2name(int id, int qtype, char *buf);
+
+/* Convert quota format name to number */
+int name2fmt(char *str);
+
+/* Convert time difference between given time and current time to printable form */
+void difftime2str(time_t, char *);
+
+/* Convert time to printable form */
+void time2str(time_t, char *, int);
+
+/* Check to see if particular quota is to be enabled */
+int hasquota(struct mntent *mnt, int type);
+
+/* Get quotafile name for given entry */
+char *get_qf_name(struct mntent *mnt, int type, int fmt);
+
+/* Create NULL-terminated list of handles for quotafiles for given mountpoints */
+struct quota_handle **create_handle_list(int count, char **mntpoints, int type, int fmt,
+
+ char local_only);
+/* Dispose given list of handles */
+int dispose_handle_list(struct quota_handle **hlist);
+
+/* Warn about too new kernel */
+void warn_new_kernel(int fmt);
+
+/* Check kernel supported quotafile format */
+int kern_quota_format(void);
+
+/* Check whether is quota turned on on given device for given type */
+int kern_quota_on(const char *dev, int type, int fmt);
+
+#endif /* _QUOTASYS_H */
diff --git a/repquota.8 b/repquota.8
new file mode 100644
index 0000000..a4f5854
--- /dev/null
+++ b/repquota.8
@@ -0,0 +1,71 @@
+.TH REPQUOTA 8
+.UC 4
+.SH NAME
+repquota \- summarize quotas for a filesystem
+.SH SYNOPSIS
+.B /usr/etc/repquota
+[
+.B \-vug
+]
+.IR filesystem .\|.\|.
+.LP
+.B /usr/etc/repquota
+[
+.B \-avug
+]
+.SH DESCRIPTION
+.IX "repquota command" "" "\fLrepquota\fP \(em summarize quotas"
+.IX "user quotas" "repquota command" "" "\fLrepquota\fP \(em summarize quotas"
+.IX "disk quotas" "repquota command" "" "\fLrepquota\fP \(em summarize quotas"
+.IX "quotas" "repquota command" "" "\fLrepquota\fP \(em summarize quotas"
+.IX "filesystem" "repquota command" "" "\fLrepquota\fP \(em summarize quotas"
+.IX "summarize filesystem quotas repquota" "" "summarize filesystem quotas \(em \fLrepquota\fP"
+.IX "report filesystem quotas repquota" "" "report filesystem quotas \(em \fLrepquota\fP"
+.IX display "filesystem quotas \(em \fLrepquota\fP"
+.LP
+.B repquota
+prints a summary of the disc usage and quotas for the specified file
+systems. For each user the current number of files and amount of space
+(in kilobytes) is printed, along with any quotas created with
+.BR edquota (8).
+.SH OPTIONS
+.TP
+.B \-a
+Report on all filesystems indicated in
+.B /etc/mtab
+to be read-write with quotas.
+.TP
+.B \-v
+Report all quotas, even if there is no usage.
+.TP
+.B \-g
+Report quotas for groups.
+.TP
+.B \-u
+Report quotas for users. This is the default.
+.LP
+Only the super-user may view quotas which are not their own.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+default filesystems
+.TP
+.B /etc/passwd
+default set of users
+.TP
+.B /etc/passwd
+default set of groups
+.PD
+.SH SEE ALSO
+.BR quota (1),
+.BR quotactl (2),
+.BR edquota (8),
+.BR quotacheck (8),
+.BR quotaon (8)
diff --git a/repquota.c b/repquota.c
new file mode 100644
index 0000000..b296149
--- /dev/null
+++ b/repquota.c
@@ -0,0 +1,160 @@
+/*
+ *
+ * Utility for reporting quotas
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+
+#include "pot.h"
+#include "common.h"
+#include "quotasys.h"
+#include "quotaio.h"
+
+#define FL_USER 1
+#define FL_GROUP 2
+#define FL_VERBOSE 4
+#define FL_ALL 8
+
+int flags, fmt = -1;
+char **mnt;
+int mntcnt;
+
+static void parse_options(int argcnt, char **argstr)
+{
+ int ret;
+ char *slash = strrchr(argstr[0], '/');
+
+ if (!slash)
+ slash = argstr[0];
+ else
+ slash++;
+
+ while ((ret = getopt(argcnt, argstr, "VavughF:")) != EOF) {
+ switch (ret) {
+ case '?':
+ case 'h':
+ usage:
+ fprintf(stderr,
+ _
+ ("Utility for reporting quotas.\nUsage:\n%s [-vug] [-F quotaformat] (-a | mntpoint)\n"),
+ slash);
+ fprintf(stderr, _("Bugs to %s\n"), MY_EMAIL);
+ exit(1);
+ case 'V':
+ version();
+ exit(0);
+ case 'u':
+ flags |= FL_USER;
+ break;
+ case 'g':
+ flags |= FL_GROUP;
+ break;
+ case 'v':
+ flags |= FL_VERBOSE;
+ break;
+ case 'a':
+ flags |= FL_ALL;
+ break;
+ case 'F':
+ if ((fmt = name2fmt(optarg)) == QF_ERROR)
+ exit(1);
+ break;
+
+ }
+ }
+
+ if ((flags & FL_ALL && optind != argcnt) || (!(flags & FL_ALL) && optind == argcnt)) {
+ fputs(_("Bad number of arguments.\n"), stderr);
+ goto usage;
+ }
+ if (fmt == QF_RPC) {
+ fputs(_("Repquota can't report through RPC calls.\n"), stderr);
+ exit(1);
+ }
+ if (!(flags & (FL_USER | FL_GROUP)))
+ flags |= FL_USER;
+ if (!(flags & FL_ALL)) {
+ mnt = argstr + optind;
+ mntcnt = argcnt - optind;
+ }
+}
+
+static char overlim(uint usage, uint softlim, uint hardlim)
+{
+ if ((usage > softlim && softlim) || (usage > hardlim && hardlim))
+ return '+';
+ return '-';
+}
+
+static int print(struct dquot *dquot)
+{
+ char name[MAXNAMELEN];
+ char time[MAXTIMELEN];
+ struct util_dqblk *entry = &dquot->dq_dqb;
+
+ if (!entry->dqb_curspace && !entry->dqb_curinodes && !(flags & FL_VERBOSE))
+ return 0;
+ id2name(dquot->dq_id, dquot->dq_h->qh_type, name);
+ difftime2str(entry->dqb_btime, time);
+ printf("%-10s%c%c%8Lu%8Lu%8Lu%7s", name,
+ overlim(qb2kb(toqb(entry->dqb_curspace)), qb2kb(entry->dqb_bsoftlimit),
+ qb2kb(entry->dqb_bhardlimit)), overlim(entry->dqb_curinodes,
+ entry->dqb_isoftlimit,
+ entry->dqb_ihardlimit),
+ (long long)qb2kb(toqb(entry->dqb_curspace)), (long long)qb2kb(entry->dqb_bsoftlimit),
+ (long long)qb2kb(entry->dqb_bhardlimit), time);
+ difftime2str(entry->dqb_itime, time);
+ printf("%8Lu%6Lu%6Lu%7s\n", (long long)entry->dqb_curinodes,
+ (long long)entry->dqb_isoftlimit, (long long)entry->dqb_ihardlimit, time);
+ return 0;
+}
+
+static void report_it(struct quota_handle *h, int type)
+{
+ char bgbuf[MAXTIMELEN], igbuf[MAXTIMELEN];
+
+ printf(_("*** Report for %s quotas on device %s\n"), type2name(type), h->qh_quotadev);
+ time2str(h->qh_info.dqi_bgrace, bgbuf, TF_ROUND);
+ time2str(h->qh_info.dqi_igrace, igbuf, TF_ROUND);
+ printf("Block grace time: %s Inode grace time: %s\n", bgbuf, igbuf);
+ printf(" Block limits File limits\n");
+ printf("User used soft hard grace used soft hard grace\n");
+
+ if (h->qh_ops->scan_dquots(h, print) < 0)
+ return;
+ if (h->qh_ops->report)
+ h->qh_ops->report(h, flags & FL_VERBOSE);
+}
+
+static void report(int type)
+{
+ struct quota_handle **handles;
+ int i;
+
+ if (flags & FL_ALL)
+ handles = create_handle_list(0, NULL, type, fmt, 1);
+ else
+ handles = create_handle_list(mntcnt, mnt, type, fmt, 1);
+ for (i = 0; handles[i]; i++)
+ report_it(handles[i], type);
+ dispose_handle_list(handles);
+}
+
+int main(int argcnt, char **argstr)
+{
+ gettexton();
+ parse_options(argcnt, argstr);
+ warn_new_kernel(fmt);
+ if (flags & FL_USER)
+ report(USRQUOTA);
+ if (flags & FL_GROUP)
+ report(GRPQUOTA);
+ return 0;
+}
diff --git a/rquota.3 b/rquota.3
new file mode 100644
index 0000000..8eee71e
--- /dev/null
+++ b/rquota.3
@@ -0,0 +1,34 @@
+.\"@(#)rquota.3;
+.TH RQUOTA 3
+.SH NAME
+rquota \- implement quotas on remote machines
+.SH PROTOCOL
+.B /usr/include/rpcsvc/rquota.x
+.SH DESCRIPTION
+.IX "rquota()" "" "\fLrquota()\fP \(em implement quotas on remote machines"
+.LP
+The
+.B rquota(\|)
+protocol inquires about quotas on remote machines.
+It is used in conjunction with
+.SM NFS\s0,
+since
+.SM NFS
+itself does not implement quotas.
+.SH PROGRAMMING
+.LP
+.B #include <rpcsvc/rquota.h>
+.LP
+The following
+.SM XDR
+routines are available in
+.BR librpcsvc :
+.nf
+.B xdr_getquota_arg
+.B xdr_getquota_rslt
+.B xdr_rquota
+.fi
+.SH SEE ALSO
+.BR quota (1),
+.BR quotactl (2)
+
diff --git a/rquota.x b/rquota.x
new file mode 100644
index 0000000..3cd5c10
--- /dev/null
+++ b/rquota.x
@@ -0,0 +1,139 @@
+/* @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC */
+/* @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro */
+
+/*
+ * Remote quota protocol
+ * Requires unix authentication
+ */
+
+const RQ_PATHLEN = 1024;
+
+struct sq_dqblk {
+ unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */
+ unsigned int rq_bsoftlimit; /* preferred limit on disk blks */
+ unsigned int rq_curblocks; /* current block count */
+ unsigned int rq_fhardlimit; /* absolute limit on allocated files */
+ unsigned int rq_fsoftlimit; /* preferred file limit */
+ unsigned int rq_curfiles; /* current # allocated files */
+ unsigned int rq_btimeleft; /* time left for excessive disk use */
+ unsigned int rq_ftimeleft; /* time left for excessive files */
+};
+
+struct getquota_args {
+ string gqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
+ int gqa_uid; /* Inquire about quota for uid */
+};
+
+struct setquota_args {
+ int sqa_qcmd;
+ string sqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
+ int sqa_id; /* Set quota for uid */
+ sq_dqblk sqa_dqblk;
+};
+
+struct ext_getquota_args {
+ string gqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
+ int gqa_type; /* Type of quota info is needed about */
+ int gqa_id; /* Inquire about quota for id */
+};
+
+struct ext_setquota_args {
+ int sqa_qcmd;
+ string sqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */
+ int sqa_id; /* Set quota for id */
+ int sqa_type; /* Type of quota to set */
+ sq_dqblk sqa_dqblk;
+};
+
+/*
+ * remote quota structure
+ */
+struct rquota {
+ int rq_bsize; /* block size for block counts */
+ bool rq_active; /* indicates whether quota is active */
+ unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */
+ unsigned int rq_bsoftlimit; /* preferred limit on disk blks */
+ unsigned int rq_curblocks; /* current block count */
+ unsigned int rq_fhardlimit; /* absolute limit on allocated files */
+ unsigned int rq_fsoftlimit; /* preferred file limit */
+ unsigned int rq_curfiles; /* current # allocated files */
+ unsigned int rq_btimeleft; /* time left for excessive disk use */
+ unsigned int rq_ftimeleft; /* time left for excessive files */
+};
+
+enum qr_status {
+ Q_OK = 1, /* quota returned */
+ Q_NOQUOTA = 2, /* noquota for uid */
+ Q_EPERM = 3 /* no permission to access quota */
+};
+
+union getquota_rslt switch (qr_status status) {
+case Q_OK:
+ rquota gqr_rquota; /* valid if status == Q_OK */
+case Q_NOQUOTA:
+ void;
+case Q_EPERM:
+ void;
+};
+
+union setquota_rslt switch (qr_status status) {
+case Q_OK:
+ rquota sqr_rquota; /* valid if status == Q_OK */
+case Q_NOQUOTA:
+ void;
+case Q_EPERM:
+ void;
+};
+
+program RQUOTAPROG {
+ version RQUOTAVERS {
+ /*
+ * Get all quotas
+ */
+ getquota_rslt
+ RQUOTAPROC_GETQUOTA(getquota_args) = 1;
+
+ /*
+ * Get active quotas only
+ */
+ getquota_rslt
+ RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2;
+
+ /*
+ * Set all quotas
+ */
+ setquota_rslt
+ RQUOTAPROC_SETQUOTA(setquota_args) = 3;
+
+ /*
+ * Get active quotas only
+ */
+ setquota_rslt
+ RQUOTAPROC_SETACTIVEQUOTA(setquota_args) = 4;
+ } = 1;
+ version EXT_RQUOTAVERS {
+ /*
+ * Get all quotas
+ */
+ getquota_rslt
+ RQUOTAPROC_GETQUOTA(ext_getquota_args) = 1;
+
+ /*
+ * Get active quotas only
+ */
+ getquota_rslt
+ RQUOTAPROC_GETACTIVEQUOTA(ext_getquota_args) = 2;
+
+ /*
+ * Set all quotas
+ */
+ setquota_rslt
+ RQUOTAPROC_SETQUOTA(ext_setquota_args) = 3;
+
+ /*
+ * Set active quotas only
+ */
+ setquota_rslt
+ RQUOTAPROC_SETACTIVEQUOTA(ext_setquota_args) = 4;
+ } = 2;
+} = 100011;
diff --git a/rquota_client.c b/rquota_client.c
new file mode 100644
index 0000000..017dd2c
--- /dev/null
+++ b/rquota_client.c
@@ -0,0 +1,309 @@
+/*
+ * QUOTA An implementation of the diskquota system for the LINUX
+ * operating system. QUOTA is implemented using the BSD systemcall
+ * interface as the means of communication with the user level.
+ * Should work for all filesystems because of integration into the
+ * VFS layer of the operating system.
+ * This is based on the Melbourne quota system wich uses both user and
+ * group quota files.
+ *
+ * This part does the rpc-communication with the rquotad.
+ *
+ * Version: $Id: rquota_client.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+#include "mntopt.h"
+#include "rquota.h"
+#include "common.h"
+#include "quotaio.h"
+
+#if defined(RPC)
+
+/* Convert network format of quotas to utils one */
+static inline void clinet2utildqblk(struct util_dqblk *u, struct rquota *n)
+{
+ /* Copy the quota */
+ u->dqb_bhardlimit = n->rq_bhardlimit;
+ u->dqb_bsoftlimit = n->rq_bsoftlimit;
+ u->dqb_ihardlimit = n->rq_fhardlimit;
+ u->dqb_isoftlimit = n->rq_fsoftlimit;
+ u->dqb_curinodes = n->rq_curfiles;
+ u->dqb_curspace = n->rq_curblocks * n->rq_bsize;
+ u->dqb_btime = n->rq_btimeleft;
+ u->dqb_itime = n->rq_ftimeleft;
+ /* Convert from remote block size */
+ if (n->rq_bsize != RPC_DQBLK_SIZE) {
+ int conversion_unit;
+
+ conversion_unit = n->rq_bsize >> RPC_DQBLK_SIZE_BITS;
+ if (conversion_unit == 0) {
+ conversion_unit = RPC_DQBLK_SIZE / n->rq_bsize;
+
+ u->dqb_bhardlimit /= conversion_unit;
+ u->dqb_bsoftlimit /= conversion_unit;
+ }
+ else {
+ u->dqb_bhardlimit *= conversion_unit;
+ u->dqb_bsoftlimit *= conversion_unit;
+ }
+ }
+}
+
+/* Convert utils format of quotas to network one */
+static inline void cliutil2netdqblk(struct sq_dqblk *n, struct util_dqblk *u)
+{
+ n->rq_bhardlimit = u->dqb_bhardlimit;
+ n->rq_bsoftlimit = u->dqb_bsoftlimit;
+ n->rq_fhardlimit = u->dqb_ihardlimit;
+ n->rq_fsoftlimit = u->dqb_isoftlimit;
+ n->rq_curblocks = toqb(u->dqb_curspace);
+ n->rq_curfiles = u->dqb_curinodes;
+ n->rq_btimeleft = u->dqb_btime;
+ n->rq_ftimeleft = u->dqb_itime;
+}
+
+/*
+ * Collect the requested quota information from a remote host.
+ */
+void rpc_rquota_get(struct dquot *dquot)
+{
+ CLIENT *clnt;
+ getquota_rslt *result;
+ union {
+ getquota_args arg;
+ ext_getquota_args ext_arg;
+ } args;
+ char *fsname_tmp, *host, *pathname;
+ struct timeval timeout = { 2, 0 };
+
+ /*
+ * Initialize with NULL.
+ */
+ memset(&dquot->dq_dqb, 0, sizeof(dquot->dq_dqb));
+
+ /*
+ * Convert host:pathname to seperate host and pathname.
+ */
+ fsname_tmp = (char *)smalloc(strlen(dquot->dq_h->qh_quotadev) + 1);
+ strcpy(fsname_tmp, dquot->dq_h->qh_quotadev);
+ host = fsname_tmp;
+
+ /*
+ * Strip off pathname on nfs mounted dir. Ignore entries of any
+ * automounter.
+ */
+ if ((pathname = strchr(fsname_tmp, ':')) == (char *)0 || *(pathname + 1) == '(')
+ return;
+
+ *pathname++ = '\0';
+
+ /*
+ * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program)
+ */
+ args.ext_arg.gqa_pathp = pathname;
+ args.ext_arg.gqa_id = dquot->dq_id;
+ args.ext_arg.gqa_type = dquot->dq_h->qh_type;
+
+ /*
+ * Create a RPC client.
+ */
+ if ((clnt = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp")) != NULL) {
+ /*
+ * Initialize unix authentication
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ /*
+ * Setup protocol timeout.
+ */
+ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);
+
+ /*
+ * Do RPC call and check result.
+ */
+ result = rquotaproc_getquota_2(&args.ext_arg, clnt);
+ if (result != NULL && result->status == Q_OK)
+ clinet2utildqblk(&dquot->dq_dqb, &result->getquota_rslt_u.gqr_rquota);
+
+ /*
+ * Destroy unix authentication and RPC client structure.
+ */
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+ else {
+ result = NULL;
+ }
+
+ if (result == NULL || !result->status) {
+ if (dquot->dq_h->qh_type == USRQUOTA) {
+ /*
+ * Try RQUOTAPROG because server doesn't seem to understand EXT_RQUOTAPROG. (NON-LINUX servers.)
+ */
+ args.arg.gqa_pathp = pathname;
+ args.arg.gqa_uid = dquot->dq_id;
+
+ /*
+ * Create a RPC client.
+ */
+ if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) {
+ /*
+ * Initialize unix authentication
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ /*
+ * Setup protocol timeout.
+ */
+ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);
+
+ /*
+ * Do RPC call and check result.
+ */
+ result = rquotaproc_getquota_1(&args.arg, clnt);
+ if (result != NULL && result->status == Q_OK)
+ clinet2utildqblk(&dquot->dq_dqb,
+ &result->getquota_rslt_u.gqr_rquota);
+
+ /*
+ * Destroy unix authentication and RPC client structure.
+ */
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+ }
+ }
+
+ free(fsname_tmp);
+}
+
+/*
+ * Set the requested quota information on a remote host.
+ */
+void rpc_rquota_set(int qcmd, struct dquot *dquot)
+{
+#if defined(RPC_SETQUOTA)
+ CLIENT *clnt;
+ setquota_rslt *result;
+ union {
+ setquota_args arg;
+ ext_setquota_args ext_arg;
+ } args;
+ char *fsname_tmp, *host, *pathname;
+ struct timeval timeout = { 2, 0 };
+
+ /*
+ * Convert host:pathname to seperate host and pathname.
+ */
+ fsname_tmp = (char *)smalloc(strlen(dquot->dq_h->qh_quotadev) + 1);
+ strcpy(fsname_tmp, dquot->dq_h->qh_quotadev);
+ host = fsname_tmp;
+
+ /*
+ * Strip off pathname on nfs mounted dir. Ignore entries of any
+ * automounter.
+ */
+ if ((pathname = strchr(fsname_tmp, ':')) == (char *)0 || *(pathname + 1) == '(')
+ return;
+
+ *pathname++ = '\0';
+
+ /*
+ * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program)
+ */
+ args.ext_arg.sqa_qcmd = qcmd;
+ args.ext_arg.sqa_pathp = pathname;
+ args.ext_arg.sqa_id = dquot->dq_id;
+ args.ext_arg.sqa_type = dquot->dq_h->qh_type;
+ cliutil2netdqblk(&args.ext_arg.sqa_dqblk, &dquot->dq_dqb);
+
+ if ((clnt = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp")) != NULL) {
+ /*
+ * Initialize unix authentication
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ /*
+ * Setup protocol timeout.
+ */
+ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);
+
+ /*
+ * Do RPC call and check result.
+ */
+ result = rquotaproc_setquota_2(&args.ext_arg, clnt);
+ if (result != NULL && result->status == Q_OK)
+ clinet2utildqblk(&dquot->dq_dqb, &result->setquota_rslt_u.sqr_rquota);
+
+ /*
+ * Destroy unix authentication and RPC client structure.
+ */
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+ else
+ result = NULL;
+
+ if (result == NULL || !result->status) {
+ if (dquot->dq_h->qh_type == USRQUOTA) {
+ /*
+ * Try RQUOTAPROG because server doesn't seem to understand EXT_RQUOTAPROG. (NON-LINUX servers.)
+ */
+ args.arg.sqa_qcmd = qcmd;
+ args.arg.sqa_pathp = pathname;
+ args.arg.sqa_id = dquot->dq_id;
+ cliutil2netdqblk(&args.arg.sqa_dqblk, &dquot->dq_dqb);
+
+ /*
+ * Create a RPC client.
+ */
+ if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) {
+ /*
+ * Initialize unix authentication
+ */
+ clnt->cl_auth = authunix_create_default();
+
+ /*
+ * Setup protocol timeout.
+ */
+ clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);
+
+ /*
+ * Do RPC call and check result.
+ */
+ result = rquotaproc_setquota_1(&args.arg, clnt);
+ if (result != NULL && result->status == Q_OK)
+ clinet2utildqblk(&dquot->dq_dqb,
+ &result->setquota_rslt_u.sqr_rquota);
+
+ /*
+ * Destroy unix authentication and RPC client structure.
+ */
+ auth_destroy(clnt->cl_auth);
+ clnt_destroy(clnt);
+ }
+ }
+ }
+ free(fsname_tmp);
+#endif
+}
+#endif
diff --git a/rquota_client.h b/rquota_client.h
new file mode 100644
index 0000000..7bf92b5
--- /dev/null
+++ b/rquota_client.h
@@ -0,0 +1,18 @@
+/*
+ *
+ * Header file for rquota functions
+ *
+ */
+
+#ifndef _RQUOTA_CLIENT_H
+#define _RQUOTA_CLIENT_H
+
+#include "quotaio.h"
+
+/* Collect the requested quota information from a remote host. */
+void rpc_rquota_get(struct dquot *dquot);
+
+/* Set the requested quota information on a remote host. */
+void rpc_rquota_set(int qcmd, struct dquot *dquot);
+
+#endif
diff --git a/rquota_server.c b/rquota_server.c
new file mode 100644
index 0000000..7468661
--- /dev/null
+++ b/rquota_server.c
@@ -0,0 +1,342 @@
+/*
+ * QUOTA An implementation of the diskquota system for the LINUX
+ * operating system. QUOTA is implemented using the BSD systemcall
+ * interface as the means of communication with the user level.
+ * Should work for all filesystems because of integration into the
+ * VFS layer of the operating system.
+ * This is based on the Melbourne quota system wich uses both user and
+ * group quota files.
+ *
+ * This part does the lookup of the info.
+ *
+ * Version: $Id: rquota_server.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <rpc/rpc.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <arpa/inet.h>
+#include <paths.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <netdb.h>
+#ifdef HOST_ACCESS
+#include <tcpd.h>
+#endif
+
+#include "mntopt.h"
+#include "quotaops.h"
+#include "bylabel.h"
+#include "rquota.h"
+#include "quotaio.h"
+#include "quotasys.h"
+#include "dqblk_rpc.h"
+
+#define STDIN_FILENO 0
+
+#define TYPE_EXTENDED 0x01
+#define ACTIVE 0x02
+
+#define FACILITY LOG_LOCAL7
+
+#ifndef MAXPATHNAMELEN
+#define MAXPATHNAMELEN BUFSIZ
+#endif
+
+#define NETTYPE AF_INET
+
+#ifdef HOSTS_ACCESS
+#define good_client(a,b) hosts_ctl("rpc.rquotad", b, inet_ntoa(a->sin_addr), "")
+#endif
+
+int allow_severity = LOG_INFO;
+int deny_severity = LOG_WARNING;
+
+/*
+ * Global unix authentication credentials.
+ */
+extern struct authunix_parms *unix_cred;
+
+int in_group(gid_t * gids, u_int len, gid_t gid)
+{
+ gid_t *gidsp = gids + len;
+
+ while (gidsp > gids)
+ if (*(--gids) == gid)
+ return 1;
+
+ return 0;
+}
+
+static inline void servnet2utildqblk(struct util_dqblk *u, sq_dqblk * n)
+{
+ u->dqb_bhardlimit = n->rq_bhardlimit;
+ u->dqb_bsoftlimit = n->rq_bsoftlimit;
+ u->dqb_ihardlimit = n->rq_fhardlimit;
+ u->dqb_isoftlimit = n->rq_fsoftlimit;
+ u->dqb_curspace = n->rq_curblocks << RPC_DQBLK_SIZE_BITS;
+ u->dqb_curinodes = n->rq_curfiles;
+ u->dqb_btime = n->rq_btimeleft;
+ u->dqb_itime = n->rq_ftimeleft;
+}
+
+static inline void servutil2netdqblk(struct rquota *n, struct util_dqblk *u)
+{
+ n->rq_bhardlimit = u->dqb_bhardlimit;
+ n->rq_bsoftlimit = u->dqb_bsoftlimit;
+ n->rq_fhardlimit = u->dqb_ihardlimit;
+ n->rq_fsoftlimit = u->dqb_isoftlimit;
+ n->rq_curblocks = (u->dqb_curspace + RPC_DQBLK_SIZE - 1) >> RPC_DQBLK_SIZE_BITS;
+ n->rq_curfiles = u->dqb_curinodes;
+ n->rq_btimeleft = u->dqb_btime;
+ n->rq_ftimeleft = u->dqb_itime;
+}
+
+setquota_rslt *setquotainfo(int flags, caddr_t * argp, struct svc_req *rqstp)
+{
+ static setquota_rslt result;
+
+#if defined(RPC_SETQUOTA)
+ union {
+ setquota_args *args;
+ ext_setquota_args *ext_args;
+ } arguments;
+ struct stat st;
+ dev_t device;
+ FILE *mntf;
+ struct util_dqblk dqblk;
+ struct dquot *dquot;
+ struct mntent *mnt;
+ char *pathname;
+ int id, qcmd, type;
+ struct quota_handle *handles[2] = { NULL, NULL };
+
+#ifdef HOSTS_ACCESS
+ struct hostent *hp;
+ struct sockaddr_in *addr;
+
+ addr = (svc_getcaller(rqstp->rq_xprt));
+ hp = gethostbyaddr((char *)&(addr->sin_addr), sizeof(addr->sin_addr), AF_INET);
+
+ if (!good_client(svc_getcaller(rqstp->rq_xprt), hp->h_name)) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+
+#endif
+
+ /*
+ * First check authentication.
+ */
+ if (flags & TYPE_EXTENDED) {
+ arguments.ext_args = (ext_setquota_args *) argp;
+
+ id = arguments.ext_args->sqa_id;
+ if (unix_cred->aup_uid != 0) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+
+ qcmd = arguments.ext_args->sqa_qcmd;
+ type = arguments.ext_args->sqa_type;
+ pathname = arguments.ext_args->sqa_pathp;
+ servnet2utildqblk(&dqblk, &arguments.ext_args->sqa_dqblk);
+ }
+ else {
+ arguments.args = (setquota_args *) argp;
+
+ id = arguments.args->sqa_id;
+ if (unix_cred->aup_uid != 0) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+
+ qcmd = arguments.args->sqa_qcmd;
+ type = USRQUOTA;
+ pathname = arguments.args->sqa_pathp;
+ servnet2utildqblk(&dqblk, &arguments.args->sqa_dqblk);
+ }
+
+ result.status = Q_NOQUOTA;
+ if (stat(pathname, &st) == -1)
+ return (&result);
+
+ device = st.st_dev;
+ result.setquota_rslt_u.sqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
+
+ mntf = setmntent(_PATH_MOUNTED, "r");
+ while ((mnt = getmntent(mntf))) {
+ if (stat(mnt->mnt_dir, &st) == -1)
+ continue;
+ if (st.st_dev != device)
+ continue;
+ if (!(handles[0] = init_io(mnt, type, -1)))
+ continue;
+ break;
+ }
+ endmntent(mntf);
+ if (!(dquot = handles[0]->qh_ops->read_dquot(handles[0], id)))
+ goto out;
+ if (qcmd == QCMD(Q_RPC_SETQLIM, type) || qcmd == QCMD(Q_RPC_SETQUOTA, type)) {
+ dquot->dq_dqb.dqb_bsoftlimit = dqblk.dqb_bsoftlimit;
+ dquot->dq_dqb.dqb_bhardlimit = dqblk.dqb_bhardlimit;
+ dquot->dq_dqb.dqb_isoftlimit = dqblk.dqb_isoftlimit;
+ dquot->dq_dqb.dqb_ihardlimit = dqblk.dqb_ihardlimit;
+ dquot->dq_dqb.dqb_btime = dqblk.dqb_btime;
+ dquot->dq_dqb.dqb_itime = dqblk.dqb_itime;
+ }
+ if (qcmd == QCMD(Q_RPC_SETUSE, type) || qcmd == QCMD(Q_RPC_SETQUOTA, type)) {
+ dquot->dq_dqb.dqb_curspace = dqblk.dqb_curspace;
+ dquot->dq_dqb.dqb_curinodes = dqblk.dqb_curinodes;
+ }
+ if (handles[0]->qh_ops->commit_dquot(dquot) == -1)
+ goto out;
+ result.status = Q_OK;
+ out:
+ dispose_handle_list(handles);
+#else
+ result.status = Q_EPERM;
+#endif
+ return (&result);
+}
+
+getquota_rslt *getquotainfo(int flags, caddr_t * argp, struct svc_req * rqstp)
+{
+ static getquota_rslt result;
+ union {
+ getquota_args *args;
+ ext_getquota_args *ext_args;
+ } arguments;
+ struct stat st;
+ dev_t device;
+ FILE *mntf;
+ struct dquot *dquot = NULL;
+ struct mntent *mnt;
+ char *pathname;
+ int id, type;
+ struct quota_handle *handles[2] = { NULL, NULL };
+
+#ifdef HOSTS_ACCESS
+ struct hostent *hp;
+ struct sockaddr_in *addr;
+
+ addr = (svc_getcaller(rqstp->rq_xprt));
+ hp = gethostbyaddr((char *)&(addr->sin_addr), sizeof(addr->sin_addr), AF_INET);
+
+ if (!good_client(svc_getcaller(rqstp->rq_xprt), hp->h_name)) {
+ return (FALSE);
+ }
+#endif
+
+ /*
+ * First check authentication.
+ */
+ if (flags & TYPE_EXTENDED) {
+ arguments.ext_args = (ext_getquota_args *) argp;
+ id = arguments.ext_args->gqa_id;
+ type = arguments.ext_args->gqa_type;
+ pathname = arguments.ext_args->gqa_pathp;
+
+ if (type == USRQUOTA && unix_cred->aup_uid && unix_cred->aup_uid != id) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+
+ if (type == GRPQUOTA && unix_cred->aup_uid && unix_cred->aup_gid != id &&
+ !in_group((gid_t *) unix_cred->aup_gids, unix_cred->aup_len, id)) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+ }
+ else {
+ arguments.args = (getquota_args *) argp;
+ id = arguments.args->gqa_uid;
+ type = USRQUOTA;
+ pathname = arguments.args->gqa_pathp;
+
+ if (unix_cred->aup_uid && unix_cred->aup_uid != id) {
+ result.status = Q_EPERM;
+ return (&result);
+ }
+ }
+
+ result.status = Q_NOQUOTA;
+
+ if (stat(pathname, &st) == -1)
+ return (&result);
+
+ device = st.st_dev;
+ result.getquota_rslt_u.gqr_rquota.rq_bsize = RPC_DQBLK_SIZE;
+
+ mntf = setmntent(_PATH_MOUNTED, "r");
+ while ((mnt = getmntent(mntf))) {
+ if (stat(mnt->mnt_dir, &st) == -1)
+ continue;
+ if (st.st_dev != device)
+ continue;
+ if (!(handles[0] = init_io(mnt, type, -1)))
+ continue;
+ break;
+ }
+ endmntent(mntf);
+ if (!(flags & ACTIVE) || QIO_ENABLED(handles[0]))
+ dquot = handles[0]->qh_ops->read_dquot(handles[0], id);
+ if (dquot) {
+ result.status = Q_OK;
+ result.getquota_rslt_u.gqr_rquota.rq_active =
+ QIO_ENABLED(handles[0]) ? TRUE : FALSE;
+ servutil2netdqblk(&result.getquota_rslt_u.gqr_rquota, &dquot->dq_dqb);
+ }
+ dispose_handle_list(handles);
+ return (&result);
+}
+
+/*
+ * Map RPC-entrypoints to local function names.
+ */
+getquota_rslt *rquotaproc_getquota_1_svc(getquota_args * argp, struct svc_req * rqstp)
+{
+ return (getquotainfo(0, (caddr_t *) argp, rqstp));
+}
+
+getquota_rslt *rquotaproc_getactivequota_1_svc(getquota_args * argp, struct svc_req * rqstp)
+{
+ return (getquotainfo(ACTIVE, (caddr_t *) argp, rqstp));
+}
+
+getquota_rslt *rquotaproc_getquota_2_svc(ext_getquota_args * argp, struct svc_req * rqstp)
+{
+ return (getquotainfo(TYPE_EXTENDED, (caddr_t *) argp, rqstp));
+}
+
+getquota_rslt *rquotaproc_getactivequota_2_svc(ext_getquota_args * argp, struct svc_req * rqstp)
+{
+ return (getquotainfo(TYPE_EXTENDED | ACTIVE, (caddr_t *) argp, rqstp));
+}
+
+setquota_rslt *rquotaproc_setquota_1_svc(setquota_args * argp, struct svc_req * rqstp)
+{
+ return (setquotainfo(0, (caddr_t *) argp, rqstp));
+}
+
+setquota_rslt *rquotaproc_setactivequota_1_svc(setquota_args * argp, struct svc_req * rqstp)
+{
+ return (setquotainfo(ACTIVE, (caddr_t *) argp, rqstp));
+}
+
+setquota_rslt *rquotaproc_setquota_2_svc(ext_setquota_args * argp, struct svc_req * rqstp)
+{
+ return (setquotainfo(TYPE_EXTENDED, (caddr_t *) argp, rqstp));
+}
+
+setquota_rslt *rquotaproc_setactivequota_2_svc(ext_setquota_args * argp, struct svc_req * rqstp)
+{
+ return (setquotainfo(TYPE_EXTENDED | ACTIVE, (caddr_t *) argp, rqstp));
+}
diff --git a/rquota_svc.c b/rquota_svc.c
new file mode 100644
index 0000000..368d212
--- /dev/null
+++ b/rquota_svc.c
@@ -0,0 +1,233 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <rpc/pmap_clnt.h> /* for pmap_unset */
+#include <stdio.h>
+#include <stdlib.h> /* getenv, exit */
+#include <string.h> /* strcmp */
+#include <memory.h>
+#include <unistd.h>
+
+#ifdef __STDC__
+#define SIG_PF void(*)(int)
+#endif
+
+#include "pot.h"
+#include "rquota.h"
+#include "quotasys.h"
+
+/*
+ * Global authentication credentials.
+ */
+struct authunix_parms *unix_cred;
+
+char **argvargs;
+int argcargs;
+static void rquotaprog_1(struct svc_req *rqstp, register SVCXPRT * transp)
+{
+ union {
+ getquota_args rquotaproc_getquota_1_arg;
+ setquota_args rquotaproc_setquota_1_arg;
+ getquota_args rquotaproc_getactivequota_1_arg;
+ setquota_args rquotaproc_setactivequota_1_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ char *(*local) (char *, struct svc_req *);
+
+ /*
+ * Don't bother authentication for NULLPROC.
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ (void)svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
+ return;
+ }
+
+ /*
+ * First get authentication.
+ */
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_UNIX:
+ unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+
+ switch (rqstp->rq_proc) {
+ case RQUOTAPROC_GETQUOTA:
+ xdr_argument = (xdrproc_t) xdr_getquota_args;
+ xdr_result = (xdrproc_t) xdr_getquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_getquota_1_svc;
+ break;
+
+ case RQUOTAPROC_SETQUOTA:
+ xdr_argument = (xdrproc_t) xdr_setquota_args;
+ xdr_result = (xdrproc_t) xdr_setquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_setquota_1_svc;
+ break;
+
+ case RQUOTAPROC_GETACTIVEQUOTA:
+ xdr_argument = (xdrproc_t) xdr_getquota_args;
+ xdr_result = (xdrproc_t) xdr_getquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_getactivequota_1_svc;
+ break;
+
+ case RQUOTAPROC_SETACTIVEQUOTA:
+ xdr_argument = (xdrproc_t) xdr_setquota_args;
+ xdr_result = (xdrproc_t) xdr_setquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_setactivequota_1_svc;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ (void)memset((char *)&argument, 0, sizeof(argument));
+ if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) {
+ svcerr_decode(transp);
+ return;
+ }
+ result = (*local) ((char *)&argument, rqstp);
+ if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) {
+ fprintf(stderr, _("unable to free arguments"));
+ exit(1);
+ }
+ return;
+}
+
+static void rquotaprog_2(struct svc_req *rqstp, register SVCXPRT * transp)
+{
+ union {
+ ext_getquota_args rquotaproc_getquota_2_arg;
+ ext_setquota_args rquotaproc_setquota_2_arg;
+ ext_getquota_args rquotaproc_getactivequota_2_arg;
+ ext_setquota_args rquotaproc_setactivequota_2_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ char *(*local) (char *, struct svc_req *);
+
+ /*
+ * Don't bother authentication for NULLPROC.
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ (void)svc_sendreply(transp, (xdrproc_t) xdr_void, (char *)NULL);
+ return;
+ }
+
+ /*
+ * First get authentication.
+ */
+ switch (rqstp->rq_cred.oa_flavor) {
+ case AUTH_UNIX:
+ unix_cred = (struct authunix_parms *)rqstp->rq_clntcred;
+ break;
+ case AUTH_NULL:
+ default:
+ svcerr_weakauth(transp);
+ return;
+ }
+
+ switch (rqstp->rq_proc) {
+ case RQUOTAPROC_GETQUOTA:
+ xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
+ xdr_result = (xdrproc_t) xdr_getquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_getquota_2_svc;
+ break;
+
+ case RQUOTAPROC_SETQUOTA:
+ xdr_argument = (xdrproc_t) xdr_ext_setquota_args;
+ xdr_result = (xdrproc_t) xdr_setquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_setquota_2_svc;
+ break;
+
+ case RQUOTAPROC_GETACTIVEQUOTA:
+ xdr_argument = (xdrproc_t) xdr_ext_getquota_args;
+ xdr_result = (xdrproc_t) xdr_getquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_getactivequota_2_svc;
+ break;
+
+ case RQUOTAPROC_SETACTIVEQUOTA:
+ xdr_argument = (xdrproc_t) xdr_ext_setquota_args;
+ xdr_result = (xdrproc_t) xdr_setquota_rslt;
+ local = (char *(*)(char *, struct svc_req *))rquotaproc_setactivequota_2_svc;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ (void)memset((char *)&argument, 0, sizeof(argument));
+ if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) {
+ svcerr_decode(transp);
+ return;
+ }
+ result = (*local) ((char *)&argument, rqstp);
+ if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+ svcerr_systemerr(transp);
+ }
+ if (!svc_freeargs(transp, xdr_argument, (caddr_t) & argument)) {
+ fprintf(stderr, _("unable to free arguments"));
+ exit(1);
+ }
+ return;
+}
+
+int main(int argc, char **argv)
+{
+ register SVCXPRT *transp;
+
+ argcargs = argc;
+ argvargs = argv;
+
+ gettexton();
+ warn_new_kernel(-1);
+
+ (void)pmap_unset(RQUOTAPROG, RQUOTAVERS);
+ (void)pmap_unset(RQUOTAPROG, EXT_RQUOTAVERS);
+
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ fprintf(stderr, _("cannot create udp service."));
+ exit(1);
+ }
+ if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_UDP)) {
+ fprintf(stderr, _("unable to register (RQUOTAPROG, RQUOTAVERS, udp)."));
+ exit(1);
+ }
+ if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_UDP)) {
+ fprintf(stderr, _("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, udp)."));
+ exit(1);
+ }
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL) {
+ fprintf(stderr, _("cannot create tcp service."));
+ exit(1);
+ }
+ if (!svc_register(transp, RQUOTAPROG, RQUOTAVERS, rquotaprog_1, IPPROTO_TCP)) {
+ fprintf(stderr, _("unable to register (RQUOTAPROG, RQUOTAVERS, tcp)."));
+ exit(1);
+ }
+ if (!svc_register(transp, RQUOTAPROG, EXT_RQUOTAVERS, rquotaprog_2, IPPROTO_TCP)) {
+ fprintf(stderr, _("unable to register (RQUOTAPROG, EXT_RQUOTAVERS, tcp)."));
+ exit(1);
+ }
+
+ daemon(1, 1);
+ svc_run();
+ fprintf(stderr, _("svc_run returned"));
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/rquotad.8 b/rquotad.8
new file mode 100644
index 0000000..e6bbb1e
--- /dev/null
+++ b/rquotad.8
@@ -0,0 +1,45 @@
+.TH RQUOTAD 8
+.SH NAME
+rquotad, rpc.rquotad \- remote quota server
+.SH SYNOPSIS
+.B rpc.rquotad
+.SH DESCRIPTION
+.LP
+.IX "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX daemons "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX "user quotas" "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX "disk quotas" "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX "quotas" "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX "filesystem" "rquotad daemon" "" "\fLrquotad\fP \(em remote quota server"
+.IX "remote procedure call services" "rquotad" "" "\fLrquotad\fP \(em remote quota server"
+.B rquotad
+is an
+.BR rpc (3N)
+server which returns quotas for a user of a local filesystem
+which is mounted by a remote machine over the
+.SM NFS\s0.
+The results are used by
+.BR quota (1)
+to display user quotas for remote filesystems.
+The
+.B rquotad
+daemon is normally started at boot time from the
+system startup scripts.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+default filesystems
+.PD
+.SH "SEE ALSO"
+.BR quota (1),
+.BR rpc (3N),
+.BR nfs (5),
+.BR services (5),
+.BR inetd (8)
diff --git a/set_limits_example.c b/set_limits_example.c
new file mode 100644
index 0000000..52af20c
--- /dev/null
+++ b/set_limits_example.c
@@ -0,0 +1,60 @@
+#include <sys/types.h>
+#include <sys/quota.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "pot.h"
+
+int copy_user_quota_limits(const char *block_device, uid_t from, uid_t to)
+{
+ struct dqblk dq;
+
+ if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), block_device, from, (caddr_t) & dq) == 0) {
+ if (quotactl(QCMD(Q_SETQLIM, USRQUOTA), block_device, to, (caddr_t) & dq) == 0) {
+ return (0);
+ }
+ else {
+ fprintf(stderr,
+ _
+ ("copy_user_quota_limits: Failed to set userquota for uid %ld : %s\n"),
+ to, strerror(errno));
+ return (1);
+ }
+ }
+ else {
+ fprintf(stderr,
+ _("copy_user_quota_limits: Failed to get userquota for uid %ld : %s\n"),
+ from, strerror(errno));
+ return (1);
+ }
+}
+
+int copy_group_quota_limits(const char *block_device, gid_t from, gid_t to)
+{
+ struct dqblk dq;
+
+ if (quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), block_device, from, (caddr_t) & dq) == 0) {
+ if (quotactl(QCMD(Q_SETQLIM, GRPQUOTA), block_device, to, (caddr_t) & dq) == 0) {
+ return (0);
+ }
+ else {
+ fprintf(stderr,
+ _
+ ("copy_group_quota_limits: Failed to set groupquota for uid %ld : %s\n"),
+ to, strerror(errno));
+ return (1);
+ }
+ }
+ else {
+ fprintf(stderr,
+ _("copy_group_quota_limits: Failed to get groupquota for uid %ld : %s\n"),
+ from, strerror(errno));
+ return (1);
+ }
+}
+
+main(int argc, char **argv)
+{
+ gettexton();
+ copy_user_quota_limits("/dev/hda8", 152, 151);
+}
diff --git a/setquota.8 b/setquota.8
new file mode 100644
index 0000000..4e4323d
--- /dev/null
+++ b/setquota.8
@@ -0,0 +1,88 @@
+.TH SETQUOTA 8
+.SH NAME
+setquota \- set disk quotas
+.SH SYNOPSIS
+.B /usr/sbin/setquota
+[
+.B \-nr
+]
+[
+.B \-u
+|
+.B \-g
+]
+.I name
+.I filesystem
+.I block-softlimit
+.I block-hardlimit
+.I inode-softlimit
+.I inode-hardlimit
+.LP
+.B /usr/sbin/setquota
+[
+.B \-nr
+]
+[
+.B \-u
+|
+.B \-g
+]
+[
+.B \-p protoname
+]
+.I name
+.I filesystem
+.SH DESCRIPTION
+.IX "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
+.IX set "disk quotas \(em \fLsetquota\fP"
+.IX "disk quotas" "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
+.IX "disk quotas" "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
+.IX "quotas" "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
+.IX "filesystem" "setquota command" "" "\fLsetquota\fP \(em set disk quotas"
+.B setquota
+is a command line quota editor.
+The filesystem, user/group name and new quotas for this
+filesystem can be specified on the command line.
+.TP
+.B -n
+Consider
+.I name
+to be a numeric ID (don't lookup user/group names).
+.TP
+.B -r
+Edit also remote quota use rpc.rquotad on remote server to set quota.
+.TP
+.B -u
+Set user quotas for named user. This is the default.
+.TP
+.B -g
+Set group quotas for named group.
+.TP
+.B -p \f2protoname\f1
+Use quota settings of user or group
+.I protoname
+to set the quota for the named user or group.
+.PP
+To disable a quota, set the coresponding parameter to 0. To change quotas
+for several filesystems, invoke once for each filesystem.
+.PP
+Only the super-user may edit quotas.
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user or aquota.group
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user or quota.group
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/mtab
+mounted filesystems
+.PD
+.SH SEE ALSO
+.BR edquota (8),
+.BR quota (1),
+.BR quotactl (2),
+.BR quotacheck (8),
+.BR quotaon (8),
+.BR repquota (8)
diff --git a/setquota.c b/setquota.c
new file mode 100644
index 0000000..63f80c4
--- /dev/null
+++ b/setquota.c
@@ -0,0 +1,232 @@
+/*
+ *
+ * Set disk quota from command line
+ *
+ */
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <getopt.h>
+
+#if defined(RPC)
+#include "rquota.h"
+#include "rquota_client.h"
+#endif
+#include "pot.h"
+#include "quotaops.h"
+#include "common.h"
+#include "quotasys.h"
+
+#define FL_USER 1
+#define FL_GROUP 2
+#define FL_RPC 4
+#define FL_ALL 8
+#define FL_PROTO 16
+#define FL_GRACE 32
+
+int flags, fmt = -1;
+char **mnt;
+int mntcnt;
+qid_t protoid, id;
+struct util_dqblk toset;
+
+/* Print usage information */
+static void usage(void)
+{
+#if defined(RPC_SETQUOTA)
+ fprintf(stderr, _("Usage:\n"
+ " setquota [-u|-g] [-r] [-F quotaformat] <user|group>\n"
+ "\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-r] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"));
+#else
+ fprintf(stderr, _("Usage:\n"
+ " setquota [-u|-g] [-F quotaformat] <user|group>\n"
+ "\t<block-softlimit> <block-hardlimit> <inode-softlimit> <inode-hardlimit> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-F quotaformat] <-p protouser|protogroup> <user|group> -a|<filesystem>...\n"
+ " setquota [-u|-g] [-F quotaformat] -t <blockgrace> <inodegrace> -a|<filesystem>...\n"));
+#endif
+ fprintf(stderr, _("Bugs to: %s\n"), MY_EMAIL);
+ exit(1);
+}
+
+/* Convert string to number - print error message in case of failure */
+static long parse_num(char *str, char *msg)
+{
+ char *errch;
+ long ret = strtol(str, &errch, 0);
+
+ if (*errch) {
+ fprintf(stderr, _("Bad %s: %s\n"), msg, str);
+ usage();
+ }
+ return ret;
+}
+
+/* Convert our flags to quota type */
+static inline int flag2type(int flags)
+{
+ if (flags & FL_USER)
+ return USRQUOTA;
+ if (flags & FL_GROUP)
+ return GRPQUOTA;
+ return -1;
+}
+
+/* Parse options of setquota */
+static void parse_options(int argcnt, char **argstr)
+{
+ int ret, otherargs;
+ char *protoname = NULL;
+
+#ifdef RPC_SETQUOTA
+ char *opts = "igp:urVF:ta";
+#else
+ char *opts = "igp:uVF:ta";
+#endif
+
+#ifdef RPC_SETQUOTA
+ flags |= FL_RPC;
+#endif
+
+ while ((ret = getopt(argcnt, argstr, opts)) != EOF) {
+ switch (ret) {
+ case '?':
+ case 'h':
+ usage();
+ case 'g':
+ flags |= FL_GROUP;
+ break;
+ case 'u':
+ flags |= FL_USER;
+ break;
+ case 'p':
+ flags |= FL_PROTO;
+ protoname = optarg;
+ break;
+ case 'r':
+ flags &= ~FL_RPC;
+ break;
+ case 'a':
+ flags |= FL_ALL;
+ break;
+ case 't':
+ flags |= FL_GRACE;
+ break;
+ case 'F':
+ if ((fmt = name2fmt(optarg)) == QF_ERROR)
+ exit(1);
+ break;
+ case 'V':
+ version();
+ break;
+ }
+ }
+ if (flags & FL_USER && flags & FL_GROUP) {
+ fputs(_("Group and user quotas can't be used together.\n"), stderr);
+ usage();
+ }
+ if (flags & FL_PROTO && flags & FL_GRACE) {
+ fputs(_("Prototype user has no sense when editting grace times.\n"), stderr);
+ usage();
+ }
+ if (flags & FL_GRACE)
+ otherargs = 2;
+ else {
+ otherargs = 1;
+ if (!(flags & FL_PROTO))
+ otherargs += 4;
+ }
+ if (optind + otherargs > argcnt) {
+ fputs(_("Bad number of arguments.\n"), stderr);
+ usage();
+ }
+ if (!(flags & (FL_USER | FL_GROUP)))
+ flags |= FL_USER;
+ if (!(flags & FL_GRACE)) {
+ id = name2id(argstr[optind++], flag2type(flags));
+ if (!(flags & FL_PROTO)) {
+ toset.dqb_bsoftlimit = parse_num(argstr[optind++], _("block softlimit"));
+ toset.dqb_bhardlimit = parse_num(argstr[optind++], _("block hardlimit"));
+ toset.dqb_isoftlimit = parse_num(argstr[optind++], _("inode softlimit"));
+ toset.dqb_ihardlimit = parse_num(argstr[optind++], _("inode hardlimit"));
+ }
+ else
+ protoid = name2id(protoname, flag2type(flags));
+ }
+ else {
+ toset.dqb_btime = parse_num(argstr[optind++], _("block grace time"));
+ toset.dqb_itime = parse_num(argstr[optind++], _("inode grace time"));
+ }
+ if (!(flags & FL_ALL)) {
+ mntcnt = argcnt - optind;
+ mnt = argstr + optind;
+ if (!mntcnt) {
+ fputs(_("Mountpoint not specified.\n"), stderr);
+ usage();
+ }
+ }
+}
+
+/* Set user limits */
+static void setlimits(struct quota_handle **handles)
+{
+ struct dquot *q, *protoq, *protoprivs = NULL, *curprivs;
+
+ curprivs = getprivs(id, handles);
+ if (flags & FL_PROTO) {
+ protoprivs = getprivs(protoid, handles);
+ for (q = curprivs, protoq = protoprivs; q; q = q->dq_next, protoq = protoq->dq_next) {
+ q->dq_dqb.dqb_bsoftlimit = protoq->dq_dqb.dqb_bsoftlimit;
+ q->dq_dqb.dqb_bhardlimit = protoq->dq_dqb.dqb_bhardlimit;
+ q->dq_dqb.dqb_isoftlimit = protoq->dq_dqb.dqb_isoftlimit;
+ q->dq_dqb.dqb_ihardlimit = protoq->dq_dqb.dqb_ihardlimit;
+ }
+ freeprivs(protoprivs);
+ }
+ else {
+ for (q = curprivs; q; q = q->dq_next) {
+ q->dq_dqb.dqb_bsoftlimit = toset.dqb_bsoftlimit;
+ q->dq_dqb.dqb_bhardlimit = toset.dqb_bhardlimit;
+ q->dq_dqb.dqb_isoftlimit = toset.dqb_isoftlimit;
+ q->dq_dqb.dqb_ihardlimit = toset.dqb_ihardlimit;
+ }
+ }
+ putprivs(curprivs);
+ freeprivs(curprivs);
+}
+
+/* Set grace times */
+static void setgraces(struct quota_handle **handles)
+{
+ int i;
+
+ for (i = 0; handles[i]; i++) {
+ handles[i]->qh_info.dqi_bgrace = toset.dqb_btime;
+ handles[i]->qh_info.dqi_igrace = toset.dqb_itime;
+ mark_quotafile_info_dirty(handles[i]);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct quota_handle **handles;
+
+ gettexton();
+ parse_options(argc, argv);
+ warn_new_kernel(fmt);
+
+ if (flags & FL_ALL)
+ handles = create_handle_list(0, NULL, flag2type(flags), fmt, !(flags & FL_RPC));
+ else
+ handles = create_handle_list(mntcnt, mnt, flag2type(flags), fmt, !(flags & FL_RPC));
+
+ if (flags & FL_GRACE)
+ setgraces(handles);
+ else
+ setlimits(handles);
+ dispose_handle_list(handles);
+ return 0;
+}
diff --git a/setup_quota_group b/setup_quota_group
new file mode 100755
index 0000000..7343fea
--- /dev/null
+++ b/setup_quota_group
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+if [ $# -lt 2 ]; then
+ echo "Usage: $0 proto_type_user group"
+ exit 1
+fi
+
+gid=`cat /etc/group | grep "^$2" | cut -d: -f3`
+for user in `cat /etc/passwd | grep ".*:.*:$gid:" | cut -d: -f1`
+do
+ edquota -p $1 $user
+done
diff --git a/warnquota.8 b/warnquota.8
new file mode 100644
index 0000000..9acd434
--- /dev/null
+++ b/warnquota.8
@@ -0,0 +1,37 @@
+.TH WARNQUOTA 8
+.SH NAME
+warnquota \- send mail to users over quota
+.SH SYNOPSIS
+.B warnquota
+.SH DESCRIPTION
+.B warnquota
+checks the disk quota for each filesystem and mails a warning
+message to those users who have reached their limit.
+It is typically run via
+.BR cron (8).
+.SH FILES
+.PD 0
+.TP 20
+.B aquota.user
+quota file at the filesystem root (version 2 quota, non-XFS filesystems)
+.TP
+.B quota.user
+quota file at the filesystem root (version 1 quota, non-XFS filesystems)
+.TP
+.B /etc/warnquota.conf
+configuration file
+.TP
+.B /etc/mtab
+default filesystems
+.TP
+.B /etc/passwd
+default set of users
+.PD
+.SH "SEE ALSO"
+.BR quota (1),
+.BR cron (8),
+.BR edquota (8).
+.SH AUTHORS
+.BR warnquota (8)
+was written by Marco van Wieringen <mvw@planets.elm.net>.
+This reference page written by Heiko Schlittermann <heiko@lotte.sax.de>.
diff --git a/warnquota.c b/warnquota.c
new file mode 100644
index 0000000..a4516d5
--- /dev/null
+++ b/warnquota.c
@@ -0,0 +1,374 @@
+/*
+ * QUOTA An implementation of the diskquota system for the LINUX operating
+ * system. QUOTA is implemented using the BSD systemcall interface
+ * as the means of communication with the user level. Should work for
+ * all filesystems because of integration into the VFS layer of the
+ * operating system. This is based on the Melbourne quota system wich
+ * uses both user and group quota files.
+ *
+ * Program to mail to users that they are over there quota.
+ *
+ * Author: Marco van Wieringen <mvw@planets.elm.net>
+ *
+ * Version: $Id: warnquota.c,v 1.1 2001/03/23 12:03:27 jkar8572 Exp $
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+
+#include "mntopt.h"
+#include "pot.h"
+#include "bylabel.h"
+#include "common.h"
+#include "quotasys.h"
+#include "quotaio.h"
+
+/* these are just defaults, overridden in the WARNQUOTA_CONF file */
+#define MAIL_CMD "/usr/lib/sendmail -t"
+#define FROM "support@localhost"
+#define SUBJECT "Disk Quota usage on system"
+#define CC_TO "root"
+#define SUPPORT "support@localhost"
+#define PHONE "(xxx) xxx-xxxx or (yyy) yyy-yyyy"
+
+#define DEF_MESSAGE _("Hi,\n\nWe noticed that you are in violation with the quotasystem\n" \
+ "used on this system. We have found the following violations:\n\n")
+#define DEF_SIGNATURE _("\nWe hope that you will cleanup before your grace period expires.\n" \
+ "\nBasically, this means that the system thinks you are using more disk space\n" \
+ "on the above partition(s) than you are allowed. If you do not delete files\n" \
+ "and get below your quota before the grace period expires, the system will\n" \
+ "prevent you from creating new files.\n\n" \
+ "For additional assistance, please contact us at %s\nor via " \
+ "phone at %s.\n")
+
+#define QUOTATAB "/etc/quotatab"
+#define CNF_BUFFER 2048
+#define WARNQUOTA_CONF "/etc/warnquota.conf"
+
+struct usage {
+ char *devicename;
+ struct util_dqblk dq_dqb;
+ struct usage *next;
+};
+
+struct configparams {
+ char mail_cmd[CNF_BUFFER];
+ char from[CNF_BUFFER];
+ char subject[CNF_BUFFER];
+ char cc_to[CNF_BUFFER];
+ char support[CNF_BUFFER];
+ char phone[CNF_BUFFER];
+};
+
+struct offenderlist {
+ int offender_id;
+ char *offender_name;
+ struct usage *usage;
+ struct offenderlist *next;
+};
+
+typedef struct quotatable {
+ char *devname;
+ char *devdesc;
+} quotatable_t;
+
+int qtab_i = 0;
+quotatable_t *quotatable = (quotatable_t *) NULL;
+
+/*
+ * Global pointers to list.
+ */
+static struct offenderlist *offenders = (struct offenderlist *)0;
+
+struct offenderlist *add_offender(int id)
+{
+ struct passwd *pwd;
+ struct offenderlist *offender;
+
+ if ((pwd = getpwuid(id)) == (struct passwd *)0)
+ return ((struct offenderlist *)0);
+
+ offender = (struct offenderlist *)smalloc(sizeof(struct offenderlist));
+
+ offender->offender_id = id;
+ offender->offender_name = (char *)smalloc(strlen(pwd->pw_name) + 1);
+ offender->usage = (struct usage *)NULL;
+ strcpy(offender->offender_name, pwd->pw_name);
+ offender->next = offenders;
+ offenders = offender;
+ return offender;
+}
+
+void add_offence(struct dquot *dquot)
+{
+ struct offenderlist *lptr;
+ struct usage *usage;
+
+ for (lptr = offenders; lptr; lptr = lptr->next)
+ if (lptr->offender_id == dquot->dq_id)
+ break;
+
+ if (!lptr)
+ if (!(lptr = add_offender(dquot->dq_id)))
+ return;
+
+ usage = (struct usage *)smalloc(sizeof(struct usage));
+ memcpy(&usage->dq_dqb, &dquot->dq_dqb, sizeof(struct util_dqblk));
+
+ usage->devicename = sstrdup(dquot->dq_h->qh_quotadev);
+ /*
+ * Stuff it in front
+ */
+ usage->next = lptr->usage;
+ lptr->usage = usage;
+}
+
+int check_offence(struct dquot *dquot)
+{
+ if (
+ (dquot->dq_dqb.dqb_bsoftlimit
+ && toqb(dquot->dq_dqb.dqb_curspace) >= dquot->dq_dqb.dqb_bsoftlimit)
+ || (dquot->dq_dqb.dqb_isoftlimit
+ && dquot->dq_dqb.dqb_curinodes >= dquot->dq_dqb.dqb_isoftlimit)) add_offence(dquot);
+ return 0;
+}
+
+void mail_user(struct offenderlist *offender, struct configparams *config)
+{
+ struct usage *lptr;
+ FILE *fp;
+ int cnt;
+ char timebuf[MAXTIMELEN];
+ struct util_dqblk *dqb;
+
+ if ((fp = popen(config->mail_cmd, "w")) != (FILE *) 0) {
+ fprintf(fp, "From: %s\n", config->from);
+ fprintf(fp, "Reply-To: %s\n", config->support);
+ fprintf(fp, "Subject: %s\n", config->subject);
+ fprintf(fp, "To: %s\n", offender->offender_name);
+ fprintf(fp, "Cc: %s\n", config->cc_to);
+ fprintf(fp, "\n");
+ fprintf(fp, DEF_MESSAGE);
+ for (lptr = offender->usage; lptr != (struct usage *)0; lptr = lptr->next) {
+ dqb = &lptr->dq_dqb;
+ for (cnt = 0; cnt < qtab_i; cnt++) {
+ if (!strncmp
+ (quotatable[cnt].devname, lptr->devicename,
+ strlen(quotatable[cnt].devname)))
+ fprintf(fp, "\n%s\n", quotatable[cnt].devdesc);
+ }
+ fprintf(fp,
+ _
+ ("\n Block limits File limits\n"));
+ fprintf(fp,
+ _
+ ("Filesystem used soft hard grace used soft hard grace\n"));
+ if (strlen(lptr->devicename) > 15)
+ fprintf(fp, "%s\n%15s", lptr->devicename, "");
+ else
+ fprintf(fp, "%-15s", lptr->devicename);
+ if (dqb->dqb_bsoftlimit && dqb->dqb_bsoftlimit <= toqb(dqb->dqb_curspace))
+ difftime2str(dqb->dqb_btime, timebuf);
+ else
+ timebuf[0] = '\0';
+ fprintf(fp, "%c%c%8Lu%8Lu%8Lu%7s",
+ dqb->dqb_bsoftlimit
+ && toqb(dqb->dqb_curspace) >= dqb->dqb_bsoftlimit ? '+' : '-',
+ dqb->dqb_isoftlimit
+ && dqb->dqb_curinodes >= dqb->dqb_isoftlimit ? '+' : '-',
+ (long long)toqb(dqb->dqb_curspace), (long long)dqb->dqb_bsoftlimit,
+ (long long)dqb->dqb_bhardlimit, timebuf);
+ if (dqb->dqb_isoftlimit && dqb->dqb_isoftlimit <= dqb->dqb_curinodes)
+ difftime2str(dqb->dqb_itime, timebuf);
+ else
+ timebuf[0] = '\0';
+ fprintf(fp, " %6Lu%6Lu%6Lu%7s\n\n",
+ (long long)dqb->dqb_curinodes,
+ (long long)dqb->dqb_isoftlimit,
+ (long long)dqb->dqb_ihardlimit, timebuf);
+ }
+ fprintf(fp, DEF_SIGNATURE, config->support, config->phone);
+ fclose(fp);
+ }
+}
+
+void mail_to_offenders(struct configparams *config)
+{
+ struct offenderlist *lptr;
+
+ /*
+ * Dump offenderlist.
+ */
+ for (lptr = offenders; lptr != (struct offenderlist *)0; lptr = lptr->next)
+ mail_user(lptr, config);
+}
+
+void get_quotatable(void)
+{
+ FILE *fp;
+ char buffer[2048], *filename, *colpos;
+
+ filename = (char *)smalloc(strlen(QUOTATAB) + 1);
+ sprintf(filename, "%s", QUOTATAB);
+
+ if ((fp = fopen(filename, "r")) == (FILE *) NULL)
+ return;
+
+ for (qtab_i = 0;
+ quotatable =
+ (quotatable_t *) realloc(quotatable, sizeof(quotatable_t) * (qtab_i + 1)),
+ fgets(buffer, sizeof(buffer), fp) != (char *)NULL; qtab_i++) {
+ if ((colpos = strchr(buffer, ':'))) {
+ *colpos = 0;
+ quotatable[qtab_i].devname = (char *)smalloc(strlen(buffer) + 1);
+ strcpy(quotatable[qtab_i].devname, buffer);
+ quotatable[qtab_i].devdesc = (char *)smalloc(strlen(++colpos) + 1);
+ strcpy(quotatable[qtab_i].devdesc, colpos);
+ if ((colpos = strchr(quotatable[qtab_i].devdesc, '\n')))
+ *colpos = 0;
+ while ((colpos = strchr(quotatable[qtab_i].devdesc, '|')))
+ *colpos = '\n';
+ }
+
+ if (buffer[0] == '#' || /* comment */
+ !quotatable[qtab_i].devname || !quotatable[qtab_i].devdesc ||
+ strlen(quotatable[qtab_i].devname) < 2 ||
+ strlen(quotatable[qtab_i].devdesc) < 2 /* stupid root */ )qtab_i--;
+ }
+ fclose(fp);
+ free(filename);
+}
+
+/*
+ * Wipe spaces, tabs, quotes and newlines from beginning and end of string
+ */
+void stripstring(char **buff)
+{
+ char *p;
+
+ /* first put a \0 at the tight place to end the string */
+ p = *buff + strlen(*buff) - 1;
+ while (*p == ' ' || *p == '\n' || *p == '\t' || *p == '"' || *p == '\'')
+ p--;
+ p[1] = 0;
+
+ /* then determine the position to start */
+ p = *buff;
+ while (*p == ' ' || *p == '\n' || *p == '\t' || *p == '"' || *p == '\'')
+ p++;
+
+ *buff = p;
+}
+
+/*
+ * Reads config parameters from configfile
+ * uses default values if error occurs
+ */
+void readconfigfile(const char *filename, struct configparams *config)
+{
+ FILE *fp;
+ char *buff;
+ char *var;
+ char *value;
+ char *pos;
+ int line;
+
+ /* set default values */
+ strncpy(config->mail_cmd, MAIL_CMD, CNF_BUFFER);
+ strncpy(config->from, FROM, CNF_BUFFER);
+ strncpy(config->subject, SUBJECT, CNF_BUFFER);
+ strncpy(config->cc_to, CC_TO, CNF_BUFFER);
+ strncpy(config->support, SUPPORT, CNF_BUFFER);
+ strncpy(config->phone, PHONE, CNF_BUFFER);
+
+ fp = fopen(filename, "r");
+ if (fp == (FILE *) NULL) { /* if config file doesn't exist or is not readable */
+ return;
+ }
+
+ buff = (char *)smalloc(CNF_BUFFER);
+ line = 0;
+ while (fgets(buff, CNF_BUFFER, fp)) { /* start reading lines */
+ line++;
+
+ /* check for comments or empty lines */
+ if (buff[0] == '#' || buff[0] == ';' || buff[0] == '\n')
+ continue;
+
+ /* check for a '=' char */
+ if ((pos = strchr(buff, '='))) {
+ pos[0] = '\0'; /* split buff in two parts: var and value */
+ var = buff;
+ value = pos + 1;
+
+ stripstring(&var); /* clean up var and value */
+ stripstring(&value);
+
+ /* check if var matches anything */
+ if (!strncmp(var, "MAIL_CMD", CNF_BUFFER)) {
+ strncpy(config->mail_cmd, value, CNF_BUFFER);
+ }
+ else if (!strncmp(var, "FROM", CNF_BUFFER)) {
+ strncpy(config->from, value, CNF_BUFFER);
+ }
+ else if (!strncmp(var, "SUBJECT", CNF_BUFFER)) {
+ strncpy(config->subject, value, CNF_BUFFER);
+ }
+ else if (!strncmp(var, "CC_TO", CNF_BUFFER)) {
+ strncpy(config->cc_to, value, CNF_BUFFER);
+ }
+ else if (!strncmp(var, "SUPPORT", CNF_BUFFER)) {
+ strncpy(config->support, value, CNF_BUFFER);
+ }
+ else if (!strncmp(var, "PHONE", CNF_BUFFER)) {
+ strncpy(config->phone, value, CNF_BUFFER);
+ }
+ else { /* not matched at all */
+ fprintf(stderr, "Error in config file (line %d), ignoring\n", line);
+ }
+ }
+ else { /* no '=' char in this line */
+ fprintf(stderr, "Possible error in config file (line %d), ignoring\n",
+ line);
+ }
+ }
+ fclose(fp);
+
+ free(buff);
+
+ return;
+}
+
+void warn_quota(void)
+{
+ struct quota_handle **handles;
+ struct configparams config;
+ int i;
+
+ readconfigfile(WARNQUOTA_CONF, &config);
+
+ handles = create_handle_list(0, NULL, USRQUOTA, -1, 1);
+ for (i = 0; handles[i]; i++)
+ handles[i]->qh_ops->scan_dquots(handles[i], check_offence);
+ get_quotatable();
+ mail_to_offenders(&config);
+}
+
+int main(int argc, char **argv)
+{
+ gettexton();
+ warn_new_kernel(-1);
+ warn_quota();
+ return 0;
+}
diff --git a/warnquota.conf b/warnquota.conf
new file mode 100644
index 0000000..c957c0e
--- /dev/null
+++ b/warnquota.conf
@@ -0,0 +1,16 @@
+# this is an example warnquota.conf
+#
+; ; and # type comments are allowed
+# and even blank lines
+
+# values can be quoted:
+MAIL_CMD = "/usr/my/sendmail/instead/sendmail -t"
+FROM = "bas@localhost"
+# but they don't have to be:
+SUBJECT = Hey, user, clean up your account!
+CC_TO = "sysadm@localhost"
+SUPPORT = "support@myhost.com"
+PHONE = "(123) 456-1111 or (222) 333-4444"
+#
+# end of example warnquota.conf file
+#
diff --git a/xqmstats.c b/xqmstats.c
new file mode 100644
index 0000000..ed66e46
--- /dev/null
+++ b/xqmstats.c
@@ -0,0 +1,53 @@
+/*
+ * Display XFS quota manager statistics from /proc.
+ */
+
+#ident "Copyright (c) 2001 Silicon Graphics, Inc."
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include "pot.h"
+
+#define XQMFILE "/proc/fs/xfs/xqm"
+#define STATFILE "/proc/fs/xfs/stat"
+
+int main(int argc, char **argv)
+{
+ FILE *stats, *xqm;
+ char buffer[256];
+ unsigned values[8];
+
+ gettexton();
+
+ memset(values, 0, sizeof(unsigned) * 8);
+
+ if ((stats = fopen(STATFILE, "r")) == NULL || (xqm = fopen(XQMFILE, "r")) == NULL) {
+ fprintf(stderr, "The running kernel does not support XFS\n");
+ return 1;
+ }
+ while (!feof(stats)) {
+ fgets(buffer, 256, stats);
+ if (sscanf(buffer, "qm %u %u %u %u %u %u %u %u\n",
+ &values[0], &values[1], &values[2], &values[3],
+ &values[4], &values[5], &values[6], &values[7]) == 8)
+ break;
+ }
+ if (!feof(stats)) {
+ printf(_("XFS Quota Manager dquot statistics\n"));
+ printf(_(" reclaims: %u\n"), values[0]);
+ printf(_(" missed reclaims: %u\n"), values[1]);
+ printf(_(" dquot dups: %u\n"), values[2]);
+ printf(_(" cache misses: %u\n"), values[3]);
+ printf(_(" cache hits: %u\n"), values[4]);
+ printf(_(" dquot wants: %u\n"), values[5]);
+ printf(_(" shake reclaims: %u\n"), values[6]);
+ printf(_(" inact reclaims: %u\n"), values[7]);
+ }
+ if (fscanf(xqm, "%u %u %u %u\n", &values[0], &values[1], &values[2], &values[3]) == 4)
+ printf(_("Maximum %u dquots (currently %u incore, %u on freelist)\n"), values[0],
+ values[1], values[3]);
+ fclose(stats);
+ fclose(xqm);
+ return 0;
+}