Subject: mount(8) options, !/etc/mtab, libkern.a, MANY others (#295 part 4 of 8) Index: many/many 2.11BSD Description: Mount(8) does not pass options other than 'readonly' thru to the kernel even though the kernel understands many more options than that. /etc/mtab is not needed any longer because applications (mount, umount, others) can obtain the list of mounted filesystems via getmntinfo(3), or getfsstat(2) There are copies of 15 libc routines in the kernel directories. These are invariant but nevertheless are always being recompiled/assembled whenever a kernel is built. Repeat-By: It sounds inadequate, but, "observation". Fix: This is #295 (part 4 of 8). Please refer to part 1 (#292) for detailed instructions and a description of contents. ----------------------------cut here------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # /usr/src/lib/libc/string # /usr/src/lib/libkern # /usr/src/etc/quotacheck # /usr/src/etc/edquota.c # /usr/src/etc/quotaon.c # /usr/src/etc/repquota.c # This archive created: Tue Jan 30 21:08:08 1996 export PATH; PATH=/bin:/usr/bin:$PATH if test ! -d '/usr/src/lib/libc/string' then mkdir '/usr/src/lib/libc/string' fi cd '/usr/src/lib/libc/string' if test -f 'strcspn.c' then echo shar: "will not over-write existing file 'strcspn.c'" else sed 's/^X//' << \SHAR_EOF > 'strcspn.c' X/*- X * Copyright (c) 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Chris Torek. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strcspn.c 8.1.1 (2.11BSD) 1996/1/11"; X#endif /* LIBC_SCCS and not lint */ X X#include X#include X X/* X * Span the complement of string s2. X */ Xsize_t Xstrcspn(s1, s2) X char *s1; X char *s2; X{ X register char *p, *spanp; X register char c, sc; X X /* X * Stop as soon as we find any character from s2. Note that there X * must be a NUL in s2; it suffices to stop when we find that, too. X */ X for (p = s1;;) { X c = *p++; X spanp = s2; X do { X if ((sc = *spanp++) == c) X return (p - 1 - s1); X } while (sc != 0); X } X /* NOTREACHED */ X} SHAR_EOF chmod 644 'strcspn.c' fi if test -f 'strpbrk.c' then echo shar: "will not over-write existing file 'strpbrk.c'" else sed 's/^X//' << \SHAR_EOF > 'strpbrk.c' X/* X * Copyright (c) 1985, 1993 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strpbrk.c 8.1.1 (2.11BSD) 1996/1/11"; X#endif /* LIBC_SCCS and not lint */ X X#include X#include X#include /* for NULL */ X X/* X * Find the first occurrence in s1 of a character in s2 (excluding NUL). X */ Xchar * Xstrpbrk(s1, s2) X register char *s1; X char *s2; X{ X register char *scanp; X register int c; X int sc; X X while ((c = *s1++) != 0) { X for (scanp = s2; (sc = *scanp++) != 0;) X if (sc == c) X return ((char *)(s1 - 1)); X } X return (NULL); X} SHAR_EOF chmod 644 'strpbrk.c' fi if test -f 'strsep.c' then echo shar: "will not over-write existing file 'strsep.c'" else sed 's/^X//' << \SHAR_EOF > 'strsep.c' X/*- X * Copyright (c) 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#include X#include X#include X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strsep.c 8.1.1 (2.11BSD) 1996/1/11"; X#endif /* LIBC_SCCS and not lint */ X X/* X * Get next token from string *stringp, where tokens are possibly-empty X * strings separated by characters from delim. X * X * Writes NULs into the string at *stringp to end tokens. X * delim need not remain constant from call to call. X * On return, *stringp points past the last NUL written (if there might X * be further tokens), or is NULL (if there are definitely no more tokens). X * X * If *stringp is NULL, strsep returns NULL. X */ Xchar * Xstrsep(stringp, delim) X register char **stringp; X char *delim; X{ X register char *s; X register char *spanp; X int c, sc; X char *tok; X X if ((s = *stringp) == NULL) X return (NULL); X for (tok = s;;) { X c = *s++; X spanp = delim; X do { X if ((sc = *spanp++) == c) { X if (c == 0) X s = NULL; X else X s[-1] = 0; X *stringp = s; X return (tok); X } X } while (sc != 0); X } X /* NOTREACHED */ X} SHAR_EOF chmod 644 'strsep.c' fi if test -f 'strspn.c' then echo shar: "will not over-write existing file 'strspn.c'" else sed 's/^X//' << \SHAR_EOF > 'strspn.c' X/* X * Copyright (c) 1989, 1993 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strspn.c 8.1.1 (2.11BSD) 1996/1/11"; X#endif /* LIBC_SCCS and not lint */ X X#include X#include X X/* X * Span the string s2 (skip characters that are in s2). X */ Xsize_t Xstrspn(s1, s2) X char *s1; X char *s2; X{ X register char *p = s1, *spanp; X register char c, sc; X X /* X * Skip any characters in s2, excluding the terminating \0. X */ Xcont: X c = *p++; X for (spanp = s2; (sc = *spanp++) != 0;) X if (sc == c) X goto cont; X return (p - 1 - s1); X} SHAR_EOF chmod 644 'strspn.c' fi if test -f 'strtok.c' then echo shar: "will not over-write existing file 'strtok.c'" else sed 's/^X//' << \SHAR_EOF > 'strtok.c' X/* X * Copyright (c) 1988, 1993 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strtok.c 8.1.1 (2.11BSD) 1996/1/11"; X#endif /* LIBC_SCCS and not lint */ X X#include X#include X Xchar * Xstrtok(s, delim) X register char *s; X register char *delim; X{ X register char *spanp; X int c, sc; X char *tok; X static char *last; X X X if (s == NULL && (s = last) == NULL) X return (NULL); X X /* X * Skip (span) leading delimiters (s += strspn(s, delim), sort of). X */ Xcont: X c = *s++; X for (spanp = (char *)delim; (sc = *spanp++) != 0;) { X if (c == sc) X goto cont; X } X X if (c == 0) { /* no non-delimiter characters */ X last = NULL; X return (NULL); X } X tok = s - 1; X X /* X * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). X * Note that delim must have one NUL; we stop if we see that, too. X */ X for (;;) { X c = *s++; X spanp = (char *)delim; X do { X if ((sc = *spanp++) == c) { X if (c == 0) X s = NULL; X else X s[-1] = 0; X last = s; X return (tok); X } X } while (sc != 0); X } X /* NOTREACHED */ X} SHAR_EOF chmod 644 'strtok.c' fi if test ! -d 'profiled' then mkdir 'profiled' fi cd 'profiled' chmod 755 . cd .. if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# @(#)Makefile 1.1 (2.11BSD GTE) 1995/1/15 X# X# This is the Makefile for the 'string' functions. New routines ported from X# 4.4BSD's libc/string directory go here but existing libc/gen files are X# being left where they are. X# X XDEFS= XCFLAGS= -O ${DEFS} XCC= cc X XSRCS= strcspn.c strpbrk.c strsep.c strspn.c strstr.c strtok.c XOBJS= strcspn.o strpbrk.o strsep.o strspn.o strstr.o strtok.o X X.c.o: X ${CC} -p ${CFLAGS} -c $*.c X ld -X -r $*.o X mv a.out profiled/$*.o X ${CC} ${CFLAGS} -c $*.c X ld -X -r $*.o X mv a.out $*.o X Xall: stringlib stringlib_p X Xstringlib stringlib_p: ${OBJS} X @echo "building profiled stringlib" X @cd profiled; ar cru ../stringlib_p ${OBJS} X @echo "building normal stringlib" X @ar cru stringlib ${OBJS} X Xclean: X rm -f ${OBJS} profiled/*.o tags Makefile.bak stringlib stringlib_p X Xdepend: ${SRCS} X mkdep ${CFLAGS} ${SRCS} X Xtags: X cwd=`pwd`; \ X for i in ${SRCS}; do \ X ctags -a -f ${TAGSFILE} $$cwd/$$i; \ X done X X# DO NOT DELETE THIS LINE -- mkdep uses it. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. SHAR_EOF chmod 644 'Makefile' fi if test -f 'strstr.c' then echo shar: "will not over-write existing file 'strstr.c'" else sed 's/^X//' << \SHAR_EOF > 'strstr.c' X/*- X * Copyright (c) 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Chris Torek. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if defined(LIBC_SCCS) && !defined(lint) Xstatic char sccsid[] = "@(#)strstr.c 8.1.1 (2.11BSD) 1996/1/15"; X#endif /* LIBC_SCCS and not lint */ X X#include X X/* X * Find the first occurrence of find in s. X */ Xchar * Xstrstr(s, find) X register char *s, *find; X{ X register char c; X char sc; X size_t len; X X if ((c = *find++) != 0) { X len = strlen(find); X do { X do { X if ((sc = *s++) == 0) X return (NULL); X } while (sc != c); X } while (strncmp(s, find, len) != 0); X s--; X } X return ((char *)s); X} SHAR_EOF chmod 440 'strstr.c' fi chmod 755 . cd .. if test ! -d '/usr/src/lib/libkern' then mkdir '/usr/src/lib/libkern' fi cd '/usr/src/lib/libkern' if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# @(#)Makefile 1.0 (2.11BSD GTE) 1995/1/10 X# X# This is the Makefile for 'libkern.a'. These are the specially compiled X# versions of libc.a routines which the kernel and network use. X# X# There are no source files in this directory. The VPATH capability is X# used instead. libkern.a needs to be installed only once (usually when the X# C library is installed) rather than compiling the sources each time X# a kernel is compiled.. X XDEFS= -DKERNEL XCFLAGS= -O ${DEFS} XCPP= /lib/cpp -P ${DEFS} XAS= /bin/as -u XPREFIX= /usr/src/lib/libc XVPATH= ${PREFIX}/pdp/crt:${PREFIX}/pdp/gen:${PREFIX}/pdp/net X XSRCS= bcmp.s bcopy.s bzero.s ffs.s htonl.s htons.s insque.s \ X ldiv.s lmul.s lrem.s remque.s strlen.s udiv.s uldiv.s ulsh.s X XOBJS= bcmp.o bcopy.o bzero.o ffs.o htonl.o htons.o insque.o \ X ldiv.o lmul.o lrem.o remque.o strlen.o udiv.o uldiv.o ulsh.o X X.c.o: X ${CC} ${CFLAGS} $*.c X ld -X -r $*.o X mv a.out $*.o X X.s.o: X ${CPP} $*.s | ${AS} -o $*.o X ld -X -r $*.o X mv a.out $*.o X Xall: libkern.a X Xlibkern.a: ${OBJS} X rm -f libkern.a X ar rv libkern.a ${OBJS} X Xclean: X rm -f ${OBJS} libkern.a X Xdepend: ${SRCS} X mkdep ${CFLAGS} ${SRCS} X Xinstall: libkern.a X install -o root -g bin -m 644 libkern.a ${DESTDIR}/usr/lib/libkern.a X ranlib ${DESTDIR}/usr/lib/libkern.a X X# DO NOT DELETE THIS LINE -- mkdep uses it. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. SHAR_EOF chmod 644 'Makefile' fi chmod 755 . cd .. if test ! -d '/usr/src/etc/quotacheck' then mkdir '/usr/src/etc/quotacheck' fi cd '/usr/src/etc/quotacheck' if test -f 'preen.c' then echo shar: "will not over-write existing file 'preen.c'" else sed 's/^X//' << \SHAR_EOF > 'preen.c' X/* X * Copyright (c) 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if !defined(lint) && defined(DOSCCS) Xstatic char sccsid[] = "@(#)preen.c 8.1.1 (2.11BSD) 1996/1/23"; X#endif /* not lint */ X X#include X#include X#include X#include X#include X#include X#include X#include X Xchar *rawname(), *unrawname(), *blockcheck(); X Xstruct part { X struct part *next; /* forward link of partitions on disk */ X char *name; /* device name */ X char *fsname; /* mounted filesystem name */ X int auxdata; /* auxillary data for application */ X} *badlist, **badnext = &badlist; X Xstruct disk { X char *name; /* disk base name */ X struct disk *next; /* forward link for list of disks */ X struct part *part; /* head of list of partitions on disk */ X int pid; /* If != 0, pid of proc working on */ X} *disks; X Xint nrun, ndisks; Xchar hotroot; X Xcheckfstab(preen, maxrun, docheck, chkit) X int preen, maxrun; X int (*docheck)(), (*chkit)(); X{ X register struct fstab *fsp; X register struct disk *dk, *nextdisk; X struct part *pt; X int ret, pid, retcode, passno, sumstatus; X union wait status; X int auxdata; X char *name; X X sumstatus = 0; X for (passno = 1; passno <= 2; passno++) { X if (setfsent() == 0) { X warn("Can't open %s\n", _PATH_FSTAB); X return (8); X } X while ((fsp = getfsent()) != 0) { X if ((auxdata = (*docheck)(fsp)) == 0) X continue; X if (preen == 0 || passno == 1 && fsp->fs_passno == 1) { X if (name = blockcheck(fsp->fs_spec)) { X if (sumstatus = (*chkit)(name, X fsp->fs_file, auxdata, 0)) X return (sumstatus); X } else if (preen) X return (8); X } else if (passno == 2 && fsp->fs_passno > 1) { X if ((name = blockcheck(fsp->fs_spec)) == NULL) { X warn("BAD DISK NAME %s\n",fsp->fs_spec); X sumstatus |= 8; X continue; X } X addpart(name, fsp->fs_file, auxdata); X } X } X if (preen == 0) X return (0); X } X if (preen) { X if (maxrun == 0) X maxrun = ndisks; X if (maxrun > ndisks) X maxrun = ndisks; X nextdisk = disks; X for (passno = 0; passno < maxrun; ++passno) { X while (ret = startdisk(nextdisk, chkit) && nrun > 0) X sleep(10); X if (ret) X return (ret); X nextdisk = nextdisk->next; X } X while ((pid = wait(&status)) != -1) { X for (dk = disks; dk; dk = dk->next) X if (dk->pid == pid) X break; X if (dk == 0) { X warn("Unknown pid %d\n", pid); X continue; X } X if (WIFEXITED(status)) X retcode = WEXITSTATUS(status); X else X retcode = 0; X if (WIFSIGNALED(status)) { X warn("%s (%s): EXITED WITH SIGNAL %d\n", X dk->part->name, dk->part->fsname, X status.w_termsig); X retcode = 8; X } X if (retcode != 0) { X sumstatus |= retcode; X *badnext = dk->part; X badnext = &dk->part->next; X dk->part = dk->part->next; X *badnext = NULL; X } else X dk->part = dk->part->next; X dk->pid = 0; X nrun--; X if (dk->part == NULL) X ndisks--; X X if (nextdisk == NULL) { X if (dk->part) { X while (ret = startdisk(dk, chkit) && X nrun > 0) X sleep(10); X if (ret) X return (ret); X } X } else if (nrun < maxrun && nrun < ndisks) { X for ( ;; ) { X if ((nextdisk = nextdisk->next) == NULL) X nextdisk = disks; X if (nextdisk->part != NULL && X nextdisk->pid == 0) X break; X } X while (ret = startdisk(nextdisk, chkit) && X nrun > 0) X sleep(10); X if (ret) X return (ret); X } X } X } X (void)endfsent(); X if (badlist) { X warn("FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", X badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); X for (pt = badlist; pt; pt = pt->next) X warn("%s (%s)%s", pt->name, pt->fsname, X pt->next ? ", " : "\n"); X } X return(sumstatus); X} X Xstruct disk * Xfinddisk(name) X char *name; X{ X register struct disk *dk, **dkp; X register char *p; X size_t len; X X for (p = name + strlen(name) - 1; p >= name; --p) X if (isdigit(*p)) { X len = p - name + 1; X break; X } X if (p < name) X len = strlen(name); X X for (dk = disks, dkp = &disks; dk; dkp = &dk->next, dk = dk->next) { X if (strncmp(dk->name, name, len) == 0 && X dk->name[len] == 0) X return (dk); X } X if ((*dkp = (struct disk *)malloc(sizeof(struct disk))) == NULL) X nomem(); X dk = *dkp; X if ((dk->name = (char *)malloc(len + 1)) == NULL) X nomem(); X (void)strncpy(dk->name, name, len); X dk->name[len] = '\0'; X dk->part = NULL; X dk->next = NULL; X dk->pid = 0; X ndisks++; X return (dk); X} X Xaddpart(name, fsname, auxdata) X char *name, *fsname; X int auxdata; X{ X struct disk *dk = finddisk(name); X register struct part *pt, **ppt = &dk->part; X X for (pt = dk->part; pt; ppt = &pt->next, pt = pt->next) X if (strcmp(pt->name, name) == 0) { X warn("%s in fstab more than once!\n", name); X return; X } X if ((*ppt = (struct part *)malloc(sizeof(struct part))) == NULL) X nomem(); X pt = *ppt; X if ((pt->name = (char *)malloc(strlen(name) + 1)) == NULL) X nomem(); X (void)strcpy(pt->name, name); X if ((pt->fsname = (char *)malloc(strlen(fsname) + 1)) == NULL) X nomem(); X (void)strcpy(pt->fsname, fsname); X pt->next = NULL; X pt->auxdata = auxdata; X} X Xstartdisk(dk, checkit) X register struct disk *dk; X int (*checkit)(); X{ X register struct part *pt = dk->part; X X dk->pid = fork(); X if (dk->pid < 0) { X perror("fork"); X return (8); X } X if (dk->pid == 0) X exit((*checkit)(pt->name, pt->fsname, pt->auxdata, 1)); X nrun++; X return (0); X} X Xchar * Xblockcheck(name) X char *name; X{ X struct stat stslash, stblock, stchar; X char *raw; X int retried = 0; X X hotroot = 0; X if (stat("/", &stslash) < 0) { X perror("/"); X warn("Can't stat root\n"); X return (0); X } Xretry: X if (stat(name, &stblock) < 0) { X perror(name); X warn("Can't stat %s\n", name); X return (0); X } X if ((stblock.st_mode & S_IFMT) == S_IFBLK) { X if (stslash.st_dev == stblock.st_rdev) X hotroot++; X raw = rawname(name); X if (stat(raw, &stchar) < 0) { X perror(raw); X warn("Can't stat %s\n", raw); X return (name); X } X if ((stchar.st_mode & S_IFMT) == S_IFCHR) { X return (raw); X } else { X warn("%s not a character device\n", raw); X return (name); X } X } else if ((stblock.st_mode & S_IFMT) == S_IFCHR && !retried) { X name = unrawname(name); X retried++; X goto retry; X } X warn("Can't make sense of name %s\n", name); X return (0); X} X Xchar * Xunrawname(name) X char *name; X{ X char *dp; X struct stat stb; X X if ((dp = rindex(name, '/')) == 0) X return (name); X if (stat(name, &stb) < 0) X return (name); X if ((stb.st_mode & S_IFMT) != S_IFCHR) X return (name); X if (dp[1] != 'r') X return (name); X (void)strcpy(&dp[1], &dp[2]); X return (name); X} X Xchar * Xrawname(name) X char *name; X{ X static char rawbuf[32]; X char *dp; X X if ((dp = rindex(name, '/')) == 0) X return (0); X *dp = 0; X (void)strcpy(rawbuf, name); X *dp = '/'; X (void)strcat(rawbuf, "/r"); X (void)strcat(rawbuf, &dp[1]); X return (rawbuf); X} X Xnomem() X { X err(8, "out of memory"); X /* NOTREACHED */ X } SHAR_EOF chmod 644 'preen.c' fi if test -f 'quotacheck.c' then echo shar: "will not over-write existing file 'quotacheck.c'" else sed 's/^X//' << \SHAR_EOF > 'quotacheck.c' X/* X * Copyright (c) 1980, 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Robert Elz at The University of Melbourne. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if !defined(lint) && defined(DOSCCS) Xstatic char copyright[] = X"@(#) Copyright (c) 1980, 1990, 1993\n\ X The Regents of the University of California. All rights reserved.\n"; X Xstatic char sccsid[] = "@(#)quotacheck.c 8.3.1 (2.11BSD) 1996/1/23"; X#endif /* not lint */ X X/* X * Fix up / report on disk quotas & usage X */ X#include X#include X X#include X#include X#include X X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xchar *qfname = QUOTAFILENAME; Xchar *quotagroup = QUOTAGROUP; X Xunion { X struct fs sblk; X char dummy[MAXBSIZE]; X} un; X#define sblock un.sblk Xino_t maxino; X Xstruct quotaname { X char flags; X char usrqfname[MAXPATHLEN + 1]; X}; X#define HASUSR 1 X Xstruct fileusage { X struct fileusage *fu_next; X ino_t fu_curinodes; X u_long fu_curblocks; X uid_t fu_id; X char fu_name[1]; X /* actually bigger */ X}; X#define FUHASH 256 /* must be power of two */ Xstruct fileusage *fuhead[FUHASH]; X Xint aflag; /* all file systems */ Xint vflag; /* verbose */ Xint fi; /* open disk file descriptor */ Xuid_t highid; /* highest addid()'ed identifier */ X Xstruct fileusage *addid(); Xchar *blockcheck(); Xvoid bread(); Xint chkquota(); Xvoid freeinodebuf(); Xstruct dinode *getnextinode(); Xgid_t getquotagid(); Xint hasquota(); Xstruct fileusage *lookup(); Xvoid *needchk(); Xint oneof(); Xvoid resetinodebuf(); Xint update(); Xvoid usage(); X Xint Xmain(argc, argv) X int argc; X char *argv[]; X{ X register struct fstab *fs; X register struct passwd *pw; X struct quotaname *auxdata; X int i, argnum, maxrun, errs, ch; X long done = 0; X char *name; X X errs = maxrun = 0; X while ((ch = getopt(argc, argv, "avl:")) != EOF) { X switch(ch) { X case 'a': X aflag++; X break; X case 'v': X vflag++; X break; X case 'l': X maxrun = atoi(optarg); X break; X default: X usage(); X } X } X argc -= optind; X argv += optind; X if ((argc == 0 && !aflag) || (argc > 0 && aflag)) X usage(); X X setpwent(); X while ((pw = getpwent()) != 0) X (void) addid(pw->pw_uid, pw->pw_name); X endpwent(); X X if (aflag) X exit(checkfstab(1, maxrun, needchk, chkquota)); X if (setfsent() == 0) X err(1, "can't open %s", FSTAB); X while ((fs = getfsent()) != NULL) { X if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || X (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) && X (auxdata = (struct quotaname *)needchk(fs)) && X (name = blockcheck(fs->fs_spec))) { X done |= 1 << argnum; X errs += chkquota(name, fs->fs_file, auxdata); X } X } X endfsent(); X for (i = 0; i < argc; i++) X if ((done & (1 << i)) == 0) X warn("%s not found in %s", argv[i], FSTAB); X exit(errs); X} X Xvoid Xusage() X{ X (void)err(1, "usage:\t%s\n\t%s\n", X "quotacheck -a [-v] [-l num]", X "quotacheck [-v] filesys ..."); X/* NOTREACHED */ X} X Xvoid * Xneedchk(fs) X register struct fstab *fs; X{ X register struct quotaname *qnp; X char *qfnp; X X if (strcmp(fs->fs_vfstype, "ufs") || X (strcmp(fs->fs_type, FSTAB_RW) && strcmp(fs->fs_type, FSTAB_RQ))) X return ((void *)NULL); X if ((qnp = (struct quotaname *)malloc(sizeof(*qnp))) == NULL) X nomem(); X qnp->flags = 0; X if (hasquota(fs, &qfnp)) { X strcpy(qnp->usrqfname, qfnp); X qnp->flags |= HASUSR; X } X if (qnp->flags) X return ((void *)qnp); X free(qnp); X return ((void *)NULL); X} X X/* X * Scan the specified filesystem to check quota(s) present on it. X */ Xint Xchkquota(fsname, mntpt, qnp) X char *fsname, *mntpt; X register struct quotaname *qnp; X{ X register struct fileusage *fup; X register struct dinode *dp; X int mode, errs = 0; X ino_t ino; X X if ((fi = open(fsname, O_RDONLY, 0)) < 0) { X perror(fsname); X return (1); X } X if (vflag) X (void)printf("*** Checking quotas for %s (%s)\n", X fsname, mntpt); X sync(); X bread(SBLOCK, (char *)&sblock, SBSIZE); X maxino = (sblock.fs_isize - 2) * INOPB; X resetinodebuf(); X for (ino = ROOTINO; ino < maxino; ino++) { X if ((dp = getnextinode(ino)) == NULL) X continue; X if ((mode = dp->di_mode & IFMT) == 0) X continue; X if (qnp->flags & HASUSR) { X fup = addid(dp->di_uid, (char *)0); X fup->fu_curinodes++; X if (mode == IFREG || mode == IFDIR || mode == IFLNK) X fup->fu_curblocks += dp->di_size; X } X } X freeinodebuf(); X if (qnp->flags & HASUSR) X errs += update(fsname, mntpt, qnp->usrqfname); X close(fi); X return (errs); X} X X/* X * Update a specified quota file. X */ Xint Xupdate(fsdev, fsname, quotafile) X char *fsdev, *fsname, *quotafile; X{ X register struct fileusage *fup; X register FILE *qfi, *qfo; X uid_t id, lastid; X struct dqblk dqbuf; X struct stat statb; X struct dqusage dqu; X dev_t quotadev; X static int warned = 0; X static struct dqblk zerodqbuf; X static struct fileusage zerofileusage; X X if ((qfo = fopen(quotafile, "r+")) == NULL) { X if (errno == ENOENT) X qfo = fopen(quotafile, "w+"); X if (qfo) { X (void) warn("creating quota file %s", quotafile); X (void) fchown(fileno(qfo), getuid(), getquotagid()); X (void) fchmod(fileno(qfo), 0640); X } else { X (void) warn("%s: %s", quotafile, strerror(errno)); X return (1); X } X } X if ((qfi = fopen(quotafile, "r")) == NULL) { X (void) warn("%s: %s", quotafile, strerror(errno)); X (void) fclose(qfo); X return (1); X } X/* X * We check that the quota file resides in the filesystem being checked. This X * restriction is imposed by the kernel for now. X*/ X fstat(fileno(qfi), &statb); X quotadev = statb.st_dev; X if (stat(unrawname(fsdev), &statb) < 0) { X warn("Can't stat %s", fsname); X fclose(qfi); X fclose(qfo); X return(1); X } X if (quotadev != statb.st_rdev) { X warn("%s dev (0x%x) mismatch %s dev (0x%x)", quotafile, X quotadev, fsname, statb.st_rdev); X fclose(qfi); X fclose(qfo); X return(1); X } X if (quota(Q_SYNC, 0, quotadev, 0) < 0 && X errno == EOPNOTSUPP && !warned && vflag) { X warned++; X (void)printf("*** Warning: %s\n", X "Quotas are not compiled into this kernel"); X } X for (lastid = highid, id = 0; id <= lastid; id++) { X if (fread((char *)&dqbuf, sizeof(struct dqblk), 1, qfi) == 0) X dqbuf = zerodqbuf; X if ((fup = lookup(id)) == 0) X fup = &zerofileusage; X if (dqbuf.dqb_curinodes == fup->fu_curinodes && X dqbuf.dqb_curblocks == fup->fu_curblocks) { X fup->fu_curinodes = 0; X fup->fu_curblocks = 0; X fseek(qfo, (long)sizeof(struct dqblk), 1); X continue; X } X if (vflag) { X if (aflag) X printf("%s: ", fsname); X printf("%-8s fixed:", fup->fu_name); X if (dqbuf.dqb_curinodes != fup->fu_curinodes) X (void)printf("\tinodes %u -> %u", X dqbuf.dqb_curinodes, fup->fu_curinodes); X if (dqbuf.dqb_curblocks != fup->fu_curblocks) X (void)printf("\tbytes %ld -> %ld", X dqbuf.dqb_curblocks, fup->fu_curblocks); X (void)printf("\n"); X } X dqbuf.dqb_curinodes = fup->fu_curinodes; X dqbuf.dqb_curblocks = fup->fu_curblocks; X fwrite((char *)&dqbuf, sizeof(struct dqblk), 1, qfo); X/* X * Need to convert from bytes to blocks for system call interface. X */ X dqu.du_curblocks = btodb(fup->fu_curblocks); X dqu.du_curinodes = fup->fu_curinodes; X (void) quota(Q_SETDUSE, id, quotadev, &dqu); X fup->fu_curinodes = 0; X fup->fu_curblocks = 0; X } X fclose(qfi); X fflush(qfo); X ftruncate(fileno(qfo), (off_t)(highid + 1) * sizeof(struct dqblk)); X fclose(qfo); X return (0); X} X X/* X * Check to see if target appears in list of size cnt. X */ Xint Xoneof(target, list, cnt) X register char *target, *list[]; X int cnt; X{ X register int i; X X for (i = 0; i < cnt; i++) X if (strcmp(target, list[i]) == 0) X return (i); X return (-1); X} X X/* X * Determine the group identifier for quota files. X */ Xgid_t Xgetquotagid() X{ X struct group *gr; X X if (gr = getgrnam(quotagroup)) X return (gr->gr_gid); X return (-1); X} X X/* X * Check to see if a particular quota is to be enabled. X */ Xhasquota(fs, qfnamep) X register struct fstab *fs; X char **qfnamep; X{ X register char *opt; X char *cp; X static char initname, usrname[100]; X static char buf[BUFSIZ]; X X if (!initname) { X strcpy(usrname, qfname); X initname = 1; X } X strcpy(buf, fs->fs_mntops); X for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { X if (cp = index(opt, '=')) X *cp++ = '\0'; X if (strcmp(opt, usrname) == 0) X break; X if (strcmp(opt, FSTAB_RQ) == 0) /* XXX compatibility */ X break; X } X if (!opt) X return (0); X if (cp) { X *qfnamep = cp; X return (1); X } X (void) sprintf(buf, "%s/%s", fs->fs_file, qfname); X *qfnamep = buf; X return (1); X} X X/* X * Routines to manage the file usage table. X * X * Lookup an id. X */ Xstruct fileusage * Xlookup(id) X uid_t id; X{ X register struct fileusage *fup; X X for (fup = fuhead[id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) X if (fup->fu_id == id) X return (fup); X return (NULL); X} X X/* X * Add a new file usage id if it does not already exist. X */ Xstruct fileusage * Xaddid(id, name) X uid_t id; X char *name; X{ X register struct fileusage *fup, **fhp; X int len; X X if (fup = lookup(id)) X return (fup); X if (name) X len = strlen(name); X else X len = 10; X if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) X err("%s", strerror(errno)); X fhp = &fuhead[id & (FUHASH - 1)]; X fup->fu_next = *fhp; X *fhp = fup; X fup->fu_id = id; X if (id > highid) X highid = id; X if (name) X bcopy(name, fup->fu_name, len + 1); X else X (void)sprintf(fup->fu_name, "%u", id); X return (fup); X} X X/* X * Special purpose version of ginode used to optimize pass X * over all the inodes in numerical order. X */ Xino_t nextino; Xlong lastinum; Xint inobufsize; Xstruct dinode *inodebuf; X#define INOBUFSIZE 128 /* number of inodes to read at a time */ X Xstruct dinode * Xgetnextinode(inumber) X ino_t inumber; X{ X daddr_t dblk; X static struct dinode *dp; X X if (inumber != nextino++ || inumber >= maxino) X err(1, "bad inode number %d to nextinode", inumber); X if (inumber > lastinum) { X dblk = itod(inumber); X lastinum += INOBUFSIZE; X bread(dblk, (char *)inodebuf, inobufsize); X dp = inodebuf; X } X return (dp++); X} X X/* X * Prepare to scan a set of inodes. X */ Xvoid Xresetinodebuf() X{ X X nextino = 1; X lastinum = 0; X inobufsize = INOBUFSIZE * sizeof (struct dinode); X if (inodebuf == NULL && X (inodebuf = (struct dinode *)malloc(inobufsize)) == NULL) X nomem(); X while (nextino < ROOTINO) X getnextinode(nextino); X} X X/* X * Free up data structures used to scan inodes. X */ Xvoid Xfreeinodebuf() X{ X X if (inodebuf != NULL) X free(inodebuf); X inodebuf = NULL; X} X X/* X * Read specified disk blocks. X */ Xvoid Xbread(bno, buf, cnt) X daddr_t bno; X char *buf; X int cnt; X{ X X if (lseek(fi, (off_t)bno * DEV_BSIZE, 0) == -1 || X read(fi, buf, cnt) != cnt) X err(1, "block %ld", bno); X} SHAR_EOF chmod 644 'quotacheck.c' fi if test -f 'Makefile' then echo shar: "will not over-write existing file 'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# X# Public Domain. 1996/1/23 - Steven Schultz X# X# @(#)Makefile 1.0 (2.11BSD GTE) 1996/1/23 X# XCFLAGS= -O XSEPFLAG= -i XSRCS= quotacheck.c preen.c XOBJS= quotacheck.o preen.o XMAN= quotacheck.0 XMANSRC= quotacheck.8 X Xall: quotacheck quotacheck.0 X Xquotacheck: ${OBJS} X ${CC} ${CFLAGS} ${SEPFLAG} -o $@ ${OBJS} X Xquotacheck.0: ${MANSRC} X /usr/man/manroff ${MANSRC} > ${MAN} X Xclean: X rm -f ${OBJS} ${MAN} quotacheck tags X Xdepend: ${SRCS} X mkdep ${CFLAGS} ${SRCS} X Xinstall: all X install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat8 X install -s -o root -g bin -m 755 quotacheck ${DESTDIR}/etc/quotacheck X Xlint: ${SRCS} X lint -hax ${SRCS} X Xtags: ${SRCS} X ctags ${SRCS} X# DO NOT DELETE THIS LINE -- mkdep uses it. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. SHAR_EOF chmod 644 'Makefile' fi if test -f 'quotacheck.8' then echo shar: "will not over-write existing file 'quotacheck.8'" else sed 's/^X//' << \SHAR_EOF > 'quotacheck.8' X.\" Copyright (c) 1983, 1990, 1991, 1993 X.\" The Regents of the University of California. All rights reserved. X.\" X.\" This code is derived from software contributed to Berkeley by X.\" Robert Elz at The University of Melbourne. X.\" X.\" Redistribution and use in source and binary forms, with or without X.\" modification, are permitted provided that the following conditions X.\" are met: X.\" 1. Redistributions of source code must retain the above copyright X.\" notice, this list of conditions and the following disclaimer. X.\" 2. Redistributions in binary form must reproduce the above copyright X.\" notice, this list of conditions and the following disclaimer in the X.\" documentation and/or other materials provided with the distribution. X.\" 3. All advertising materials mentioning features or use of this software X.\" must display the following acknowledgement: X.\" This product includes software developed by the University of X.\" California, Berkeley and its contributors. X.\" 4. Neither the name of the University nor the names of its contributors X.\" may be used to endorse or promote products derived from this software X.\" without specific prior written permission. X.\" X.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X.\" SUCH DAMAGE. X.\" X.\" @(#)quotacheck.8 8.1.1 (2.11BSD) 1996/1/24 X.\" X.TH QUOTACHECK 8 "January 24, 1996" X.UC 5 X.SH NAME X\fBquotacheck\fP \- filesystem quota consistency checker X.SH SYNOPSIS X.B quotacheck X[ \fB\-v\fP ] X.I filesystem ... X.br X.B quotacheck X[ \fB\-v\fP ] X\fB\-a\fP X.SH DESCRIPTION X.B Quotacheck Xexamines each filesystem, Xbuilds a table of current disk usage, Xand compares this table against that recorded Xin the disk quota file for the filesystem. XIf any inconsistencies are detected, both the Xquota file and the current system copy of the Xincorrect quotas are updated (the latter only Xoccurs if an active filesystem is checked). X.PP XAvailable options: X.sp X.TP 15 X\fB\-a\fP XIf the X\fB\-a\fP Xflag is supplied in place of any filesystem names, X\fBquotacheck\fP Xwill check all the filesystems indicated in X\fI/etc/fstab\fP Xto be read-write with disk quotas. X.TP 15 X\fB\-v\fP X\fBquotacheck\fP Xreports discrepancies between the Xcalculated and recorded disk quotas. X.PP XParallel passes are run on the filesystems required, Xusing the pass numbers in X.I /etc/fstab Xin an identical fashion to Xfsck(8). X.PP XNormally X.B quotacheck Xoperates silently. X.PP X.B Quotacheck Xexpects each filesystem to be checked to have a Xquota files named X.I quotas Xlocated at the root of the associated file system. XThese defaults may be overridden in X.IR /etc/fstab . XIf a file is not present, X.B quotacheck Xwill create it. X.PP X.B Quotacheck Xis normally run at boot time from the X.I /etc/rc.local Xfile, see Xrc(8), Xbefore enabling disk quotas with Xquotaon(8). X.PP X.B Quotacheck Xaccesses the raw device in calculating the actual Xdisk usage for each user. XThus, the filesystems Xchecked should be quiescent while X.B quotacheck Xis running. X.SH FILES X.TP 15 X.I quotas Xat the filesystem root X.TP 15 X.I /etc/fstab Xdefault filesystems X.SH BUGS XThe \fIquotas\fP file may be named arbitrarily but \fBmust\fP reside in Xthe filesystem for which it contains quota information. X.B Quotacheck Xwill give the error: X.sp X.in +0.5i X.I %s dev (0x%x) mismatch %s (0x%x) X.sp X.in -0.5i Xif the \fIquotas\fP file is not in the filesystem being checked. This Xrestriction is enforced by the kernel but may be lifted in the future. X.SH SEE ALSO Xquota(1), Xquotactl(2), Xfstab(5), Xedquota(8), Xfsck(8), Xquotaon(8), Xrepquota(8) X.SH HISTORY XThe X.B quotacheck Xcommand appeared in 4.2BSD. SHAR_EOF chmod 644 'quotacheck.8' fi chmod 755 . cd .. if test -f '/usr/src/etc/edquota.c' then echo shar: "will not over-write existing file '/usr/src/etc/edquota.c'" else sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/edquota.c' X/* X * Copyright (c) 1980, 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Robert Elz at The University of Melbourne. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if !defined(lint) && defined(DOSCCS) Xstatic char copyright[] = X"@(#) Copyright (c) 1980, 1990, 1993\n\ X The Regents of the University of California. All rights reserved.\n"; X Xstatic char sccsid[] = "@(#)edquota.c 8.1.1 (2.11BSD) 1996/1/21"; X#endif /* not lint */ X X/* X * Disk quota editor. X */ X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xchar *qfname = "quotas"; Xchar tmpfil[] = "/tmp/EdP.aXXXXXX"; X Xstruct quotause { X struct quotause *next; X short flags; X struct dqblk dqblk; X char fsname[MAXPATHLEN + 1]; X char qfname[1]; /* actually longer */ X} *getprivs(); X#define FOUND 0x01 X X uid_t getentry(); X Xmain(argc, argv) X register char **argv; X int argc; X{ X register struct quotause *protoprivs, *curprivs; X extern char *optarg; X extern int optind; X uid_t id, protoid; X int tmpfd; X char *protoname, ch; X int pflag = 0; X X if (argc < 2) X usage(); X if (getuid()) { X fprintf(stderr, "edquota: permission denied\n"); X exit(1); X } X while ((ch = getopt(argc, argv, "p:")) != EOF) { X switch(ch) { X case 'p': X protoname = optarg; X pflag++; X break; X default: X usage(); X } X } X argc -= optind; X argv += optind; X if (pflag) { X if ((protoid = getentry(protoname)) == -1) X exit(1); X protoprivs = getprivs(protoid); X while (argc-- > 0) { X if ((id = getentry(*argv++)) < 0) X continue; X putprivs(id, protoprivs); X } X exit(0); X } X tmpfd = mkstemp(tmpfil); X fchown(tmpfd, getuid(), getgid()); X for ( ; argc > 0; argc--, argv++) { X if ((id = getentry(*argv)) == -1) X continue; X curprivs = getprivs(id); X if (writeprivs(curprivs, tmpfd, *argv) == 0) X continue; X if (editit(tmpfil) && readprivs(curprivs, tmpfd)) X putprivs(id, curprivs); X freeprivs(curprivs); X } X close(tmpfd); X unlink(tmpfil); X exit(0); X} X Xusage() X{ X fputs("Usage: edquota [-p username] username ...\n", stderr); X exit(1); X} X X/* X * This routine converts a name for a particular quota type to X * an identifier. This routine must agree with the kernel routine X * getinoquota as to the interpretation of quota types. X */ Xuid_t Xgetentry(name) X char *name; X{ X struct passwd *pw; X X if (alldigits(name)) X return (atoi(name)); X if (pw = getpwnam(name)) X return (pw->pw_uid); X fprintf(stderr, "%s: no such user\n", name); X sleep(1); X return (-1); X} X X/* X * Collect the requested quota information. X */ Xstruct quotause * Xgetprivs(id) X u_int id; X{ X register struct fstab *fs; X register struct quotause *qup, *quptail; X struct dqblk *dq; X struct quotause *quphead; X struct stat statb; X dev_t fsdev; X int qupsize, fd; X char *qfpathname; X static int warned = 0; X extern int errno; X X setfsent(); X quphead = (struct quotause *)0; X while (fs = getfsent()) { X if (stat(fs->fs_spec, &statb) < 0) X continue; X if (strcmp(fs->fs_vfstype, "ufs")) X continue; X if (!hasquota(fs, &qfpathname)) X continue; X/* X * See the comments in quota.c about the check below. X*/ X fsdev = statb.st_rdev; X if (stat(qfpathname, &statb) < 0 || statb.st_dev != fsdev) X continue; X qupsize = sizeof(*qup) + strlen(qfpathname); X if ((qup = (struct quotause *)malloc(qupsize)) == NULL) { X fprintf(stderr, "edquota: out of memory\n"); X exit(2); X } X if (quota(Q_GETDLIM, id, fsdev, &qup->dqblk) != 0) { X if (errno == EOPNOTSUPP && !warned) { X warned++; X fprintf(stderr, "Warning: %s\n", X "Quotas are not compiled into this kernel"); X sleep(3); X } X if ((fd = open(qfpathname, O_RDONLY)) < 0) { X fd = open(qfpathname, O_RDWR|O_CREAT, 0640); X if (fd < 0 && errno != ENOENT) { X perror(qfpathname); X free(qup); X continue; X } X fprintf(stderr, "Creating quota file %s\n", X qfpathname); X sleep(3); X (void) fchown(fd, getuid(), -1); X (void) fchmod(fd, 0640); X } X lseek(fd, (long)(id * sizeof(struct dqblk)), L_SET); X switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { X case 0: /* EOF */ X /* X * Convert implicit 0 quota (EOF) X * into an explicit one (zero'ed dqblk) X */ X bzero((caddr_t)&qup->dqblk, X sizeof(struct dqblk)); X break; X X case sizeof(struct dqblk): /* OK */ X/* X * We have to convert from bytes to disc blocks because the quotas file X * entries use bytes like the kernel does. X*/ X dq = &qup->dqblk; X dq->dqb_curblocks = btodb(dq->dqb_curblocks); X dq->dqb_bhardlimit = btodb(dq->dqb_bhardlimit); X dq->dqb_bsoftlimit = btodb(dq->dqb_bsoftlimit); X break; X X default: /* ERROR */ X fprintf(stderr, "edquota: read error in "); X perror(qfpathname); X close(fd); X free(qup); X continue; X } X close(fd); X } X strcpy(qup->qfname, qfpathname); X strcpy(qup->fsname, fs->fs_file); X if (quphead == NULL) X quphead = qup; X else X quptail->next = qup; X quptail = qup; X qup->next = 0; X } X endfsent(); X return (quphead); X} X X/* X * Store the requested quota information. X */ Xputprivs(id, quplist) X uid_t id; X struct quotause *quplist; X{ X register struct quotause *qup; X struct stat sb; X int fd; X register struct dqblk *dq; X X for (qup = quplist; qup; qup = qup->next) { X if (stat(qup->qfname, &sb) < 0) { X fprintf(stderr,"edquota: can't stat %s\n",qup->qfname); X continue; X } X X if (quota(Q_SETDLIM, id, sb.st_dev, &qup->dqblk) == 0) X continue; X/* X * Have to convert from blocks to bytes now to be compatible with the kernel X*/ X dq = &qup->dqblk; X dq->dqb_bhardlimit = dbtob(dq->dqb_bhardlimit); X dq->dqb_bsoftlimit = dbtob(dq->dqb_bsoftlimit); X dq->dqb_curblocks = dbtob(dq->dqb_curblocks); X X if ((fd = open(qup->qfname, O_WRONLY)) < 0) { X perror(qup->qfname); X } else { X lseek(fd, (long)id * (long)sizeof (struct dqblk), 0); X if (write(fd, &qup->dqblk, sizeof (struct dqblk)) != X sizeof (struct dqblk)) { X fprintf(stderr, "edquota: "); X perror(qup->qfname); X } X close(fd); X } X } X} X X/* X * Take a list of priviledges and get it edited. X */ Xeditit(tmpfile) X char *tmpfile; X{ X long omask; X pid_t pid; X union wait stat; X extern char *getenv(); X X omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); X top: X if ((pid = vfork()) < 0) { X extern int errno; X X if (errno == EPROCLIM) { X fprintf(stderr, "You have too many processes\n"); X return(0); X } X if (errno == EAGAIN) { X sleep(1); X goto top; X } X perror("fork"); X return (0); X } X if (pid == 0) { X register char *ed; X X sigsetmask(omask); X setgid(getgid()); X setuid(getuid()); X if ((ed = getenv("EDITOR")) == (char *)0) X ed = _PATH_VI; X execlp(ed, ed, tmpfile, 0); X perror(ed); X exit(1); X } X waitpid(pid, &stat, 0); X sigsetmask(omask); X if (!WIFEXITED(stat) || WEXITSTATUS(stat) != 0) X return (0); X return (1); X} X X/* X * Convert a quotause list to an ASCII file. X */ Xwriteprivs(quplist, outfd, name) X struct quotause *quplist; X int outfd; X char *name; X{ X register struct quotause *qup; X register FILE *fd; X X ftruncate(outfd, (off_t)0); X lseek(outfd, (off_t)0, L_SET); X if ((fd = fdopen(dup(outfd), "w")) == NULL) { X fprintf(stderr, "edquota: "); X perror(tmpfil); X exit(1); X } X fprintf(fd, "Quotas for %s:\n", name); X for (qup = quplist; qup; qup = qup->next) { X fprintf(fd, "%s: %s %ld, limits (soft = %ld, hard = %ld)\n", X qup->fsname, "blocks in use:", X qup->dqblk.dqb_curblocks, X qup->dqblk.dqb_bsoftlimit, X qup->dqblk.dqb_bhardlimit); X fprintf(fd, "%s %u, limits (soft = %u, hard = %u)\n", X "\tinodes in use:", qup->dqblk.dqb_curinodes, X qup->dqblk.dqb_isoftlimit, qup->dqblk.dqb_ihardlimit); X } X fclose(fd); X return (1); X} X X/* X * Merge changes to an ASCII file into a quotause list. X */ Xreadprivs(quplist, infd) X struct quotause *quplist; X int infd; X{ X register struct quotause *qup; X FILE *fd; X int cnt; X register char *cp; X struct dqblk dqblk; X char *fsp, line1[BUFSIZ], line2[BUFSIZ]; X X lseek(infd, (off_t)0, L_SET); X fd = fdopen(dup(infd), "r"); X if (fd == NULL) { X fprintf(stderr, "Can't re-read temp file!!\n"); X return (0); X } X /* X * Discard title line, then read pairs of lines to process. X */ X (void) fgets(line1, sizeof (line1), fd); X while (fgets(line1, sizeof (line1), fd) != NULL && X fgets(line2, sizeof (line2), fd) != NULL) { X if ((fsp = strtok(line1, " \t:")) == NULL) { X fprintf(stderr, "%s: bad format\n", line1); X return (0); X } X if ((cp = strtok((char *)0, "\n")) == NULL) { X fprintf(stderr, "%s: %s: bad format\n", fsp, X &fsp[strlen(fsp) + 1]); X return (0); X } X cnt = sscanf(cp, X " blocks in use: %ld, limits (soft = %ld, hard = %ld)", X &dqblk.dqb_curblocks, &dqblk.dqb_bsoftlimit, X &dqblk.dqb_bhardlimit); X if (cnt != 3) { X fprintf(stderr, "%s:%s: bad format\n", fsp, cp); X return (0); X } X if ((cp = strtok(line2, "\n")) == NULL) { X fprintf(stderr, "%s: %s: bad format\n", fsp, line2); X return (0); X } X cnt = sscanf(cp, X "\tinodes in use: %u, limits (soft = %u, hard = %u)", X &dqblk.dqb_curinodes, &dqblk.dqb_isoftlimit, X &dqblk.dqb_ihardlimit); X if (cnt != 3) { X fprintf(stderr, "%s: %s: bad format\n", fsp, line2); X return (0); X } X for (qup = quplist; qup; qup = qup->next) { X if (strcmp(fsp, qup->fsname)) X continue; X qup->dqblk.dqb_bsoftlimit = dqblk.dqb_bsoftlimit; X qup->dqblk.dqb_bhardlimit = dqblk.dqb_bhardlimit; X qup->dqblk.dqb_isoftlimit = dqblk.dqb_isoftlimit; X qup->dqblk.dqb_ihardlimit = dqblk.dqb_ihardlimit; X qup->flags |= FOUND; X if (dqblk.dqb_curblocks == qup->dqblk.dqb_curblocks && X dqblk.dqb_curinodes == qup->dqblk.dqb_curinodes) X break; X fprintf(stderr, X "%s: cannot change current allocation\n", fsp); X break; X } X } X fclose(fd); X /* X * Disable quotas for any filesystems that have not been found. X */ X for (qup = quplist; qup; qup = qup->next) { X if (qup->flags & FOUND) { X qup->flags &= ~FOUND; X continue; X } X qup->dqblk.dqb_bsoftlimit = 0; X qup->dqblk.dqb_bhardlimit = 0; X qup->dqblk.dqb_isoftlimit = 0; X qup->dqblk.dqb_ihardlimit = 0; X } X return (1); X} X X/* X * Free a list of quotause structures. X */ Xfreeprivs(quplist) X struct quotause *quplist; X{ X register struct quotause *qup, *nextqup; X X for (qup = quplist; qup; qup = nextqup) { X nextqup = qup->next; X free(qup); X } X} X X/* X * Check whether a string is completely composed of digits. X */ Xalldigits(s) X register char *s; X{ X register c; X X c = *s++; X do { X if (!isdigit(c)) X return (0); X } while (c = *s++); X return (1); X} X X/* X * Check to see if a particular quota is to be enabled. X */ Xhasquota(fs, qfnamep) X register struct fstab *fs; X char **qfnamep; X{ X register char *opt; X char *cp; X static char initname, usrname[100]; X static char buf[BUFSIZ]; X X if (!initname) { X strcpy(usrname, qfname); X initname = 1; X } X strcpy(buf, fs->fs_mntops); X for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { X if (cp = index(opt, '=')) X *cp++ = '\0'; X if (strcmp(opt, usrname) == 0) X break; X if (strcmp(opt, FSTAB_RQ) == 0) /* XXX compatibility */ X break; X } X if (!opt) X return (0); X if (cp) { X *qfnamep = cp; X return (1); X } X (void) sprintf(buf, "%s/%s", fs->fs_file, qfname); X *qfnamep = buf; X return (1); X} SHAR_EOF chmod 644 '/usr/src/etc/edquota.c' fi if test -f '/usr/src/etc/quotaon.c' then echo shar: "will not over-write existing file '/usr/src/etc/quotaon.c'" else sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/quotaon.c' X/* X * Copyright (c) 1980, 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Robert Elz at The University of Melbourne. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if !defined(lint) && defined(DOSCCS) Xstatic char copyright[] = X"@(#) Copyright (c) 1980, 1990, 1993\n\ X The Regents of the University of California. All rights reserved.\n"; X Xstatic char sccsid[] = "@(#)quotaon.c 8.1.1 (2.11BSD) 1996/1/21"; X#endif /* not lint */ X X/* X * Turn quota on/off for a filesystem. X */ X#include X#include X#include X#include X#include X#include X#include X Xchar *qfname = "quotas"; X Xint aflag; /* all file systems */ Xint vflag; /* verbose */ X Xmain(argc, argv) X int argc; X char **argv; X{ X register struct fstab *fs; X char ch, *qfnp, *whoami; X long done = 0; X int i, argnum, offmode = 0, errs = 0; X X whoami = rindex(*argv, '/') + 1; X if (whoami == (char *)1) X whoami = *argv; X if (strcmp(whoami, "quotaoff") == 0) X offmode++; X else if (strcmp(whoami, "quotaon") != 0) { X fprintf(stderr, "Name must be quotaon or quotaoff not %s\n", X whoami); X exit(1); X } X while ((ch = getopt(argc, argv, "avug")) != EOF) { X switch(ch) { X case 'a': X aflag++; X break; X case 'v': X vflag++; X break; X default: X usage(whoami); X } X } X argc -= optind; X argv += optind; X if (argc <= 0 && !aflag) X usage(whoami); X setfsent(); X while ((fs = getfsent()) != NULL) { X if (strcmp(fs->fs_type, FSTAB_RQ) == 0) /* XXX compatibility */ X fs->fs_type = FSTAB_RW; X if (strcmp(fs->fs_vfstype, "ufs") || X strcmp(fs->fs_type, FSTAB_RW)) X continue; X if (aflag) { X if (hasquota(fs, &qfnp)) X errs += quotaonoff(fs, offmode, qfnp); X continue; X } X if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || X (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { X done |= 1 << argnum; X if (hasquota(fs, &qfnp)) X errs += quotaonoff(fs, offmode, qfnp); X } X } X endfsent(); X for (i = 0; i < argc; i++) X if ((done & (1 << i)) == 0) X fprintf(stderr, "%s not found in fstab\n", X argv[i]); X exit(errs); X} X Xusage(whoami) X char *whoami; X{ X X fprintf(stderr, "Usage:\n\t%s [-v] -a\n", whoami); X fprintf(stderr, "\t%s [-v] filesys ...\n", whoami); X exit(1); X} X Xquotaonoff(fs, offmode, qfpathname) X register struct fstab *fs; X int offmode; X char *qfpathname; X{ X X if (strcmp(fs->fs_file, "/") && readonly(fs)) X return (1); X if (offmode) { X if (setquota(fs->fs_spec, (char *)NULL) < 0) { X fprintf(stderr, "quotaoff: "); X perror(fs->fs_spec); X return (1); X } X if (vflag) X printf("%s: quotas turned off\n", fs->fs_file); X return (0); X } X if (setquota(fs->fs_spec, qfpathname) < 0) { X fprintf(stderr, "quotaon: using %s on", qfpathname); X perror(fs->fs_file); X return (1); X } X if (vflag) X printf("%s: quotas turned on\n", fs->fs_file); X return (0); X} X X/* X * Check to see if target appears in list of size cnt. X */ Xoneof(target, list, cnt) X register char *target, *list[]; X int cnt; X{ X register int i; X X for (i = 0; i < cnt; i++) X if (strcmp(target, list[i]) == 0) X return (i); X return (-1); X} X X/* X * Check to see if a particular quota is to be enabled. X */ Xhasquota(fs, qfnamep) X register struct fstab *fs; X char **qfnamep; X{ X register char *opt; X char *cp; X static char initname, usrname[100]; X static char buf[BUFSIZ]; X X if (!initname) { X strcpy(usrname, qfname); X initname = 1; X } X strcpy(buf, fs->fs_mntops); X for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { X if (cp = index(opt, '=')) X *cp++ = '\0'; X if (strcmp(opt, usrname) == 0) X break; X if (strcmp(opt, FSTAB_RQ) == 0) /* XXX compatibility */ X break; X } X if (!opt) X return (0); X if (cp) { X *qfnamep = cp; X return (1); X } X (void) sprintf(buf, "%s/%s", fs->fs_file, qfname); X *qfnamep = buf; X return (1); X} X X/* X * Verify file system is mounted and not readonly. X */ Xreadonly(fs) X register struct fstab *fs; X{ X struct statfs fsbuf; X X if (statfs(fs->fs_file, &fsbuf) < 0 || X strcmp(fsbuf.f_mntonname, fs->fs_file) || X strcmp(fsbuf.f_mntfromname, fs->fs_spec)) { X printf("%s: not mounted\n", fs->fs_file); X return (1); X } X if (fsbuf.f_flags & MNT_RDONLY) { X printf("%s: mounted read-only\n", fs->fs_file); X return (1); X } X return (0); X} SHAR_EOF chmod 444 '/usr/src/etc/quotaon.c' fi if test -f '/usr/src/etc/repquota.c' then echo shar: "will not over-write existing file '/usr/src/etc/repquota.c'" else sed 's/^X//' << \SHAR_EOF > '/usr/src/etc/repquota.c' X/* X * Copyright (c) 1980, 1990, 1993 X * The Regents of the University of California. All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Robert Elz at The University of Melbourne. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions X * are met: X * 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. X * 2. Redistributions in binary form must reproduce the above copyright X * notice, this list of conditions and the following disclaimer in the X * documentation and/or other materials provided with the distribution. X * 3. All advertising materials mentioning features or use of this software X * must display the following acknowledgement: X * This product includes software developed by the University of X * California, Berkeley and its contributors. X * 4. Neither the name of the University nor the names of its contributors X * may be used to endorse or promote products derived from this software X * without specific prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X#if !defined(lint) && defined(DOSCCS) Xstatic char copyright[] = X"@(#) Copyright (c) 1980, 1990, 1993\n\ X The Regents of the University of California. All rights reserved.\n"; X Xstatic char sccsid[] = "@(#)repquota.c 8.1 (Berkeley) 6/6/93"; X#endif /* not lint */ X X/* X * Quota report X */ X#include X#include X#include X#include X#include X#include X#include X#include X Xchar *qfname = QUOTAFILENAME; X Xstruct fileusage { X struct fileusage *fu_next; X struct dqblk fu_dqblk; X u_int fu_id; X char fu_name[1]; X /* actually bigger */ X}; X#define FUHASH 256 /* must be power of two */ Xstruct fileusage *fuhead[FUHASH]; Xstruct fileusage *lookup(); Xstruct fileusage *addid(); Xu_int highid; /* highest addid()'ed identifier per type */ X Xint vflag; /* verbose */ Xint aflag; /* all file systems */ X Xmain(argc, argv) X int argc; X char **argv; X{ X register struct fstab *fs; X register struct passwd *pw; X int errs = 0; X int i, argnum; X long done = 0; X extern char *optarg; X extern int optind; X char ch, *qfnp; X X while ((ch = getopt(argc, argv, "aguv")) != EOF) { X switch(ch) { X case 'a': X aflag++; X break; X case 'v': X vflag++; X break; X default: X usage(); X } X } X argc -= optind; X argv += optind; X if (argc == 0 && !aflag) X usage(); X X setpwent(); X while ((pw = getpwent()) != 0) X (void) addid(pw->pw_uid, pw->pw_name); X endpwent(); X X setfsent(); X while ((fs = getfsent()) != NULL) { X if (strcmp(fs->fs_vfstype, "ufs")) X continue; X if (aflag) { X if (hasquota(fs, &qfnp)) X errs += repquota(fs, qfnp); X continue; X } X if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || X (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { X done |= 1 << argnum; X if (hasquota(fs, &qfnp)) X errs += repquota(fs, qfnp); X } X } X endfsent(); X for (i = 0; i < argc; i++) X if ((done & (1 << i)) == 0) X fprintf(stderr, "%s not found in fstab\n", argv[i]); X exit(errs); X} X Xusage() X{ X fprintf(stderr, "Usage:\n\t%s\n\t%s\n", X "repquota [-v] [-g] [-u] -a", X "repquota [-v] [-g] [-u] filesys ..."); X exit(1); X} X Xrepquota(fs, qfpathname) X register struct fstab *fs; X char *qfpathname; X{ X register struct fileusage *fup; X FILE *qf; X u_int id; X struct dqblk dqbuf; X struct stat statb; X static struct dqblk zerodqblk; X static int warned = 0; X static int multiple = 0; X extern int errno; X X if ((qf = fopen(qfpathname, "r")) == NULL) { X perror(qfpathname); X return (1); X } X if (fstat(fileno(qf), &statb) < 0) { X perror(qfpathname); X fclose(qf); X return(1); X } X if (quota(Q_SYNC, 0, statb.st_dev, 0) < 0 && X errno == EOPNOTSUPP && !warned && vflag) { X warned++; X fprintf(stdout, X "*** Warning: Quotas are not compiled into this kernel\n"); X } X if (multiple++) X printf("\n"); X if (vflag) X fprintf(stdout, "*** Report for quotas on %s (%s)\n", X fs->fs_file, fs->fs_spec); X for (id = 0; ; id++) { X fread(&dqbuf, sizeof(struct dqblk), 1, qf); X if (feof(qf)) X break; X if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) X continue; X if ((fup = lookup(id)) == 0) X fup = addid(id, (char *)0); X fup->fu_dqblk = dqbuf; X } X fclose(qf); X printf(" Block limits File limits\n"); X printf("User used soft hard warn used soft hard warn\n"); X for (id = 0; id <= highid; id++) { X fup = lookup(id); X if (fup == 0) X continue; X if (fup->fu_dqblk.dqb_curinodes == 0 && X fup->fu_dqblk.dqb_curblocks == 0) X continue; X printf("%-10s", fup->fu_name); X printf("%c%c%8ld%8ld%8ld%5u", X fup->fu_dqblk.dqb_bsoftlimit && X fup->fu_dqblk.dqb_curblocks >= X fup->fu_dqblk.dqb_bsoftlimit ? '+' : '-', X fup->fu_dqblk.dqb_isoftlimit && X fup->fu_dqblk.dqb_curinodes >= X fup->fu_dqblk.dqb_isoftlimit ? '+' : '-', X fup->fu_dqblk.dqb_curblocks / 1024, X fup->fu_dqblk.dqb_bsoftlimit / 1024, X fup->fu_dqblk.dqb_bhardlimit / 1024, X fup->fu_dqblk.dqb_bwarn); X X printf(" %6u%6u%6u%6u\n", X fup->fu_dqblk.dqb_curinodes, X fup->fu_dqblk.dqb_isoftlimit, X fup->fu_dqblk.dqb_ihardlimit, X fup->fu_dqblk.dqb_iwarn); X fup->fu_dqblk = zerodqblk; X } X return (0); X} X X/* X * Check to see if target appears in list of size cnt. X */ Xoneof(target, list, cnt) X register char *target, *list[]; X int cnt; X{ X register int i; X X for (i = 0; i < cnt; i++) X if (strcmp(target, list[i]) == 0) X return (i); X return (-1); X} X X/* X * Check to see if a particular quota is to be enabled. X */ Xhasquota(fs, qfnamep) X register struct fstab *fs; X char **qfnamep; X{ X register char *opt; X char *cp; X static char initname, usrname[100]; X static char buf[BUFSIZ]; X X if (!initname) { X strcpy(usrname, qfname); X initname = 1; X } X strcpy(buf, fs->fs_mntops); X for (opt = strtok(buf, ","); opt; opt = strtok(NULL, ",")) { X if (cp = index(opt, '=')) X *cp++ = '\0'; X if (strcmp(opt, usrname) == 0) X break; X if (strcmp(opt, FSTAB_RQ) == 0) /* XXX compatibility */ X break; X } X if (!opt) X return (0); X if (cp) { X *qfnamep = cp; X return (1); X } X (void) sprintf(buf, "%s/%s", fs->fs_file, qfname); X *qfnamep = buf; X return (1); X} X X/* X * Routines to manage the file usage table. X * X * Lookup an id. X */ Xstruct fileusage * Xlookup(id) X u_int id; X{ X register struct fileusage *fup; X X for (fup = fuhead[id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) X if (fup->fu_id == id) X return (fup); X return ((struct fileusage *)0); X} X X/* X * Add a new file usage id if it does not already exist. X */ Xstruct fileusage * Xaddid(id, name) X u_short id; X char *name; X{ X struct fileusage *fup, **fhp; X int len; X extern char *calloc(); X X if (fup = lookup(id)) X return (fup); X if (name) X len = strlen(name); X else X len = 10; X if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) { X fprintf(stderr, "out of memory for fileusage structures\n"); X exit(1); X } X fhp = &fuhead[id & (FUHASH - 1)]; X fup->fu_next = *fhp; X *fhp = fup; X fup->fu_id = id; X if (id > highid) X highid = id; X if (name) { X bcopy(name, fup->fu_name, len + 1); X } else { X sprintf(fup->fu_name, "%u", id); X } X return (fup); X} SHAR_EOF chmod 444 '/usr/src/etc/repquota.c' fi exit 0 # End of shell archive