.title DISKUSE - Get disk quota usage for this user ;+ ; ; Author: ; Dave Leonard, Advanced Data Management, 12-DEC-1980 ; ; Revised: ; 20-may-1981, put in "day-quota-exceeded" check to not ; cause problems with running jobs when other users login ; ; Revised: ; dd-mmm-198y, Tom Gerhard, ADM - support group-wide quotas. ; ; Restrictions: ; 1) Only the users default disk is checked. ; ; 2) All files owned by the UIC are counted towards the usage ; count, this means all files on [0,0] (directories for example) ; and all lost files are counted. Thus the user may see some ; discrepency between the number on his directory listing and ; what the quota usage shows. NOTE: File headers are also counted ; in this total. Thus one block/file surcharge is counted. ; ; 3) There is no convient way to get a breakdown of where all ; the contributing files are. i.e. what directory they are on. ; ; Usage: ; First thing to do is to set up the QUOTA files for your site. ; See the system managers guide (chapter 6) for more info on ; running the DISKQUOTA utility. Set the default([000,000]), to ; the max allowed, or 999999 blocks for both OVERDRAFT and PERMANANT. ; Issue a REBUILD command, and then set the OVERDRAFT limit to ; the actual quota assigned to each UIC. ; ; (CAUTION - you must not have any users on your system while doing ; the REBUILD as it write-locks the pack while it's in progress!!!) ; ; As this program requires write access to the quota file on ; each disk it is run from, either the quota file must be writeable ; by all users, or this program must be installed with SYSPRV ; privilege. If the quota file is made writeable, it is recommended ; that SYS$SYSTEM:DISKQUOTA.EXE be protected from read and execute ; access by WORLD. ; ; Description: ; ; Individual quotas: ; DISKUSE - is a routine that is run at login time. Usually ; by inserting the command ; ; $ RUN SYS$SYSTEM:DISKUSE ; ; in the common login file for all users (typically ; SYS$MANAGER:SYLOGIN.COM). Its purpose is to check the ; disk space used by the running UIC and compare ; the space used with the number in the QUOTA.SYS file. The ; QUOTA.SYS file has two entries, one for PERMANANT limit and one ; for OVERDRAFT limit. The scheme used here is to actually use ; the number in the OVERDRAFT slot as the actual disk quota. The ; PERMANANT limit is usually set to twice the OVERDRAFT limit. ; If the user has exceeded the disk blocks specified in the ; OVERDRAFT slot, his PERMANANT entry is reduced to the number ; in the OVERDRAFT entry and the user is notified that his disk ; usage is over the allowed limit. This efectively lowers the boom ; on a user who uses a lot of temporary storage, and does not delete ; his files after he is done. It allows him to run up to double ; his assigned quota before he is denied disk space. ; ; At that time, when the user logs in, he is notified that he has ; excluded his quota, and that he has one day to clean things up. ; He will continue to get this message for one day, after that, ; the actual diskquota will be set down to the overdraft limit. ; ; This scheme is considerably nicer to the user than DEC's ; hard and fast limits. ; ; If the user has logged on with excessive disk usage for more ; than one day, he is restricted to his quota until he cleans up ; his directory and logs in again. At that time, the usage is ; again checked, if it is below the allowed limit, (in the ; OVERDRAFT slot), the actual PERMANANT entry is set to twice ; the OVERDRAFT number and the user is notified that his quota ; has been lifted. ; ; Group quotas: ; To implement a quota for an entire UIC group, make an entry ; for the UIC [group,0] with the overdraft set to the desired ; quota for the group, and the permanent quota set to twice ; the overdraft. For each member, enter a small number in the ; overdraft, and twice that number for permanent. When any ; user in the group logs in, the useage for the group is summed ; and reported. If the group usage is over the quota defined ; by the entry for [group,0], both the group and individual member ; entries are flagged as described under individual quotas. ; Thus, one member of a group (i.e. a manager) can be given an ; overdraft large enough so that he can continue to create and ; extend files even though the group has exceeded it's quota. ; NOTE that this algorithm needs to handle users with a UIC of ; [group,0] as a special case. ;- .enable sup .disable global .library 'SYS$LIBRARY:LIB' $DQFDEF ; Disk Quota File block $FIBDEF ; File ID Block $IODEF ; I/O def's $JPIDEF ; Job Process Info $qiowdef $SSDEF .external LIB$PUT_OUTPUT .entry DISKUSE, ^m $ASSIGN_S - ; assign channel to SYS$DISK DEVNAM=drive, - CHAN=channel blbs r0, 10$ ; go o.k. ? ret 10$: movab fibblk, r10 movw #fib$c_exa_quota, fib$w_cntrlfunc(r10) ; examine quota entry $getjpi_s itmlst = items ; get [group,member] blbs r0, 15$ ret ;+ ; get date ;- 15$: $numtim_s - timbuf = time_buf movzwl time_buf+4, bindate movab dqfblk, r11 moval acp_qio, r0 movzwl channel, qiow$_chan(r0) movl #io$_acpcontrol, qiow$_func(r0) movaq iosb, qiow$_iosb(r0) movaq fibdesc, qiow$_p1(r0) movaq dqfdesc, qiow$_p2(r0) movaq dqfblklen, qiow$_p3(r0) movaq dqfdesc, qiow$_p4(r0) clrq qiow$_p5(r0) movw group, DQF$L_UIC+2(r11) clrw dqf$l_uic(r11) ; Check for group-wide quota check_quota: $qiow_g acp_qio blbc r0, 10$ movzwl iosb, r0 blbs r0, 20$ 10$: cmpl r0, #ss$_nodiskquota bneq 15$ tstw dqf$l_uic(r11) ; Check for group-wide quota bneq 15$ ;+ ; No group-wide quota - specify exact member number and re-try ;- movw member, dqf$l_uic(r11) brb check_quota 15$: ret 20$: tstw dqf$l_uic(r11) bneq 25$ bsbw scan_group 25$: $FAO_S - member_hdr, - outlength, - outlinedesc, - P1=DQF$L_UIC+2(r11), - P2=DQF$L_UIC(r11), - P3=DQF$L_USAGE(r11), - P4=DQF$L_OVERDRAFT(r11) blbc r0, 40$ pushab outlinedesc calls #1, g^LIB$PUT_OUTPUT blbs r0, 50$ 40$: ret 50$: cmpl DQF$L_USAGE(r11), DQF$L_OVERDRAFT(r11) ; exceede allowed ? bgtr 60$ ; screw this guy ashl #1, DQF$L_OVERDRAFT(r11), r9 ; mult overdraft by 2 cmpl r9, DQF$L_PERMQUOTA(r11) ; all o.k. ? beql 51$ movl r9, DQF$L_PERMQUOTA(r11) ; set quota back up brb 70$ 51$: ret ; usage was o.k. 60$: bsbw check_over blbs r0, 70$ brw warning 70$: bsbw mod_permquota cmpl #1, r8 ; just give warning ? beql warning cmpl DQF$L_OVERDRAFT(r11), DQF$L_PERMQUOTA(r11) ; set down or up ? beql down bsbw print_up_msg ret down: bsbw print_down_msg ret warning: bsbw print_warning ret print_up_msg: movl #512, outlength $FAO_S - upline, - ; SET UP outlength, - outlinedesc, - P1=DQF$L_PERMQUOTA(r11) brb end_fao print_warning: pushaq readthis calls #1, g^lib$put_output movl #512, outlength $FAO_S - warnline, - ; GIVE WARNING outlength, - outlinedesc, - P1=DQF$L_OVERDRAFT(r11) brb end_fao print_down_msg: pushaq readthis calls #1, g^lib$put_output movl #512, outlength $fao_s - downline, - ; SET DOWN outlength, - outlinedesc, - P1=DQF$L_PERMQUOTA(r11) end_fao: blbc r0, 900$ pushab outlinedesc calls #1, g^lib$put_output blbc r0, 900$ rsb 900$: ret ; ; CONDITIONS: ; ; 1) If overdraft*2 is equal to permquota, then warning message has not ; started yet, thus - give warning, and set permquota to overdraft*2+bindate ; ; 2) If overdraft*2+bindate is equal to permquota then just give warning ; message for today and don't change anything ; ; 3) If neither of the above two apply, then this guy has been over quota for ; more than one day, thus screw him now... ; check_over: clrl r8 ; clear flags register ashl #1, DQF$L_OVERDRAFT(r11), r9 ; mult overdraft by 2 cmpl r9, DQF$L_PERMQUOTA(r11) ; CONDITION #1 ??? bneq 61$ ; nope... incl r8 ; set flag to 1 61$: addl2 bindate, r9 ; add on date cmpl r9, DQF$L_PERMQUOTA(r11) ; CONDITION #2 ??? bneq 62$ ; nope... clrl r0 rsb 62$: tstl r8 ; condition 1 set ? beql 64$ ; nope movl r9, DQF$L_PERMQUOTA(r11) ; set warn date brb 65$ 64$: movl DQF$L_OVERDRAFT(r11), DQF$L_PERMQUOTA(r11); set quota down movl #2, r8 65$: movl #1, r0 rsb .page scan_group: clrl fib$l_wcc(r10) movl #fib$m_all_mem, fib$l_cntrlval(r10) clrl group_usage movl dqf$l_overdraft(r11), group_overdraft movl dqf$l_permquota(r11), group_permquota 100$: $qiow_g acp_qio blbc r0, 110$ movzwl iosb, r0 blbs r0, 120$ 110$: cmpl r0, #ss$_nodiskquota beql 200$ ret 120$: addl dqf$l_usage(r11), group_usage brb 100$ 190$: ret 200$: $fao_s - group_hdr, - outlength, - outlinedesc, - p1 = dqf$l_uic+2(r11), - p2 = group_usage, - p3 = group_overdraft blbc r0, 190$ pushaq outlinedesc calls #1, g^lib$put_output blbc r0, 190$ ; Determine if quota file needs modification cmpl group_usage, group_overdraft bleq 300$ brw group_overquota 300$: mull3 #2, group_overdraft, r9 cmpl r9, group_permquota beql raise_member ; Group overdrawn flag was set - reset permquota movl r9, dqf$l_permquota(r11) movl r9, group_permquota clrw dqf$l_uic(r11) bsbw mod_permquota bsbw print_up_msg brb raise_member group_overquota: clrw dqf$l_uic(r11) movl group_overdraft, dqf$l_overdraft(r11) movl group_permquota, dqf$l_permquota(r11) bsbw check_over movl dqf$l_permquota(r11), group_permquota blbc r0, 100$ bsbw mod_permquota cmpl group_permquota, group_overdraft beql lower_member 100$: bsbw print_warning brb raise_member raise_member: movl group_overdraft, r7 brb change_member lower_member: bsbw print_down_msg clrl r7 change_member: ;+ ; Change the member's permanent quota to the value stored in R7 ;- movw #fib$c_exa_quota, fib$w_cntrlfunc(r10) clrl fib$l_cntrlval(r10) clrl fib$l_wcc(r10) movw member, dqf$l_uic(r11) $qiow_g acp_qio blbc r0, 900$ movzwl iosb, r0 blbc r0, 900$ $fao_s - ctrstr = member_use - outlen = outlength, - outbuf = outlinedesc, - p1 = group - p2 = member - p3 = dqf$l_usage(r11) pushaq outlength calls #1, g^lib$put_output tstl r7 bneq 300$ movl dqf$l_overdraft(r11), r7 300$: cmpl dqf$l_permquota(r11), r7 beql 400$ movl r7, dqf$l_permquota(r11) bsbw mod_permquota 400$: 900$: ret mod_permquota: clrl fib$l_wcc(r10) movw #fib$c_mod_quota, fib$w_cntrlfunc(r10) movl #fib$m_mod_perm, fib$l_cntrlval(r10) $qiow_g acp_qio blbc r0, 900$ movzwl iosb, r0 blbc r0, 900$ rsb 900$: ret .psect data, wrt acp_qio: $qiow ; Define parm list for qio group_usage: .blkl 1 group_overdraft: .blkl 1 group_permquota: .blkl 1 items: .word 4 .word JPI$_GRP .address group .address group_len .word 4 .word JPI$_MEM .address member .address member_len .long 0 group: .blkl 1 group_len: .blkl 1 member: .blkl 1 member_len: .blkl 1 group_hdr: .ascid "!_Disk usage for [!3OW,*] !UL used / !UL maximum" member_hdr: .ascid "!_Disk usage for [!OB,!OB] !UL used / !UL maximum" member_use: .ascid "!_Disk usage for [!3OW,!3OW] !UL used" outlinedesc: outlength: .long 512 .address outline outline: .blkb 512 time_buf: .blkw 7 bindate: .long 0 downline: .ascid "!_No files may be created until you reduce your usage to!/" - "!_less than !UL blocks. This strict quota enforcement!/" - "!_will remain in effect until you reduce your usage." upline: .ascid "!/!_Formerly imposed disk quotas have been lifted.!/" - "!_Please try to curb excessive space usage." TAB = ^x09 LF = ^x0a CR = ^x0d readthis: .ascid - "***** READ THIS *****" - "You have exceeded your maximum allowed disk usage." warnline:.ascid - "!_You have one day's grace period to reduce your usage to!/" - "!_less than !UL blocks. After this grace period,!/" - "!_quota enforcement will be instated until you reduce!/" - "!_your usage." fibdesc: .long FIB$C_LENGTH .address fibblk dqfdesc: .long DQF$C_LENGTH .address dqfblk drive: .ascid /SYS$DISK/ ; drive to check usage on channel: .blkw 1 iosb: .blkw 4 fibblk: .blkb FIB$C_LENGTH dqfblk: .blkb DQF$C_LENGTH dqfblklen: .address 1$ 1$: .blkw 1 .end DISKUSE