github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/old/linux_backend/src/repquota/repquota.c (about) 1 #include <assert.h> 2 #include <errno.h> 3 #include <fstab.h> 4 #include <inttypes.h> 5 #include <malloc.h> 6 #include <mntent.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <sys/quota.h> 11 12 /** 13 * Attempts to look up the device name associated with supplied mount point. 14 * 15 * @param dir Mount point to look up 16 * @param dev_name Where to place the device name. Caller must free. 17 * 18 * @return 0 on success 19 * -1 mount point not found 20 * -2 cannot open mtab 21 */ 22 static int lookup_device(const char* dir, char** dev_name) { 23 FILE* mtab = NULL; 24 struct mntent* mtab_entry = NULL; 25 size_t fsname_len = 0; 26 int retval = -1; 27 28 assert(NULL != dir); 29 assert(NULL != dev_name); 30 31 if (NULL == (mtab = setmntent(_PATH_MOUNTED, "r"))) { 32 return -2; 33 } 34 35 while (NULL != (mtab_entry = getmntent(mtab))) { 36 if (!strcmp(mtab_entry->mnt_dir, dir)) { 37 fsname_len = strlen(mtab_entry->mnt_fsname) + 1; 38 39 *dev_name = malloc(fsname_len); 40 assert(NULL != *dev_name); 41 42 strncpy(*dev_name, mtab_entry->mnt_fsname, fsname_len); 43 retval = 0; 44 break; 45 } 46 } 47 48 endmntent(mtab); 49 50 return retval; 51 } 52 53 /** 54 * Attempts to print a helpful error message to stderr. 55 * 56 * @param msg Error message to prepend. 57 */ 58 static void print_quotactl_error(const char* msg) { 59 assert(NULL != msg); 60 61 switch (errno) { 62 case EFAULT: 63 fprintf(stderr, "%s: Block device invalid.\n", msg); 64 break; 65 66 case ENOENT: 67 fprintf(stderr, "%s: Block device doesn't exist.\n", msg); 68 break; 69 70 case ENOSYS: 71 fprintf(stderr, "%s: Kernel doesn't haven quota support.\n", msg); 72 break; 73 74 case ENOTBLK: 75 fprintf(stderr, "%s: Not a block device.\n", msg); 76 break; 77 78 case EPERM: 79 fprintf(stderr, "%s: Insufficient privilege.\n", msg); 80 break; 81 82 case ESRCH: 83 fprintf(stderr, "%s: No quota for supplied user.\n", msg); 84 break; 85 86 default: 87 perror(msg); 88 break; 89 } 90 } 91 92 /** 93 * Prints relevant quota information to stdout for the supplied uid. 94 * On failure, will attempt to print a helpful error messge to stderr. 95 * 96 * @param filesystem Filesystem to report quota information for 97 * @param uid Uid to report quota information for 98 * 99 * @return -1 on error, 0 otherwise 100 */ 101 static int print_quota_usage(const char* filesystem, int uid) { 102 assert(NULL != filesystem); 103 104 char emsg[1024]; 105 struct dqblk quota_info; 106 107 memset("a_info, 0, sizeof(quota_info)); 108 109 if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), filesystem, uid, (caddr_t) "a_info) < 0) { 110 sprintf(emsg, "Failed retrieving quota for uid=%d", uid); 111 print_quotactl_error(emsg); 112 return -1; 113 } 114 115 printf("%d ", uid); 116 117 /* Block info */ 118 printf("%llu %llu %llu %llu ", 119 (long long unsigned int) quota_info.dqb_curspace, 120 (long long unsigned int) quota_info.dqb_bsoftlimit, 121 (long long unsigned int) quota_info.dqb_bhardlimit, 122 (long long unsigned int) quota_info.dqb_btime); 123 124 /* Inode info */ 125 printf("%llu %llu %llu %llu\n", 126 (long long unsigned int) quota_info.dqb_curinodes, 127 (long long unsigned int) quota_info.dqb_isoftlimit, 128 (long long unsigned int) quota_info.dqb_ihardlimit, 129 (long long unsigned int) quota_info.dqb_itime); 130 131 return 0; 132 } 133 134 int main(int argc, char* argv[]) { 135 char* filesystem = NULL; 136 char* device_name = NULL; 137 char** uid_strs = NULL; 138 int* uids = NULL; 139 int num_uids = 0; 140 int ii = 0; 141 142 if (argc < 3) { 143 printf("Usage: report_quota [filesystem] [uid]+\n"); 144 printf("Reports quota information for the supplied uids on the given filesystem\n"); 145 printf("Format is: <uid> <bytes used> <soft> <hard> <grace> <inodes used> <soft> <hard> <grace>\n"); 146 exit(1); 147 } 148 149 filesystem = argv[1]; 150 num_uids = argc - 2; 151 uid_strs = argv + 2; 152 153 if (lookup_device(filesystem, &device_name) < 0) { 154 printf("Couldn't find device for %s\n", argv[1]); 155 exit(1); 156 } 157 158 uids = malloc(sizeof(*uids) * num_uids); 159 assert(NULL != uids); 160 161 memset(uids, 0, sizeof(*uids) * num_uids); 162 for (ii = 0; ii < num_uids; ii++) { 163 uids[ii] = atoi(uid_strs[ii]); 164 } 165 166 for (ii = 0; ii < num_uids; ii++) { 167 if (print_quota_usage(device_name, uids[ii]) < 0) { 168 exit(1); 169 } 170 } 171 172 /* Pedantry! */ 173 free(device_name); 174 free(uids); 175 176 return 0; 177 }