1 /*
2 * quota.c
3 * (C)1998-2011 by Marc Huber <Marc.Huber@web.de>
4 *
5 * $Id: quota.c,v 1.13 2015/03/14 06:11:27 marc Exp marc $
6 *
7 */
8
9 #include <sys/types.h>
10 #include "headers.h"
11 #include <unistd.h>
12 #include <fcntl.h>
13
14 static const char rcsid[] __attribute__ ((used)) = "$Id: quota.c,v 1.13 2015/03/14 06:11:27 marc Exp marc $";
15
16 static int lock(int);
17
quota_add(struct context * ctx,long long q)18 void quota_add(struct context *ctx, long long q)
19 {
20 int f;
21 ssize_t i;
22 char buffer[20];
23
24 if (!ctx->quota_path)
25 return;
26
27 setegid(real_uid);
28 seteuid(real_gid);
29 f = open(ctx->quota_path, O_RDWR | O_CREAT | O_NOFOLLOW, 0644);
30 if (f > -1) {
31 if (!lock(f)) {
32 buffer[0] = 0;
33 i = read(f, buffer, sizeof(buffer) - 1);
34
35 if (i > 0)
36 buffer[i] = 0;
37
38 sscanf(buffer, "%lld", &ctx->quota_ondisk);
39
40 if (q < 0 && ctx->quota_ondisk < -q)
41 ctx->quota_ondisk = 0;
42 else
43 ctx->quota_ondisk += q;
44
45 if (q) {
46 lseek(f, 0, SEEK_SET);
47 if (ftruncate(f, 0)) {
48 //FIXME
49 }
50
51 snprintf(buffer, sizeof(buffer), "%lld", ctx->quota_ondisk);
52 if (write(f, buffer, strlen(buffer))) {
53 //FIXME
54 }
55 }
56 } else
57 logmsg("Updating quota file %s failed (%lld).", ctx->quota_path, q);
58 close(f);
59 }
60 setegid(ctx->gid);
61 seteuid(ctx->uid);
62 }
63
lock(int fn)64 static int lock(int fn)
65 {
66 struct flock fl;
67 int i;
68 sigset_t sig_set;
69
70 Debug((DEBUG_LOCK, "+ %s (%d)\n", __func__, fn));
71
72 fl.l_type = F_WRLCK; /* exclusive lock */
73 fl.l_whence = SEEK_SET;
74 fl.l_len = 0; /* lock whole file */
75 fl.l_start = 0;
76
77 sigemptyset(&sig_set);
78 sigaddset(&sig_set, SIGALRM);
79 sigprocmask(SIG_UNBLOCK, &sig_set, NULL);
80
81 alarm(2); /* wait at most 2 seconds for the lock */
82 i = fcntl(fn, F_SETLKW, &fl);
83 alarm(0);
84
85 sigprocmask(SIG_BLOCK, &sig_set, NULL);
86
87 Debug((DEBUG_LOCK, "- %s %s\n", __func__, i ? "FAILURE" : "SUCCESS"));
88 return i;
89 }
90