#include #include #include #include #include #include #include #include "diskquotaconf.h" #include "diskquotaconf.m" #include #include #include #include "quota.h" using namespace std; static HELP_FILE help_quotarep ("diskquotaconf","quotarep"); static void formatlimit (int limit, char s[20]) { if (limit == 0){ s[0] = '-'; s[1] = '\0'; }else{ sprintf (s,"%d",limit); } } struct QREC{ int id; int gid; int bused; int bslimit; int bhlimit; int fused; int fslimit; int fhlimit; string idstr; string gecos; string gidstr; bool operator < (const QREC &q) const { return bused < q.bused; } /* Format the limit. Place - instead of 0 to indicate no limit */ void formatlimit (char bslim[20],char bhlim[20],char fslim[20],char fhlim[20]) { ::formatlimit (bslimit,bslim); ::formatlimit (bhlimit,bhlim); ::formatlimit (fslimit,fslim); ::formatlimit (fhlimit,fhlim); } /* Return 0 if the account is not over any quota 1 if it is over one soft quota 2 if it is over one hard quota */ int status(){ int ret = 0; if (bused >= bhlimit && bhlimit != 0){ ret = 2; }else if (bused >= bslimit && bslimit != 0){ ret = 1; } if (ret != 2){ if (fused >= fhlimit && fhlimit != 0){ ret = 2; }else if (fused >= fslimit && fslimit != 0){ ret = 1; } } return ret; } }; static bool CMP_QREC_BY_GROUP (const QREC &a, const QREC &b) { bool ret = a.gidstr < b.gidstr; if (a.gidstr == b.gidstr) ret = a.bused < b.bused; return ret; } static void quota_loadinfo( bool usrquota, bool userinfo, // Fill the user name, gecos and friends // doing and getpwuid() const char *device, vector &tb, map &groups) { tb.clear(); glocal bool usrquota = usrquota; glocal bool userinfo = userinfo; SSTRING args; args.setfromf ("-n %s %s" ,usrquota ? "-u" : "-g" ,device); glocal bool start = false; glocal vector *tb = &tb; ("repquota",args.get(),10); if (glocal.start){ char flags[100],f[5][100]; QREC rec; // repquota produce a variable number of columns, but // the second colums (flags) has + sign to tell if the grace // column is there or not. There is one plus for the block limit // and one plus for the file limit. int ns; if ((ns=sscanf (line,"#%d %s %d %d %d %s %s %s %s %s" ,&rec.id,flags,&rec.bused,&rec.bslimit,&rec.bhlimit ,f[0],f[1],f[2],f[3],f[4]))>=8){ if (flags[0] == '+' || ns >= 9){ rec.fused = atoi(f[1]); rec.fslimit = atoi(f[2]); rec.fhlimit = atoi(f[3]); }else{ rec.fused = atoi(f[0]); rec.fslimit = atoi(f[1]); rec.fhlimit = atoi(f[2]); } rec.gid = -1; if (glocal.usrquota){ if (glocal.userinfo){ struct passwd *p = getpwuid (rec.id); if (p != NULL){ rec.gid = p->pw_gid; rec.idstr = p->pw_name; rec.gecos = p->pw_gecos; }else{ char tmp[20]; sprintf (tmp,"#%d",rec.id); rec.idstr = tmp; } } }else{ rec.gid = rec.id; } glocal.tb->push_back (rec); } }else{ if (strncmp(line,"-----",5)==0){ glocal.start = true; } } return 0; for (unsigned i=0; i void quota_show (const char *device, bool usrquota) { glocal bool usrquota = usrquota; glocal const char *device = device; glocal bool reload = true; glocal map groups; glocal vector tb; glocal set expanded; // Groups where users are shown { // Fill the map struct group *g; setgrent(); while ((g=getgrent())!=NULL) glocal.groups[g->gr_gid] = g->gr_name; } SSTRING tmpt; tmpt.setfromf ("%s: %s" ,usrquota ? MSG_U(T_UQUOTAREP,"User disk quota report") : MSG_U(T_GQUOTAREP,"Group disk quota report") ,device); (tmpt.get(),"",help_quotarep); sortable(); if (glocal.usrquota){ newf_head (MSG_U(H_QUOTAREP,"Group\tUser\tSpace(K)\tMax.(s)\tMax.(h)\tFiles\tMax.(s)\tMax.(h)\tUser name")); sethdispo ("llrrrrrrl"); sortpolicy ("aannnnnna"); }else{ sethdispo ("lrrrrrr"); sortpolicy ("annnnnn"); newf_head (MSG_U(H_QUOTAREPG,"Group\tSpace(K)\tMax.(s)\tMax.(h)\tFiles\tMax.(s)\tMax.(h)")); } setbutinfo (MENU_USR1,MSG_U(B_RELOAD,"Reload"),MSG_R(B_RELOAD)); if (glocal.reload){ glocal.reload = false; quota_loadinfo (glocal.usrquota,true,glocal.device,glocal.tb,glocal.groups); } // Define the 3 drawing context // black: all fine // orange: over soft quota // red: over hard quota const char *font = guiid_setfont (10,GFONT_ID_DEFAULT,GFONT_STYLE_DEFAULT,GFONT_WEIGHT_DEFAULT,false); const char *penorange = guiid_setpen ("orange"); const char *penred = guiid_setpen ("red"); const char *dcblack = guiid_setdc (font,NULL,NULL); const char *dcorange = guiid_setdc (font,penorange,NULL); const char *dcred = guiid_setdc (font,penred,NULL); const char *tbdc[]={dcblack,dcorange,dcred}; if (glocal.usrquota){ int lastgid = -2; set::iterator endexp = glocal.expanded.end(); for (unsigned i=0; i status) status = st; total.bused += r.bused; total.fused += r.fused; } } char tmp[20]; snprintf (tmp,sizeof(tmp)-1,MSG_U(I_NUSERS,"%4d account(s)"),j-i); total.gecos = tmp; i=j-1; } lastgid = rec.gid; setnextdcs (tbdc[status]); char bslimit[20],bhlimit[20],fslimit[20],fhlimit[20]; total.formatlimit (bslimit,bhlimit,fslimit,fhlimit); new_menuitemf (total.gidstr.c_str(),"%s\t%d\t%s\t%s\t%d\t%s\t%s\t%s" ,total.idstr.c_str() ,total.bused,bslimit,bhlimit ,total.fused,fslimit,fhlimit ,total.gecos.c_str()); set_lookup (starti); } }else{ for (unsigned i=0; i if (glocal.usrquota){ QREC &rec = glocal.tb[no]; set::iterator it = glocal.expanded.find(rec.gid); if (it == glocal.expanded.end()){ // Add in set glocal.expanded.insert (rec.gid); }else{ glocal.expanded.erase (it); } } glocal.reload = true; } /* Start quota_show in a different uithread. */ static void quota_showt (const char *device, bool userquota) { glocal const char *device = device; glocal bool userquota = userquota; (true); string device = glocal.device; dontwait(); quota_show (device.c_str(),glocal.userquota); } void quota_show() { glocal FSTAB fstab; (MSG_U(T_QUOTA,"Disk quota report") ,"",help_nil); newf_head (MSG_U(H_DQUOTA,"Device\tMount point\tUser quota\tGroup quota")); sortable(); sortpolicy ("aaaa"); sethdispo ("llll"); for (int i=0; iis_valid() && en->gettype() == FSTAB_ENTRY_LOCAL){ new_menuitemf (en->getsource(),"%s\t%s\t%s" ,en->getmpoint() ,en->has_quota_u() ? MSG_U(I_ENABLED,"Enabled") : "" ,en->has_quota_g() ? MSG_R(I_ENABLED) : ""); set_lookup(i); } } FSTAB_ENTRY *en = glocal.fstab.getitem(no); if (!en->has_quota_u() && !en->has_quota_g()){ xconf_notice (MSG_U(N_NOQUOTA ,"Quota not enabled for this file system")); }else{ const char *mpoint = en->getmpoint(); SSTRINGS tb; if (en->has_quota_u() && en->has_quota_g()){ DIALOG_MENUPOPUP dia; dia.new_menuitem ("",MSG_U(M_SHOWUSER,"Show user quota report")); dia.new_menuitem ("",MSG_U(M_SHOWGROUP,"Show group quota report")); int nof = 0; if (dia.editmenu (MSG_U(M_SELREPORT,"Select a report"),nof) ==MENU_OK){ quota_showt (mpoint,nof==0); } }else if (en->has_quota_u()){ quota_showt (mpoint,true); }else if (en->has_quota_g()){ quota_showt (mpoint,false); } } } /* Get the disk usage for a user or group based on the repquota utility */ int show_getquota (const char *device, bool usrquota, int id, QUOTA_USED &used) { int ret = -1; vector tb; map groups; quota_loadinfo (usrquota,false,device,tb,groups); int n = tb.size(); for (int i=0; i