From: moeller@gwdgv1.dnet.gwdg.de ("GWDGV1::MOELLER")
Newsgroups: comp.os.vms
Subject: IO$M_MOVEFILE example (VMS 5.5+)
Date: 31 Aug 92 12:24:39 GMT
Distribution: world
Organization: The Internet

I recently installed VMS 5.5-1 on a test machine, and had to try out
the new MOVEFILE function. Below is MOVEF1.C, a program to defragment
a single file using this rather powerful XQP primitive.
In order to compile MOVEF1.C, you'll need FIBDEF.H, to be created by
the .MLB => .H utility posted here several times (Below I'll include
a stub for those who didn't care to save that utility).
The FIBDEF.H which comes with VAXC will *not* work.

Some observations:
(a) IO$M_MOVEFILE requires a large amount of *paged* pool, i.e.
    normally a contigous chunk of 65k bytes, plus a lot of small
    packets.
(b) The documentation allows you to specify a RVN (in order to
    "place" the moved file within a volume set), but also warns
    that moving across volumes is not supported. The program
    allows you to specify that RVN, but I guess it has no purpose
    (I didn't test the program with a volume set yet).
(c) The program below uses RMS to $OPEN the file prior to moving it.
    This has the side effect of possibly updating the expiration date.
    That't a bug ($SEARCH would have been more appropriate, I guess).

Warning: Running this program on many files of a fragmented disk will
normally *increase* the fragmentation of free space.

Wolfgang J. Moeller, GWDG, D-3400 Goettingen, F.R.Germany | Disclaimer ...
PSI%(0262)45050352008::MOELLER      Phone: +49 551 201516 | No claim intended!
Internet: moeller@gwdgv1.dnet.gwdg.de   | This space intentionally left blank.

--- FIBDEF.H stub (use only if you can't do better) ---
#define	FIB$L_ACCTL	0
#define	FIB$W_FID	4
#define	FIB$W_DID	10
#define	FIB$W_EXCTL	22
#define	FIB$B_ALOPTS	32
#define	FIB$B_ALALIGN	33
#define	FIB$W_LOC_FID	34
#define	FIB$L_LOC_ADDR	40
#define	FIB$L_MOV_SVBN	64
#define	FIB$L_MOV_VBNCNT	68
#define	FIB$C_LENGTH	72
#define	FIB$M_NOPLACE	16384
#define	FIB$M_ALCON	1
#define	FIB$M_EXACT	1
#define	FIB$C_LBN	2
--- end of FIBDEF.H stub ---

$! ................... Cut between dotted lines and save. ...................
$!...........................................................................
$! VAX/VMS archive file created by VMS_SHARE V06.10 7-FEB-1989.
$!
$! VMS_SHARE was written by James Gray (Gray:OSBUSouth@Xerox.COM) from
$! VMS_SHAR by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au).
$!
$! To unpack, simply save, concatinate all parts into one file and
$! execute (@) that file.
$!
$! This archive was created by user MOELLER
$! on 31-AUG-1992 13:52:32.61.
$!
$! It contains the following 1 file:
$!        MOVEF1.C
$!
$!============================================================================
$ SET SYMBOL/SCOPE=( NOLOCAL, NOGLOBAL )
$ VERSION = F$GETSYI( "VERSION" )
$ IF VERSION .GES "V4.4" THEN GOTO VERSION_OK
$ WRITE SYS$OUTPUT "You are running VMS ''VERSION'; ", -
    "VMS_SHARE V06.10 7-FEB-1989 requires VMS V4.4 or higher."
$ EXIT 44 ! SS$_ABORT
$VERSION_OK:
$ GOTO START
$!
$UNPACK_FILE:
$ WRITE SYS$OUTPUT "Creating ''FILE_IS'"
$ DEFINE/USER_MODE SYS$OUTPUT NL:
$ EDIT/TPU/COMMAND=SYS$INPUT/NODISPLAY/OUTPUT='FILE_IS'/NOSECTION -
    VMS_SHARE_DUMMY.DUMMY
b_part := CREATE_BUFFER( "{Part}", GET_INFO( COMMAND_LINE, "file_name" ) )
; s_file_spec := GET_INFO( COMMAND_LINE, "output_file" ); SET( OUTPUT_FILE
, b_part, s_file_spec ); b_errors := CREATE_BUFFER( "{Errors}" ); i_errors
:= 0; pat_beg_1 := ANCHOR & "-+-+-+ Beginning"; pat_beg_2 := LINE_BEGIN
& "+-+-+-+ Beginning"; pat_end := ANCHOR & "+-+-+-+-+ End"; POSITION
( BEGINNING_OF( b_part ) ); LOOP EXITIF SEARCH( SPAN( ' ' )@r_trail
& LINE_END, FORWARD) = 0; POSITION( r_trail ); ERASE( r_trail ); ENDLOOP
; POSITION( BEGINNING_OF( b_part ) ); i_append_line := 0; LOOP EXITIF MARK
( NONE ) = END_OF( b_part ); s_x := ERASE_CHARACTER( 1 )
; IF s_x = '+' THEN r_skip := SEARCH( pat_beg_1, FORWARD, EXACT ); IF r_skip
<> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ERASE_LINE; ENDIF
; ENDIF; IF s_x = '-' THEN r_skip := SEARCH( pat_end, FORWARD, EXACT )
; IF r_skip <> 0 THEN s_x := ''; MOVE_HORIZONTAL( -CURRENT_OFFSET ); m_skip
:= MARK( NONE ); r_skip := SEARCH( pat_beg_2, FORWARD, EXACT ); IF r_skip
<> 0 THEN POSITION( END_OF( r_skip ) ); MOVE_HORIZONTAL( -CURRENT_OFFSET )
; MOVE_VERTICAL( 1 ); MOVE_HORIZONTAL( -1 ); ELSE POSITION( END_OF( b_part )
); ENDIF; ERASE( CREATE_RANGE( m_skip, MARK( NONE ), NONE ) ); ENDIF; ENDIF
; IF s_x = 'V' THEN s_x := ''; IF i_append_line <> 0 THEN APPEND_LINE
; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF; i_append_line := 1
; MOVE_VERTICAL( 1 ); ENDIF; IF s_x = 'X' THEN s_x := ''; IF i_append_line
<> 0 THEN APPEND_LINE; MOVE_HORIZONTAL( -CURRENT_OFFSET ); ENDIF
; i_append_line := 0; MOVE_VERTICAL( 1 ); ENDIF; IF s_x <> '' THEN i_errors
:= i_errors + 1; s_text := CURRENT_LINE; POSITION( b_errors ); COPY_TEXT
( "The following line could not be unpacked properly:" ); SPLIT_LINE
; COPY_TEXT( s_x ); COPY_TEXT( s_text ); POSITION( b_part ); MOVE_VERTICAL
( 1 ); ENDIF; ENDLOOP; POSITION( BEGINNING_OF( b_part ) ); LOOP r_x := SEARCH
( "`", FORWARD, EXACT ); EXITIF r_x = 0; POSITION( r_x ); ERASE_CHARACTER( 1
); COPY_TEXT( ASCII( INT( ERASE_CHARACTER( 3 ) ) ) ); ENDLOOP
; IF i_errors = 0 THEN SET( NO_WRITE, b_errors, ON ); ELSE POSITION
( BEGINNING_OF( b_errors ) ); COPY_TEXT( FAO
( "The following !UL errors were detected while unpacking !AS", i_errors
, s_file_spec ) ); SPLIT_LINE; SET( OUTPUT_FILE, b_errors, "SYS$COMMAND" )
; ENDIF; EXIT;
$ DELETE VMS_SHARE_DUMMY.DUMMY;*
$ CHECKSUM 'FILE_IS
$ WRITE SYS$OUTPUT " CHECKSUM ", -
  F$ELEMENT( CHECKSUM_IS .EQ. CHECKSUM$CHECKSUM, ",", "failed!!,passed." )
$ RETURN
$!
$START:
$ FILE_IS = "MOVEF1.C"
$ CHECKSUM_IS = 405089925
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X/* MOVE file [arg1] contiguously `123to block [arg2] bzw. [arg2,rvn2]`125 */
X
X#include stdlib
X#include stddef
X#include string
X#include stdio
X#include assert
X
X#include fab
X#include nam
X
X#include descrip
Xtypedef struct dsc$descriptor DESCR;
X
Xtypedef`009struct Fid `123
X`009unsigned short num;
X`009unsigned short seq;
X`009unsigned char rvn;
X`009unsigned char nmx;
X`125 FID;
X
X#include "fibdef"
Xtypedef struct Fib `123`009/* stub, only what's needed */
X`009/* unsigned char fill0[FIB$L_ACCTL]; */
X`009unsigned int acctl;
X`009/* unsigned char fill1[FIB$W_FID - FIB$L_ACCTL - sizeof(int)]; */
X`009FID fid;
X`009FID did;
X`009unsigned char fill2[FIB$W_EXCTL - FIB$W_DID - sizeof(FID)];
X`009unsigned short exctl;
X`009unsigned char fill3[FIB$B_ALOPTS - FIB$W_EXCTL - sizeof(short)];
X`009unsigned char alopts;
X`009/* unsigned char fill4[FIB$B_ALALIGN - FIB$B_ALOPTS - sizeof(char)]; */
X`009unsigned char alalign;
X`009/* unsigned char fill5[FIB$W_LOC_FID - FIB$B_ALALIGN - sizeof(char)]; */
X`009FID loc_fid;
X`009/* unsigned char fill6[FIB$L_LOC_ADDR - FIB$W_LOC_FID - sizeof(FID)]; */
X`009unsigned int loc_addr;
X`009unsigned char fill7[FIB$L_MOV_SVBN - FIB$L_LOC_ADDR - sizeof(int)];
X`009unsigned int mov_svbn;
V`009/* unsigned char fill8[FIB$L_MOV_VBNCNT - FIB$L_MOV_SVBN - sizeof(int)];
X */
X`009unsigned int mov_vbncnt;
X`009/* unsigned char fill9[FIB$C_LENGTH - FIB$L_MOV_VBNCNT - sizeof(int)]; */
X`125 FIB;
X
Xextern void lib$stop();
Xextern unsigned sys$qiow();
Xextern unsigned sys$open();
X
X`009`009`009`009/* IODEF.H doesn't have MOVEFILE yet */
Xglobalvalue IO$_DEACCESS,IO$_MODIFY,IO$M_MOVEFILE;
X
X#ifndef NULL
X#define NULL ((void *) 0)
X#endif
X
X#define CHECKV(k) if((k&1) == 0) lib$stop(k)
X#define CHECK(k) `123unsigned status = k; CHECKV(status);`125
X#define ZERO1(arr,len) memset(arr,0,(len))
X
X/*****/
X
Xmain(argc,argv)
Xint argc; char **argv;
X`123
X`009static struct NAM rmsnam;
X`009static struct FAB rmsfab;
X`009static char rsfile[NAM$C_MAXRSS],exfile[NAM$C_MAXRSS];
X`009static FIB fib;
X`009DESCR fibdsc = `123sizeof(fib),0,0,&fib`125;
X`009unsigned short chan,iosb[4];
X`009int arg2c,arg2n1,arg2n2;
X
X
X`009assert(FIB$L_ACCTL == 0);
X`009assert(FIB$W_FID - FIB$L_ACCTL - sizeof(int) == 0);
X`009assert(FIB$B_ALALIGN - FIB$B_ALOPTS - sizeof(char) == 0);
X`009assert(FIB$W_LOC_FID - FIB$B_ALALIGN - sizeof(char) == 0);
X`009assert(FIB$L_LOC_ADDR - FIB$W_LOC_FID - sizeof(FID) == 0);
X`009assert(FIB$L_MOV_VBNCNT - FIB$L_MOV_SVBN - sizeof(int) == 0);
X`009assert(FIB$C_LENGTH - FIB$L_MOV_VBNCNT - sizeof(int) == 0);
X
X
X`009if(argc < 2) `123
X`009`009printf("Usage: MOVEF1 file [lbn[,rvn]]\n");
X`009`009exit(2);
X`009`125
X`009if(argc < 3) `123
X`009`009arg2c = 0;
X`009`125 else `123
X`009`009arg2c = sscanf(argv[2],"%d,%d",&arg2n1,&arg2n2);
X`009`009if(arg2c != 1 && arg2c != 2) `123
X`009`009`009printf("bad arg2\n");
X`009`009`009exit(2);
X`009`009`125
X`009`125
X
X`009rmsnam = cc$rms_nam;
X`009rmsnam.nam$l_esa = exfile;
X`009rmsnam.nam$b_ess = sizeof(exfile);
X`009rmsnam.nam$l_rsa = rsfile;
X`009rmsnam.nam$b_rss = sizeof(rsfile);
X`009rmsfab = cc$rms_fab;
X`009rmsfab.fab$l_nam = &rmsnam;
X`009rmsfab.fab$l_fna = argv[1];
X`009rmsfab.fab$b_fns = strlen(argv[1]);
X`009rmsfab.fab$l_fop = FAB$M_UFO;
X
X`009CHECK(sys$open(&rmsfab));
X
X`009chan = rmsfab.fab$l_stv;
X
X`009ZERO1(&fib,sizeof(fib));
X
X`009CHECK(sys$qiow(0,chan,IO$_DEACCESS,`009`009/* "close" */
X`009`009`009       &iosb,0,0,
X`009`009`009       &fibdsc,0,0,0,0,0));
X`009CHECK(iosb[0]);
X
X
X`009printf("Moving file %.*s",rmsnam.nam$b_rsl,rsfile);
X
X`009ZERO1(&fib,sizeof(fib));
X`009lib$movc3(&sizeof(FID),&(rmsnam.nam$w_fid[0]),&fib.fid);
X
X`009fib.exctl = FIB$M_ALCON `124 FIB$M_NOPLACE;
X
X`009if(arg2c >= 1) `123
X`009`009fib.alopts = FIB$M_EXACT;
X`009`009fib.alalign = FIB$C_LBN;
X`009`009if(arg2c >= 2) `123
X`009`009`009fib.loc_fid.rvn = arg2n2;
X`009`009`125 else `123
X`009`009`009fib.loc_fid.rvn = fib.fid.rvn;
X`009`009`125
X`009`009fib.loc_addr = arg2n1;
X
X`009`009printf(" => LBN %d, RVN %d\n",
X`009`009`009fib.loc_addr,fib.loc_fid.rvn);
X`009`125
X
X`009fib.mov_svbn = 1;
X`009fib.mov_vbncnt = 0;
X
X`009printf("\n");
X
X`009CHECK(sys$qiow(0,chan,IO$_MODIFY `124 IO$M_MOVEFILE,
X`009`009`009       &iosb,0,0,
X`009`009`009       &fibdsc,0,0,0,0,0));
X`009CHECK(iosb[0]);
X`125
$ GOSUB UNPACK_FILE
$ EXIT

Wolfgang J. Moeller, GWDG, D-3400 Goettingen, F.R.Germany | Disclaimer ...
PSI%(0262)45050352008::MOELLER      Phone: +49 551 201516 | No claim intended!
Internet: moeller@gwdgv1.dnet.gwdg.de   | This space intentionally left blank.

Newsgroups: comp.os.vms