summaryrefslogtreecommitdiff
path: root/alpine/osdep/solquota
diff options
context:
space:
mode:
Diffstat (limited to 'alpine/osdep/solquota')
-rw-r--r--alpine/osdep/solquota174
1 files changed, 174 insertions, 0 deletions
diff --git a/alpine/osdep/solquota b/alpine/osdep/solquota
new file mode 100644
index 00000000..348bad2a
--- /dev/null
+++ b/alpine/osdep/solquota
@@ -0,0 +1,174 @@
+static char *device_name();
+
+#include <fcntl.h>
+#include <sys/fs/ufs_quota.h>
+
+/*
+ * define the "quotactl" function as in Solaris 1, based on ioctl().
+ * By Marc Mazuhelli <mazu@dmi.usherb.ca>
+ * The "special" parameter is any file on the file system,
+ * not the block special device name as in Solaris 1.
+ * Thanks to veronica@solution.maths.unsw.edu.au who provided
+ * the idea and the basis for this function.
+ *
+ * [ Apparently quotactl used to exist in SunOS but no longer exists in ]
+ * [ Solaris. This is an equivalent. If you are running on a system ]
+ * [ which has quotactl, comment this routine out or use sunquota. ]
+ */
+
+int
+quotactl(int cmd, char *special, uid_t uid, struct dqblk * addr)
+{
+ struct quotctl op;
+ int fd = open(special, O_RDONLY);
+
+ if (fd < 0)
+ return -1;
+
+ op.op = cmd;
+ op.uid = uid;
+ op.addr = (caddr_t) addr;
+
+ if (ioctl(fd, Q_QUOTACTL, &op) < 0) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return (0);
+}
+
+
+/*----------------------------------------------------------------------
+ Return space left in disk quota on file system which given path is in.
+
+ Args: path - Path name of file or directory on file system of concern
+ over - pointer to flag that is set if the user is over quota
+
+ Returns: If *over = 0, the number of bytes free in disk quota as per
+ the soft limit.
+ If *over = 1, the number of bytes *over* quota.
+ -1 is returned on an error looking up quota
+ 0 is returned if there is no quota
+
+BUG: If there's more than 2.1Gb free this function will break
+ ----*/
+long
+disk_quota(path, over)
+ char *path;
+ int *over;
+{
+ static int no_quota = 0;
+ struct stat statx;
+ struct dqblk quotax;
+ long q;
+ char *dname;
+
+ if(no_quota)
+ return(0L); /* If no quota the first time, then none the second. */
+
+ dprint(5, (debugfile, "quota_check path: %s\n", path ? path : "?"));
+ if(stat(path, &statx) < 0) {
+ return(-1L);
+ }
+
+ *over = 0;
+ errno = 0;
+
+ dname = device_name(statx.st_dev);
+ if(dname == NULL)
+ return(-1L);
+
+ dprint(7, (debugfile, "Quota check: UID:%d device: %s\n",
+ getuid(), dname ? dname : "?"));
+ if(quotactl(Q_GETQUOTA, dname, getuid(), (char *)&quotax) < 0) {
+ dprint(5, (debugfile, "Quota failed : %s\n",
+ error_description(errno)));
+ return(-1L); /* Something went wrong */
+ }
+
+ dprint(5,(debugfile,"Quota: bsoftlimit:%d bhardlimit:%d curblock:%d\n",
+ quotax.dqb_bsoftlimit, quotax.dqb_bhardlimit, quotax.dqb_curblocks));
+
+ if(quotax.dqb_bsoftlimit == -1)
+ return(-1L);
+
+ q = (quotax.dqb_bsoftlimit - quotax.dqb_curblocks) * 512;
+
+ if(q < 0) {
+ q = -q;
+ *over = 1;
+ }
+ dprint(5, (debugfile, "disk_quota returning :%d, over:%d\n", q, *over));
+ return(q);
+}
+
+
+/*----------------------------------------------------------------------
+ * devNumToName
+ *
+ * This routine is here so that ex can get a device name to check
+ * disk quotas. One might wonder, why not use getmntent(), rather
+ * than read /etc/mtab in this crude way? The problem with getmntent
+ * is that it uses stdio, and ex/vi pointedly doesn't.
+ ----*/
+static char
+*device_name(st_devArg)
+ dev_t st_devArg;
+{
+#ifndef MTABNAME
+#define MTABNAME "/etc/mtab"
+#endif
+ char *mtab;
+ static char devName[48];
+ static char *answer = (char *) 0;
+ struct stat devStat;
+ static dev_t st_dev;
+ int nb, cur, bol;
+ char c;
+ int dname;
+
+ if (st_devArg == st_dev)
+ return answer;
+
+ mtab = read_file(MTABNAME);
+ if(mtab == NULL)
+ return((char *)NULL);
+
+ /* Initialize save data. */
+ st_dev = st_devArg;
+ answer = (char *) 0;
+ nb = strlen(mtab);
+
+ for (cur=bol=0, dname=1; cur < nb; ++cur) {
+
+ if (dname && (mtab[cur] <= ' ')) {
+ /* Space, tab or other such character has been found,
+ presumably marking the end of the device name string. */
+
+ dname = 0;
+ c = mtab[cur]; /* Save current character. */
+ mtab[cur] = 0; /* C zero-terminated string. */
+
+ /* Get device number, via stat(). If it's the right
+ number, copy the string and return its address. */
+ if (stat (&mtab[bol], &devStat) == 0) {
+ if (devStat.st_rdev == st_dev) {
+ if ((cur - bol + 1) < sizeof (devName)) {
+ strncpy (devName, &mtab[bol], sizeof(devName));
+ devName[sizeof(devName)-1] = '\0';
+ answer = &devName[0];
+ return(answer);
+ }
+ }
+ }
+ mtab[cur] = c;
+ }
+ if (mtab[cur] == '\n') {
+ dname = 1;
+ bol = cur + 1;
+ }
+ }
+ answer = NULL;
+
+ return(answer);
+}