From: dongray@cdclu1.genrad.com (Derek Dongray)
Newsgroups: comp.os.vms
Subject: Re: Can I change quota entries from DCL or a program?
Date: 29 Jul 92 19:33:41 GMT
Distribution: world
Organization: The Internet

> Does anyone know of a EASY way to read and modify the entries in the QUOTA
> file?
>
> I'm trying to design an application which allows specific users to adjust
> quotas for other users. I'd like to be able to do this without writing SHOW
> QUOTA to a file and then parsing it and generating commands for SYSMAN to
> adjust the quota.
>
> I know that ALL-IN-1 somehow checks your quota - anyone know if it does
> anything fancy besides parsing the output of a SHOW QUOTA or SYSMAN command?
>
> --
> Bob Boag                                BITNET:   boag@marshall
> Senior Software Systems Analyst         Internet: boag@marshall.wvnet.edu
> Marshall University Computer Center     Phone:    (304)696-2624
> Huntington, WV 25755-5320               FAX:      (304)696-3601

In SYS$LIBRARY:LIB.MLB is a module $DQFDEF which gives the format records in
QUOTA.SYS. It's fairly easy then to write a program to examine/modify a disk
quota entry. See the disk quota ACP control functions in I/O User's Ref, Part
1. To examine other users' quota entries requires read access to the QUOTA.SYS.
To change a quota entry, the program must lock the volume (FIB$C_LOCK_VOL) and
unlock when doen (FIB$C_UNLK_VOL); to do this requires either SYSPRV or being
the volume owner.

Following my sig is a pascal program to list all disk quotas on the current
disk. Obviously, the requires read access to QUOTA.SYS.

--------------------------------------------------------------------------------
Name : Derek Dongray, Systems Manager, GenRad Ltd.
Phone : 061 486 1511 ext 166
PSS : 234261600119::Dongray                 UKnet : Derek.Dongray@GenRad.co.uk
InterNet : Dongray@cdclu1.GenRad.com        CompuServe : 70374,2745
Address : Monmouth House, Monmouth Road, Cheadle Hulme, Cheshire, SK8 7AY, UK.
--------------------------------------------------------------------------------
[inherit('sys$library:starlet')]

program examine_quota(output);

type

    byte_unsigned = [byte] 0..255;
    word_unsigned = [word] 0..65535;
    word_integer  = [word] -32768..32767;

    io_status_block	= record
	    case integer of
	1:     (condition	: [pos( 0)] word_unsigned;
		transfer_count	: [pos(16)] word_integer;
		terminator	: [pos(32)] word_integer;
		terminator_size : [pos(48)] word_integer);
	2:     (sys_condition	: [pos( 0)] integer;
		device_info	: [pos(32)] unsigned);
	3:     (status		: [pos( 0)] word_unsigned;
		offset_to_term	: [pos(16)] word_integer;
		terminator_char : [pos(32)] char;
		reserved_1	: [pos(40)] byte_unsigned;
		terminator_length : [pos(48)] byte_unsigned;
		cursor_pos_from_eol : [pos(56)] byte_unsigned);
	4:     (transmit_speed	: [pos(16)] byte_unsigned;
		receive_speed	: [pos(24)] byte_unsigned;
		cr_fill_count	: [pos(32)] byte_unsigned;
		lf_fill_count	: [pos(40)] byte_unsigned;
		parity_flags	: [pos(48)] byte_unsigned);
			end;

{ *** Module $DQFDEF *** }
const
    DQF$M_ACTIVE = 1;
    DQF$K_LENGTH = 32;
    DQF$C_LENGTH = 32;
    DQF$S_DQFDEF = 32;

type
    DQF$TYPE = record
            case integer of
        1:(
                DQF$L_FLAGS : [pos(0)] unsigned);
        2:(
                DQF$V_ACTIVE : [pos(0),bit] boolean;
                DQF$L_UIC : [pos(32)] unsigned;
                DQF$L_USAGE : [pos(64)] unsigned;
                DQF$L_PERMQUOTA : [pos(96)] unsigned;
                DQF$L_OVERDRAFT : [pos(128)] unsigned);
            end; {of record DQF$TYPE}

{End of Module $DQFDEF}

var
    qtfb : dqf$type;
    fib  : fib$type;
    qtfdsc, fibdsc : dsc1$type;
    iosb : io_status_block;
    chan, len : word_unsigned;
    stat : integer;
    nambuf : packed array [1..50] of char;
    uic : record case boolean of
       true: (l : unsigned);
       false: (m: word_unsigned; g:word_unsigned);
          end;

procedure lib$stop(code:integer); external;

begin
   stat := $assign('sys$disk:',chan);
   if not odd(stat) then lib$stop(stat);

   qtfb := zero;

   fib::fib1$type.fib$w_cntrlfunc := fib$c_exa_quota;
   fib::fib1$type.fib$l_cntrlval := 0;

{  +++
   to examine just one entry, set qtfb.dqf$l_uic to the required UIC and
   omit the following. }

   fib::fib1$type.fib$v_all_mem := true;
   fib::fib1$type.fib$v_all_grp := true;
   fib::fib$type.fib$l_wcc := 0;

{  --- }

   fibdsc := zero;
   fibdsc.dsc$w_maxstrlen := 64 {size (fib1$type)?};
   fibdsc.dsc$a_pointer::unsigned := iaddress(fib);

   qtfdsc := zero;
   qtfdsc.dsc$w_maxstrlen := 32 {size (dqf1$type)?};
   qtfdsc.dsc$a_pointer::unsigned := iaddress(qtfb);

   stat:= $qiow(chan:=chan,
		 func:=io$_acpcontrol,
	  	 iosb:=iosb,
		 p1:=%immed iaddress(fibdsc),
		 p2:=%immed iaddress(qtfdsc),
		 p3:=%immed iaddress(len),
	     	 p4:=%immed iaddress(qtfdsc));

   while odd(stat) and odd(iosb.condition) do
   begin
      if not odd($idtoasc(qtfb.dqf$l_uic,len,nambuf)) then
      begin
           uic.l := qtfb.dqf$l_uic::unsigned;
           nambuf := '['+oct(uic.g,6,6)+','+oct(uic.m,6,6)+']';
           len := 15;
      end;

      writeln('User :',substr(nambuf,1,len));
      writeln('Usage:',qtfb.dqf$l_usage);
      writeln('Quota:',qtfb.dqf$l_permquota);
      writeln('Overd:',qtfb.dqf$l_overdraft);

      stat:= $qiow(chan:=chan,
                    func:=io$_acpcontrol,
                    iosb:=iosb,
                    p1:=%immed iaddress(fibdsc),
                    p2:=%immed iaddress(qtfdsc),
                    p3:=%immed iaddress(len),
                    p4:=%immed iaddress(qtfdsc));

   end;

   $dassgn(chan);
end.

Newsgroups: comp.os.vms