summaryrefslogtreecommitdiff
path: root/alpine/osdep/sunquota
blob: 3528a1bb9dfa6e5bc9998b4386adb712a6f9c633 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
static char *device_name();

/*----------------------------------------------------------------------
   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);
}