void * needchk(struct fstab *fs) { struct quotaname *qnp; char *qfnp; if (strcmp(fs->fs_vfstype, "ufs") || strcmp(fs->fs_type, FSTAB_RW)) return (NULL); if ((qnp = malloc(sizeof(*qnp))) == NULL) errx(1, "malloc failed"); qnp->flags = 0; if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) { strcpy(qnp->grpqfname, qfnp); qnp->flags |= HASGRP; } if (uflag && hasquota(fs, USRQUOTA, &qfnp)) { strcpy(qnp->usrqfname, qfnp); qnp->flags |= HASUSR; } if (qnp->flags) return (qnp); free(qnp); return (NULL); }
void * needchk(struct fstab *fs) { struct quotaname *qnp; char *qfnp; if (fs->fs_passno == 0) return NULL; if (strcmp(fs->fs_type, FSTAB_RW)) return (NULL); if (strcmp(fs->fs_vfstype, "ffs") && strcmp(fs->fs_vfstype, "ufs") && strcmp(fs->fs_vfstype, "mfs")) return (NULL); if ((qnp = malloc(sizeof(*qnp))) == NULL) err(1, "%s", strerror(errno)); qnp->flags = 0; if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) { strlcpy(qnp->grpqfname, qfnp, sizeof qnp->grpqfname); qnp->flags |= HASGRP; } if (uflag && hasquota(fs, USRQUOTA, &qfnp)) { strlcpy(qnp->usrqfname, qfnp, sizeof qnp->usrqfname); qnp->flags |= HASUSR; } if (qnp->flags) return (qnp); free(qnp); return (NULL); }
void displayquota(Quota * const quota_) { Quota quota; double pct; if (hasquota() != 0) { return; } if (quota_ == NULL) { if (quota_update("a, 0LL, 0LL, NULL) != 0) { return; } } else { quota = *quota_; } if (user_quota_files < ULONG_LONG_MAX) { pct = (double) quota.files * 100.0 / (double) user_quota_files; addreply(0, MSG_QUOTA_FILES, quota.files, (int) pct, (unsigned long long) user_quota_files); } if (user_quota_size < ULONG_LONG_MAX) { pct = (double) quota.size * 100.0 / (double) user_quota_size; addreply(0, MSG_QUOTA_SIZE, quota.size / 1024ULL, (int) pct, (unsigned long long) user_quota_size / 1024ULL); } }
int quota_update(Quota *quota, const long long files_add, const long long size_add, int *overflow) { int fd; Quota old_quota = { 0ULL, 0ULL }; Quota dummy_quota; struct flock lock; ssize_t readnb; int err = -1; char buf[84]; char *bufpnt = buf; int dummy_overflow; ssize_t left = (ssize_t) (sizeof buf - 1U); size_t buf_len; if (hasquota() != 0 || chrooted == 0) { return -2; } if (overflow == NULL) { overflow = &dummy_overflow; } if (quota == NULL) { quota = &dummy_quota; } *overflow = 0; *quota = old_quota; if ((fd = open("/" QUOTA_FILE, O_RDWR | O_CREAT | O_NOFOLLOW, (mode_t) 0600)) == -1) { return -1; } lock.l_whence = SEEK_SET; lock.l_start = (off_t) 0; lock.l_len = (off_t) 0; lock.l_pid = getpid(); lock.l_type = F_WRLCK; while (fcntl(fd, F_SETLKW, &lock) < 0) { if (errno != EINTR) { goto byenounlock; } } do { while ((readnb = read(fd, bufpnt, left)) < (ssize_t) 0 && errno == EINTR); if (readnb < (ssize_t) 0) { goto bye; } bufpnt += readnb; left -= readnb; } while (left > (ssize_t) 0 && readnb != (ssize_t) 0); *bufpnt = 0; if ((bufpnt = strchr(buf, ' ')) == NULL) { goto skipparse; } *bufpnt = 0; old_quota.files = quota->files = strtoull(buf, NULL, 10); old_quota.size = quota->size = strtoull(bufpnt + 1, NULL, 10); skipparse: if ((files_add | size_add) == 0LL) { goto okbye; } if (files_add < 0LL) { if (quota->files > (unsigned long long) -files_add) { quota->files -= (unsigned long long) (-files_add); } else { quota->files = 0ULL; } } else if (files_add >= 0LL) { quota->files += (unsigned long long) files_add; if (quota->files > user_quota_files) { *overflow = 1; } } if (size_add < 0LL) { if (quota->size > (unsigned long long) -size_add) { quota->size -= (unsigned long long) (-size_add); } else { quota->size = 0ULL; } } else if (size_add >= 0LL) { quota->size += size_add; if (quota->size > user_quota_size) { *overflow = 2; } } if ((old_quota.size != quota->size || old_quota.files != quota->files) && !SNCHECK(snprintf(buf, sizeof buf, "%llu %llu\n", quota->files, quota->size), sizeof buf) && lseek(fd, (off_t) 0, SEEK_SET) != (off_t) -1 && ftruncate(fd, (off_t) 0) == 0) { buf_len = strlen(buf); if (safe_write(fd, buf, buf_len, -1) != (ssize_t) buf_len) { (void) ftruncate(fd, (off_t) 0); goto bye; } } okbye: err = 0; bye: lock.l_type = F_UNLCK; while (fcntl(fd, F_SETLK, &lock) < 0 && errno == EINTR); byenounlock: close(fd); return err; }
/* * Collect the requested quota information. */ struct quotause * getprivs(long id, int quotatype, char *fspath) { struct fstab *fs; struct quotause *qup, *quptail; struct quotause *quphead; int qcmd, qupsize, fd; char *qfpathname; static int warned = 0; setfsent(); quphead = quptail = NULL; qcmd = QCMD(Q_GETQUOTA, quotatype); while ((fs = getfsent())) { if (fspath && *fspath && strcmp(fspath, fs->fs_spec) && strcmp(fspath, fs->fs_file)) continue; if (strcmp(fs->fs_vfstype, "ufs")) continue; if (!hasquota(fs, quotatype, &qfpathname)) continue; qupsize = sizeof(*qup) + strlen(qfpathname); if ((qup = (struct quotause *)malloc(qupsize)) == NULL) errx(2, "out of memory"); if (quotactl(fs->fs_file, qcmd, id, &qup->dqblk) != 0) { if (errno == EOPNOTSUPP && !warned) { warned++; warnx("warning: quotas are not compiled into this kernel"); sleep(3); } if ((fd = open(qfpathname, O_RDONLY)) < 0) { fd = open(qfpathname, O_RDWR|O_CREAT, 0640); if (fd < 0 && errno != ENOENT) { warn("%s", qfpathname); free(qup); continue; } warnx("creating quota file %s", qfpathname); sleep(3); fchown(fd, getuid(), getentry(quotagroup, GRPQUOTA)); fchmod(fd, 0640); } lseek(fd, (long)(id * sizeof(struct ufs_dqblk)), L_SET); switch (read(fd, &qup->dqblk, sizeof(struct ufs_dqblk))) { case 0: /* EOF */ /* * Convert implicit 0 quota (EOF) * into an explicit one (zero'ed dqblk) */ bzero((caddr_t)&qup->dqblk, sizeof(struct ufs_dqblk)); break; case sizeof(struct ufs_dqblk): /* OK */ break; default: /* ERROR */ warn("read error in %s", qfpathname); close(fd); free(qup); continue; } close(fd); } strcpy(qup->qfname, qfpathname); strcpy(qup->fsname, fs->fs_file); if (quphead == NULL) quphead = qup; else quptail->next = qup; quptail = qup; qup->next = NULL; } endfsent(); return (quphead); }
int main(int argc, char **argv) { struct fstab *fs; struct passwd *pw; struct group *gr; int gflag = 0, uflag = 0, errs = 0; long i, argnum, done = 0; char ch, *qfnp; while ((ch = getopt(argc, argv, "aguv")) != -1) { switch(ch) { case 'a': aflag++; break; case 'g': gflag++; break; case 'u': uflag++; break; case 'v': vflag++; break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0 && !aflag) usage(); if (!gflag && !uflag) { if (aflag) gflag++; uflag++; } if (gflag) { setgrent(); while ((gr = getgrent()) != 0) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); endgrent(); } if (uflag) { setpwent(); while ((pw = getpwent()) != 0) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); endpwent(); } setfsent(); while ((fs = getfsent()) != NULL) { if (strcmp(fs->fs_vfstype, "ufs")) continue; if (aflag) { if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) errs += repquota(fs, GRPQUOTA, qfnp); if (uflag && hasquota(fs, USRQUOTA, &qfnp)) errs += repquota(fs, USRQUOTA, qfnp); continue; } if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { done |= 1 << argnum; if (gflag && hasquota(fs, GRPQUOTA, &qfnp)) errs += repquota(fs, GRPQUOTA, qfnp); if (uflag && hasquota(fs, USRQUOTA, &qfnp)) errs += repquota(fs, USRQUOTA, qfnp); } } endfsent(); for (i = 0; i < argc; i++) if ((done & (1 << i)) == 0) warnx("%s not found in fstab", argv[i]); exit(errs); }
struct quotafile * quota_open(struct fstab *fs, int quotatype, int openflags) { struct quotafile *qf; struct dqhdr64 dqh; struct group *grp; struct stat st; int qcmd, serrno; if (strcmp(fs->fs_vfstype, "ufs")) return (NULL); if ((qf = calloc(1, sizeof(*qf))) == NULL) return (NULL); qf->fd = -1; qf->quotatype = quotatype; strncpy(qf->fsname, fs->fs_file, sizeof(qf->fsname)); if (stat(qf->fsname, &st) != 0) goto error; qf->dev = st.st_dev; serrno = hasquota(fs, quotatype, qf->qfname, sizeof(qf->qfname)); qcmd = QCMD(Q_GETQUOTASIZE, quotatype); if (quotactl(qf->fsname, qcmd, 0, &qf->wordsize) == 0) return (qf); if (serrno == 0) { errno = EOPNOTSUPP; goto error; } qf->accmode = openflags & O_ACCMODE; if ((qf->fd = open(qf->qfname, qf->accmode)) < 0 && (openflags & O_CREAT) != O_CREAT) goto error; /* File open worked, so process it */ if (qf->fd != -1) { qf->wordsize = 32; switch (read(qf->fd, &dqh, sizeof(dqh))) { case -1: goto error; case sizeof(dqh): if (strcmp(dqh.dqh_magic, Q_DQHDR64_MAGIC) != 0) { /* no magic, assume 32 bits */ qf->wordsize = 32; return (qf); } if (be32toh(dqh.dqh_version) != Q_DQHDR64_VERSION || be32toh(dqh.dqh_hdrlen) != sizeof(struct dqhdr64) || be32toh(dqh.dqh_reclen) != sizeof(struct dqblk64)) { /* correct magic, wrong version / lengths */ errno = EINVAL; goto error; } qf->wordsize = 64; return (qf); default: qf->wordsize = 32; return (qf); } /* not reached */ } /* open failed, but O_CREAT was specified, so create a new file */ if ((qf->fd = open(qf->qfname, O_RDWR|O_CREAT|O_TRUNC, 0)) < 0) goto error; qf->wordsize = 64; memset(&dqh, 0, sizeof(dqh)); memcpy(dqh.dqh_magic, Q_DQHDR64_MAGIC, sizeof(dqh.dqh_magic)); dqh.dqh_version = htobe32(Q_DQHDR64_VERSION); dqh.dqh_hdrlen = htobe32(sizeof(struct dqhdr64)); dqh.dqh_reclen = htobe32(sizeof(struct dqblk64)); if (write(qf->fd, &dqh, sizeof(dqh)) != sizeof(dqh)) { /* it was one we created ourselves */ unlink(qf->qfname); goto error; } grp = getgrnam(QUOTAGROUP); fchown(qf->fd, 0, grp ? grp->gr_gid : 0); fchmod(qf->fd, 0640); return (qf); error: serrno = errno; /* did we have an open file? */ if (qf->fd != -1) close(qf->fd); free(qf); errno = serrno; return (NULL); }
/* * Collect the requested quota information. */ struct quotause * getprivs(u_int id, int quotatype) { struct fstab *fs; struct quotause *qup, *quptail; struct quotause *quphead; int qcmd, qupsize, fd; u_int mid; char *qfpathname; static int warned = 0; size_t qfpathnamelen; setfsent(); quphead = NULL; qcmd = QCMD(Q_GETQUOTA, quotatype); while ((fs = getfsent())) { if (strcmp(fs->fs_vfstype, "ffs") && strcmp(fs->fs_vfstype, "ufs") && strcmp(fs->fs_vfstype, "mfs")) continue; if (!hasquota(fs, quotatype, &qfpathname)) continue; qfpathnamelen = strlen(qfpathname); qupsize = sizeof(*qup) + qfpathnamelen; if ((qup = (struct quotause *)malloc(qupsize)) == NULL) errx(2, "out of memory"); if (quotactl(fs->fs_file, qcmd, id, (char *)&qup->dqblk) != 0) { if (errno == EOPNOTSUPP && !warned) { warned++; (void)fprintf(stderr, "Warning: %s\n", "Quotas are not compiled into this kernel"); sleep(3); } if (getentry(quotagroup, GRPQUOTA, &mid) == -1) { warned++; (void)fprintf(stderr, "Warning: " "group %s not known, skipping %s\n", quotagroup, fs->fs_file); } if ((fd = open(qfpathname, O_RDONLY)) < 0) { fd = open(qfpathname, O_RDWR|O_CREAT, 0640); if (fd < 0 && errno != ENOENT) { perror(qfpathname); free(qup); continue; } (void)fprintf(stderr, "Creating quota file %s\n", qfpathname); sleep(3); (void)fchown(fd, getuid(), mid); (void)fchmod(fd, 0640); } lseek(fd, (off_t)(id * sizeof(struct dqblk)), SEEK_SET); switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) { case 0: /* EOF */ /* * Convert implicit 0 quota (EOF) * into an explicit one (zero'ed dqblk) */ bzero((caddr_t)&qup->dqblk, sizeof(struct dqblk)); break; case sizeof(struct dqblk): /* OK */ break; default: /* ERROR */ warn("read error in %s", qfpathname); close(fd); free(qup); continue; } close(fd); } strlcpy(qup->qfname, qfpathname, qfpathnamelen + 1); strlcpy(qup->fsname, fs->fs_file, sizeof qup->fsname); if (quphead == NULL) quphead = qup; else quptail->next = qup; quptail = qup; qup->next = NULL; } endfsent(); return(quphead); }