mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-28 17:20:29 +00:00
Upgrade to version 1.3 = Hunter Goatley
This version was on the VMS FREEWARE disk at some point. It shipped with the included .exes, though modern windows systems certainly don't support the direct access to SCSI DLL that's used.
This commit is contained in:
22
extracters/ods2/aareadme.too
Normal file
22
extracters/ods2/aareadme.too
Normal file
@@ -0,0 +1,22 @@
|
||||
ODS2 V1.3, 26-SEP-2001
|
||||
|
||||
This release of ODS2 has been made by me, working closely with, and
|
||||
getting approval from, Paul.
|
||||
|
||||
It will compile cleanly on OpenVMS Alpha, Windows NT/2000 using
|
||||
Visual C++ V6.0, Tru64 UNIX V5, and Solaris/Sparc using gcc.
|
||||
|
||||
To build on Windows 2000:
|
||||
|
||||
C:> nmake -f makefile.nt
|
||||
|
||||
To build on VMS:
|
||||
|
||||
$ mmk
|
||||
|
||||
|
||||
Hunter
|
||||
------
|
||||
Hunter Goatley
|
||||
goathunter@goatley.com
|
||||
http://www.goatley.com/hunter/
|
||||
175
extracters/ods2/aareadme.txt
Normal file
175
extracters/ods2/aareadme.txt
Normal file
@@ -0,0 +1,175 @@
|
||||
ODS2 June '98
|
||||
|
||||
A Program to Read ODS2 Disk Volumes
|
||||
|
||||
|
||||
Say, what is this?
|
||||
ODS2 is a program to read VMS disk volumes written in VMS
|
||||
ODS2 format.
|
||||
|
||||
Why bother?
|
||||
Well sometimes it is convenient to see what is on a VMS CD,
|
||||
or copy files from VMS disk on another platform. Maybe in
|
||||
future it could be used as a basis for a PC Bookreader
|
||||
program, or possibly other software?
|
||||
|
||||
What other platforms?
|
||||
ODS2 is written in 'Standard C' with the intent that it can
|
||||
be compiled and run on non-VMS systems. However this requires
|
||||
a C compiler which has 32 bit 'int' types, 16 bit 'short'
|
||||
types, and 8 bit 'char'. The current version does no special
|
||||
'endian' handling so it can only be run on systems which are
|
||||
little-endian like the VAX. Fortunately that inludes Intel...
|
||||
|
||||
Could it be made to run on big-endian systems?
|
||||
Yes it could! This would probably best be done by defining
|
||||
C macros or functions to extract words or long words from the
|
||||
disk structures as appropriate. On a little-endian system these
|
||||
would be simply pass-through, while on a big-endian system they
|
||||
would reverse the byte order. I have not attempted this because
|
||||
I don't have a suitable test system!!
|
||||
|
||||
What else is needed?
|
||||
Some operating system support is also required to read an
|
||||
absolute disk sector from the target disk. This is NOT as
|
||||
easy as it sounds. I do not currently have sufficient
|
||||
documentation to set this up for as many platforms as I
|
||||
would like!! However I do have modules to read disks under
|
||||
VMS (easy!) and floppies and CD under OS2, Windows 95 and
|
||||
Windows NT.
|
||||
|
||||
How do I build it?
|
||||
On a VMS system ODS2 can be compiled by executing the
|
||||
procedure BUILD.COM. On other platforms you need to compile
|
||||
Ods2.c, Rms.c, Direct.c, Access.c, Device.c, Cache.c, Vmstime.c,
|
||||
and the appropriate Phy*.c routine for your system. On OS/2 I
|
||||
compile using the gcc command:-
|
||||
gcc -fdollars-in-identifiers ods2.c,rms.c,direct.c,
|
||||
access.c,device.c,cache.c,phyos2.c,vmstime.c
|
||||
|
||||
What can it do?
|
||||
Basically ODS2 provides cut down DIRECTORY, COPY and
|
||||
SEARCH commands for VMS volumes on non-VMS systems. These
|
||||
can be used to find out what is on a VMS volume, and copy
|
||||
files onto the local file sytem.
|
||||
|
||||
What file types?
|
||||
Basically ODS2 can only deal with sequential files. I do not
|
||||
have information on how indexed file types are constructed,
|
||||
and relative files are of limited interest.
|
||||
|
||||
What about volume sets?
|
||||
ODS2 does contain support for multi-volume sets. However there
|
||||
is no checking that the correct volumes have been specified and
|
||||
error handling is very fragile. You should ensure that you
|
||||
specify volume set mount commands very carefully!
|
||||
|
||||
What about ODS5?
|
||||
Sorry, but I have no idea! I have not seen any ODS5 information
|
||||
or specifications. Most likely this program will fall in a heap
|
||||
when presented with an ODS5 disk volume.
|
||||
|
||||
What about bugs?
|
||||
There are plenty!! This code has been tested for several hours
|
||||
by a single developer/user on one workstation (absolutely no
|
||||
testing or input from any other person up to this point!).
|
||||
Contrast this to the VMS filesystem which has had hundreds of
|
||||
developers, millions of users, and has run on about 500,000
|
||||
systems over the last 20 years!! I would hope to fix some of
|
||||
the more severe limitations and provide better error handling
|
||||
fairly soon, perhaps even put some comments into the code?
|
||||
Maybe the next release might have fewer bugs?
|
||||
|
||||
It is free?
|
||||
Yeap! It is provided 'as is' to help people in the VMS
|
||||
community. However there is NO SUPPORT! I will try to fix
|
||||
any reported problems, but as I really only get to work on
|
||||
it while the kids are at Scouts on Monday nights, fixes
|
||||
happen slowly! But if you have comments or suggestions then
|
||||
please feel free to mail me!
|
||||
|
||||
Can I use the code?
|
||||
Yeap! You can use and modify the code provided that you
|
||||
acknowledge the author in the source of any modules which use
|
||||
any part of this code. I would also appreciate, where possible,
|
||||
being sent any enhancements for my own use.
|
||||
|
||||
Can I call the routines from my program?
|
||||
You should be able to. Many of the modules follow an 'RMS'
|
||||
sort of standard, and programs which only ever read RMS files
|
||||
from C might be converted to read VMS volumes on another platform
|
||||
without too much effort. In addition to the RMSish interface,
|
||||
it would not be difficult to package up an $ASSIGN/$QIOW interface
|
||||
for common file operations...
|
||||
|
||||
What is the status of ODS2?
|
||||
This is the first release - actually more like a prototype
|
||||
than an real release! But it may generate useful feedback and
|
||||
possibly be useful to others the way it is? However if you are
|
||||
tempted to use this version for real file transfers, DO YOUR OWN
|
||||
TESTING first! This program may not have encountered volumes and
|
||||
files like yours and could easily generate garbage results!!!
|
||||
|
||||
Is more work happening?
|
||||
Yes! I find the program very useful moving stuff from my
|
||||
VAXstation to my PC. I would like to be able to write ODS2 volumes
|
||||
so that I can move files in the other direction! And yes I hope
|
||||
to generally improve the code - particularly in the area of error
|
||||
handling!
|
||||
|
||||
Can I make a suggestion?
|
||||
You sure can! If you see something which needs improvement then
|
||||
let me know. It may be more interesting than whatever I am doing now!
|
||||
In fact if I don't hear from anyone then I might even loose interest!
|
||||
|
||||
Can I see a command sample?
|
||||
Sure:-
|
||||
C:> ODS2
|
||||
ODS2 v1.2
|
||||
$> mount E:,F:
|
||||
%MOUNT-I-MOUNTED, Volume FOX1 mounted on E:
|
||||
%MOUNT-I-MOUNTED, Volume FOX2 mounted on F:
|
||||
$> direct/file E:[*...]
|
||||
Directory E:[PNANKERVIS]
|
||||
3MONTH.LOWUSE;1 (51,20,2)
|
||||
ACCTEST.COM;1 (137,4,1)
|
||||
ACCTEST.EXE;1 (53,4,2)
|
||||
.....
|
||||
$> set default E:[sys0.sysmgr]
|
||||
$> dir [-.sys*...].%
|
||||
.....
|
||||
$> copy *.c *.*
|
||||
%COPY-S-COPIED, E:[SYS0.SYSMGR]ACCESS.C;1 copied to ACCESS.C (3 records)
|
||||
....
|
||||
$> show time
|
||||
24-MAR-1998 20:15:23.5
|
||||
$> dismount E:
|
||||
$> exit
|
||||
|
||||
What commands are supported?
|
||||
A summary is:-
|
||||
mount DRIVE:[,DRIVE:...]
|
||||
directory [/file|/size|/date] [FILE-SPEC]
|
||||
copy FILE-SPEC OUTPUT-FILE
|
||||
dismount DRIVE:
|
||||
search FILE-SPEC STRING
|
||||
set default DIR-SPEC
|
||||
show default
|
||||
show time
|
||||
exit
|
||||
Note - DRIVE: is normally the native system drive name,
|
||||
for example D: might be a CD on a PC - xxx: might be
|
||||
/dev/xxx on a Unix system.
|
||||
- when a list of drives is specified on the mount command
|
||||
they are assumed to contain a single valid volume set
|
||||
(this is not validated!!)
|
||||
- file-spec is in the usual VMS syntax and may contain
|
||||
wildcards (for example A:[-.*obj%%...]*abc*.obj;-2)
|
||||
|
||||
Who would write this?
|
||||
Me! Maybe it will become the basis of something more? If you
|
||||
have suggestions or want to know more then please mail me at
|
||||
paulnank@au1.ibm.com
|
||||
|
||||
Thanks for listening!
|
||||
Paul Nankervis
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* Access.h v1.2 Definitions for file access routines */
|
||||
/* Access.h v1.3 Definitions for file access routines */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -10,11 +10,24 @@
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
|
||||
#define NO_DOLLAR
|
||||
#include "cache.h"
|
||||
#include "vmstime.h"
|
||||
|
||||
#define swapw(w) ((((unsigned int)(w[0]))<<16) | (unsigned int)(w[1]))
|
||||
#ifdef BIG_ENDIAN
|
||||
#define VMSLONG(l) ((l & 0xff) << 24 | (l & 0xff00) << 8 | (l & 0xff0000) >> 8 | l >> 24)
|
||||
#define VMSWORD(w) ((w & 0xff) << 8 | w >> 8)
|
||||
#define VMSSWAP(l) ((l & 0xff0000) << 8 | (l & 0xff000000) >> 8 |(l & 0xff) << 8 | (l & 0xff00) >> 8)
|
||||
#else
|
||||
#define VMSLONG(l) l
|
||||
#define VMSWORD(w) w
|
||||
#define VMSSWAP(l) ((l & 0xffff) << 16 | l >> 16)
|
||||
#endif
|
||||
|
||||
typedef unsigned char vmsbyte;
|
||||
typedef unsigned short vmsword;
|
||||
typedef unsigned int vmsswap;
|
||||
typedef unsigned int vmslong;
|
||||
|
||||
#define FH2$M_NOBACKUP 0x2
|
||||
#define FH2$M_CONTIG 0x80
|
||||
@@ -22,140 +35,159 @@
|
||||
#define FH2$M_MARKDEL 0x8000
|
||||
#define FH2$M_ERASE 0x20000
|
||||
|
||||
typedef unsigned char u_byte;
|
||||
typedef unsigned short u_word;
|
||||
typedef unsigned int u_long;
|
||||
|
||||
#ifdef __ALPHA
|
||||
#pragma member_alignment save
|
||||
#pragma nomember_alignment
|
||||
#endif
|
||||
|
||||
struct UIC {
|
||||
u_word u_grp;
|
||||
u_word u_mem;
|
||||
vmsword uic$w_mem;
|
||||
vmsword uic$w_grp;
|
||||
};
|
||||
|
||||
|
||||
struct fiddef {
|
||||
u_word fid$w_num;
|
||||
u_word fid$w_seq;
|
||||
u_byte fid$b_rvn;
|
||||
u_byte fid$b_nmx;
|
||||
vmsword fid$w_num;
|
||||
vmsword fid$w_seq;
|
||||
vmsbyte fid$b_rvn;
|
||||
vmsbyte fid$b_nmx;
|
||||
};
|
||||
|
||||
|
||||
struct RECATTR {
|
||||
u_byte fat$b_rtype;
|
||||
u_byte fat$b_rattrib;
|
||||
u_word fat$w_rsize;
|
||||
u_word fat$l_hiblk[2];
|
||||
u_word fat$l_efblk[2];
|
||||
u_word fat$w_ffbyte;
|
||||
u_byte fat$b_bktsize;
|
||||
u_byte fat$b_vfcsize;
|
||||
u_word fat$w_maxrec;
|
||||
u_word fat$w_defext;
|
||||
u_word fat$w_gbc;
|
||||
u_byte fat$_UU0[8];
|
||||
u_word fat$w_versions;
|
||||
vmsbyte fat$b_rtype;
|
||||
vmsbyte fat$b_rattrib;
|
||||
vmsword fat$w_rsize;
|
||||
vmsswap fat$l_hiblk;
|
||||
vmsswap fat$l_efblk;
|
||||
vmsword fat$w_ffbyte;
|
||||
vmsbyte fat$b_bktsize;
|
||||
vmsbyte fat$b_vfcsize;
|
||||
vmsword fat$w_maxrec;
|
||||
vmsword fat$w_defext;
|
||||
vmsword fat$w_gbc;
|
||||
vmsbyte fat$_UU0[8];
|
||||
vmsword fat$w_versions;
|
||||
};
|
||||
|
||||
|
||||
struct HOME {
|
||||
u_long hm2$l_homelbn;
|
||||
u_long hm2$l_alhomelbn;
|
||||
u_long hm2$l_altidxlbn;
|
||||
u_word hm2$w_struclev;
|
||||
u_word hm2$w_cluster;
|
||||
u_word hm2$w_homevbn;
|
||||
u_word hm2$w_alhomevbn;
|
||||
u_word hm2$w_altidxvbn;
|
||||
u_word hm2$w_ibmapvbn;
|
||||
u_long hm2$l_ibmaplbn;
|
||||
u_long hm2$l_maxfiles;
|
||||
u_word hm2$w_ibmapsize;
|
||||
u_word hm2$w_resfiles;
|
||||
u_word hm2$w_devtype;
|
||||
u_word hm2$w_rvn;
|
||||
u_word hm2$w_setcount;
|
||||
u_word hm2$w_volchar;
|
||||
vmslong hm2$l_homelbn;
|
||||
vmslong hm2$l_alhomelbn;
|
||||
vmslong hm2$l_altidxlbn;
|
||||
vmsword hm2$w_struclev;
|
||||
vmsword hm2$w_cluster;
|
||||
vmsword hm2$w_homevbn;
|
||||
vmsword hm2$w_alhomevbn;
|
||||
vmsword hm2$w_altidxvbn;
|
||||
vmsword hm2$w_ibmapvbn;
|
||||
vmslong hm2$l_ibmaplbn;
|
||||
vmslong hm2$l_maxfiles;
|
||||
vmsword hm2$w_ibmapsize;
|
||||
vmsword hm2$w_resfiles;
|
||||
vmsword hm2$w_devtype;
|
||||
vmsword hm2$w_rvn;
|
||||
vmsword hm2$w_setcount;
|
||||
vmsword hm2$w_volchar;
|
||||
struct UIC hm2$w_volowner;
|
||||
u_long hm2$l_reserved1;
|
||||
u_word hm2$w_protect;
|
||||
u_word hm2$w_fileprot;
|
||||
u_word hm2$w_reserved2;
|
||||
u_word hm2$w_checksum1;
|
||||
struct TIME hm2$q_credate;
|
||||
u_byte hm2$b_window;
|
||||
u_byte hm2$b_lru_lim;
|
||||
u_word hm2$w_extend;
|
||||
struct TIME hm2$q_retainmin;
|
||||
struct TIME hm2$q_retainmax;
|
||||
struct TIME hm2$q_revdate;
|
||||
u_byte hm2$r_min_class[20];
|
||||
u_byte hm2$r_max_class[20];
|
||||
u_byte hm2$t_reserved3[320];
|
||||
u_long hm2$l_serialnum;
|
||||
vmslong hm2$l_reserved1;
|
||||
vmsword hm2$w_protect;
|
||||
vmsword hm2$w_fileprot;
|
||||
vmsword hm2$w_reserved2;
|
||||
vmsword hm2$w_checksum1;
|
||||
VMSTIME hm2$q_credate;
|
||||
vmsbyte hm2$b_window;
|
||||
vmsbyte hm2$b_lru_lim;
|
||||
vmsword hm2$w_extend;
|
||||
VMSTIME hm2$q_retainmin;
|
||||
VMSTIME hm2$q_retainmax;
|
||||
VMSTIME hm2$q_revdate;
|
||||
vmsbyte hm2$r_min_class[20];
|
||||
vmsbyte hm2$r_max_class[20];
|
||||
vmsbyte hm2$t_reserved3[320];
|
||||
vmslong hm2$l_serialnum;
|
||||
char hm2$t_strucname[12];
|
||||
char hm2$t_volname[12];
|
||||
char hm2$t_ownername[12];
|
||||
char hm2$t_format[12];
|
||||
u_word hm2$w_reserved4;
|
||||
u_word hm2$w_checksum2;
|
||||
vmsword hm2$w_reserved4;
|
||||
vmsword hm2$w_checksum2;
|
||||
};
|
||||
|
||||
|
||||
struct IDENT {
|
||||
char fi2$t_filename[20];
|
||||
u_word fi2$w_revision;
|
||||
struct TIME fi2$q_credate;
|
||||
struct TIME fi2$q_revdate;
|
||||
struct TIME fi2$q_expdate;
|
||||
struct TIME fi2$q_bakdate;
|
||||
vmsword fi2$w_revision;
|
||||
VMSTIME fi2$q_credate;
|
||||
VMSTIME fi2$q_revdate;
|
||||
VMSTIME fi2$q_expdate;
|
||||
VMSTIME fi2$q_bakdate;
|
||||
char fi2$t_filenamext[66];
|
||||
};
|
||||
|
||||
|
||||
struct HEAD {
|
||||
u_byte fh2$b_idoffset;
|
||||
u_byte fh2$b_mpoffset;
|
||||
u_byte fh2$b_acoffset;
|
||||
u_byte fh2$b_rsoffset;
|
||||
u_word fh2$w_seg_num;
|
||||
u_word fh2$w_struclev;
|
||||
vmsbyte fh2$b_idoffset;
|
||||
vmsbyte fh2$b_mpoffset;
|
||||
vmsbyte fh2$b_acoffset;
|
||||
vmsbyte fh2$b_rsoffset;
|
||||
vmsword fh2$w_seg_num;
|
||||
vmsword fh2$w_struclev;
|
||||
struct fiddef fh2$w_fid;
|
||||
struct fiddef fh2$w_ext_fid;
|
||||
struct RECATTR fh2$w_recattr;
|
||||
u_long fh2$l_filechar;
|
||||
u_word fh2$w_reserved1;
|
||||
u_byte fh2$b_map_inuse;
|
||||
u_byte fh2$b_acc_mode;
|
||||
vmslong fh2$l_filechar;
|
||||
vmsword fh2$w_reserved1;
|
||||
vmsbyte fh2$b_map_inuse;
|
||||
vmsbyte fh2$b_acc_mode;
|
||||
struct UIC fh2$l_fileowner;
|
||||
u_word fh2$w_fileprot;
|
||||
vmsword fh2$w_fileprot;
|
||||
struct fiddef fh2$w_backlink;
|
||||
u_byte fh2$b_journal;
|
||||
u_byte fh2$b_ru_active;
|
||||
u_word fh2$w_reserved2;
|
||||
u_long fh2$l_highwater;
|
||||
u_byte fh2$b_reserved3[8];
|
||||
u_byte fh2$r_class_prot[20];
|
||||
u_byte fh2$r_restofit[402];
|
||||
u_word fh2$w_checksum;
|
||||
vmsbyte fh2$b_journal;
|
||||
vmsbyte fh2$b_ru_active;
|
||||
vmsword fh2$w_reserved2;
|
||||
vmslong fh2$l_highwater;
|
||||
vmsbyte fh2$b_reserved3[8];
|
||||
vmsbyte fh2$r_class_prot[20];
|
||||
vmsbyte fh2$r_restofit[402];
|
||||
vmsword fh2$w_checksum;
|
||||
};
|
||||
|
||||
struct SCB {
|
||||
vmsword scb$w_struclev;
|
||||
vmsword scb$w_cluster;
|
||||
vmslong scb$l_volsize;
|
||||
vmslong scb$l_blksize;
|
||||
vmslong scb$l_sectors;
|
||||
vmslong scb$l_tracks;
|
||||
vmslong scb$l_cylinders;
|
||||
vmslong scb$l_status;
|
||||
vmslong scb$l_status2;
|
||||
vmsword scb$w_writecnt;
|
||||
char scb$t_volockname[12];
|
||||
VMSTIME scb$q_mounttime;
|
||||
vmsword scb$w_backrev;
|
||||
vmslong scb$q_genernum[2];
|
||||
char scb$b_reserved[446];
|
||||
vmsword scb$w_checksum;
|
||||
};
|
||||
|
||||
struct EXT {
|
||||
unsigned phylen;
|
||||
unsigned phyblk;
|
||||
}; /* Physical extent entry */
|
||||
|
||||
#ifdef __ALPHA
|
||||
#pragma member_alignment restore
|
||||
#endif
|
||||
|
||||
#define EXTMAX 20
|
||||
|
||||
struct WCB {
|
||||
struct CACHE cache;
|
||||
unsigned loblk,hiblk; /* Range of window */
|
||||
unsigned hd_base; /* File blocks prior to header */
|
||||
unsigned extcount; /* Extents in use */
|
||||
struct EXT ext[EXTMAX]; /* Mapping extents */
|
||||
struct fiddef hd_fid; /* Header info to create other WCBs */
|
||||
unsigned hd_basevbn; /* File blocks prior to header */
|
||||
unsigned hd_seg_num; /* Header segment number */
|
||||
struct fiddef hd_fid; /* Header FID */
|
||||
unsigned short extcount; /* Extents in use */
|
||||
unsigned phylen[EXTMAX];
|
||||
unsigned phyblk[EXTMAX];
|
||||
unsigned char rvn[EXTMAX];
|
||||
}; /* Window control block */
|
||||
|
||||
|
||||
@@ -170,6 +202,8 @@ struct VIOC {
|
||||
}; /* Chunk of a file */
|
||||
|
||||
|
||||
#define FCB_WRITE 1 /* FCB open for write... */
|
||||
|
||||
struct FCB {
|
||||
struct CACHE cache;
|
||||
struct VCB *vcb; /* Volume this file is for */
|
||||
@@ -177,9 +211,10 @@ struct FCB {
|
||||
struct HEAD *head; /* Pointer to header block */
|
||||
struct WCB *wcb; /* Window control block tree */
|
||||
struct VIOC *vioc; /* Virtual I/O chunk tree */
|
||||
unsigned modmask; /* headvioc chunk modmask */
|
||||
unsigned headvbn; /* vbn for file header */
|
||||
unsigned hiblock; /* Highest block mapped */
|
||||
unsigned highwater; /* First high water block */
|
||||
unsigned char status; /* FCB status bits */
|
||||
unsigned char rvn; /* Initial file relative volume */
|
||||
}; /* File control block */
|
||||
|
||||
@@ -197,13 +232,15 @@ struct DIRCACHE {
|
||||
struct VCB {
|
||||
unsigned status; /* Volume status */
|
||||
unsigned devices; /* Number of volumes in set */
|
||||
struct HEAD *idxboot; /* Pointer to index file boot header */
|
||||
struct FCB *fcb; /* File control block tree */
|
||||
struct DIRCACHE *dircache; /* Directory cache tree */
|
||||
struct VCBDEV {
|
||||
struct DEV *dev; /* Pointer to device info */
|
||||
struct FCB *idxfcb; /* Index file control block */
|
||||
struct FCB *mapfcb; /* Bitmap file control block */
|
||||
unsigned clustersize; /* Cluster size of the device */
|
||||
unsigned max_cluster; /* Total clusters on the device */
|
||||
unsigned free_clusters; /* Free clusters on disk volume */
|
||||
struct HOME home; /* Volume home block */
|
||||
} vcbdev[1]; /* List of volumes devices */
|
||||
}; /* Volume control block */
|
||||
@@ -216,11 +253,10 @@ struct DEV {
|
||||
unsigned status; /* Device physical status */
|
||||
unsigned sectors; /* Device physical sectors */
|
||||
unsigned sectorsize; /* Device physical sectorsize */
|
||||
int devlen; /* Length of device name */
|
||||
char devnam[1]; /* Device name */
|
||||
}; /* Device information */
|
||||
|
||||
|
||||
void fid_copy(struct fiddef *dst,struct fiddef *src,unsigned rvn);
|
||||
unsigned device_lookup(unsigned devlen,char *devnam,int create,struct DEV **retdev);
|
||||
|
||||
unsigned dismount(struct VCB *vcb);
|
||||
@@ -231,7 +267,12 @@ unsigned deaccessfile(struct FCB *fcb);
|
||||
unsigned accessfile(struct VCB *vcb,struct fiddef *fid,
|
||||
struct FCB **fcb,unsigned wrtflg);
|
||||
|
||||
unsigned deaccesschunk(struct VIOC *vioc,unsigned modmask,int reuse);
|
||||
unsigned deaccesschunk(struct VIOC *vioc,unsigned wrtvbn,int wrtblks,int reuse);
|
||||
unsigned accesschunk(struct FCB *fcb,unsigned vbn,struct VIOC **retvioc,
|
||||
char **retbuff,unsigned *retblocks,unsigned wrtblks,
|
||||
unsigned *retmodmask);
|
||||
char **retbuff,unsigned *retblocks,unsigned wrtblks);
|
||||
unsigned access_extend(struct FCB *fcb,unsigned blocks,unsigned contig);
|
||||
unsigned update_freecount(struct VCBDEV *vcbdev,unsigned *retcount);
|
||||
unsigned update_create(struct VCB *vcb,struct fiddef *did,char *filename,
|
||||
struct fiddef *fid,struct FCB **fcb);
|
||||
unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig);
|
||||
unsigned short checksum(vmsword *block);
|
||||
|
||||
@@ -1,37 +1,41 @@
|
||||
$ gccflag := 'cc'
|
||||
$ if f$extract(0,3,gccflag).nes."GCC" then gccflag=""
|
||||
$
|
||||
$ if gccflag.nes.""
|
||||
$ then p1="/optim=level=3/warn=all"+p1
|
||||
$ else p1="/warn=enabl=(defunct,obsolescent,questcode,uninit,unused)"+p1
|
||||
$ endif
|
||||
$
|
||||
$ default=f$parse(f$environment("PROCEDURE"),,,"DEVICE","SYNTAX_ONLY")+ -
|
||||
f$parse(f$environment("PROCEDURE"),,,"DIRECTORY","SYNTAX_ONLY")
|
||||
$ set def 'default'
|
||||
$
|
||||
$ call cc ods2 'p1'
|
||||
$ call cc rms 'p1'
|
||||
$ call cc direct 'p1'
|
||||
$ call cc access 'p1'
|
||||
$ call cc device 'p1'
|
||||
$ call cc cache 'p1'
|
||||
$ call cc phyvms 'p1'
|
||||
$ call cc vmstime 'p1'
|
||||
$
|
||||
$ write sys$error "''f$time()' Linking..."
|
||||
$ if gccflag.nes.""
|
||||
$ then library = ",vaxcrtl.tmp/option"
|
||||
$ create vaxcrtl.tmp
|
||||
sys$share:vaxcrtl/share
|
||||
$ endif
|
||||
$ link 'p2' ods2,rms,direct,access,device,cache,phyvms,vmstime 'library'
|
||||
$ write sys$error "''f$time()' Done"
|
||||
$ exit
|
||||
$
|
||||
$cc: subroutine
|
||||
$ if f$search(p1+".obj;").nes."" then if f$cvtime(f$file(p1+".obj;","CDT")).ges.f$cvtime(f$file(p1+".c;","CDT")) then exit
|
||||
$ write sys$error "''f$time()' Compiling ''p1'..."
|
||||
$ cc 'p2' 'p1'
|
||||
$ exit
|
||||
$ endsubroutine
|
||||
$ gccflag := 'cc'
|
||||
$ if f$extract(0,3,gccflag).nes."GCC" then gccflag=""
|
||||
$
|
||||
$ if gccflag.nes.""
|
||||
$ then p1="/optim=level=3/warn=all"+p1
|
||||
$ else p1="/warn=enabl=(defunct,obsolescent,questcode,uninit,unused)"+p1
|
||||
$ endif
|
||||
$
|
||||
$ if f$search("SYS$SYSTEM:DECC$COMPILER.EXE").eqs."" .and. gccflag.eqs.""
|
||||
$ then p1 = "/INCLUDE=SYS$DISK:[]"+p1
|
||||
$ endif
|
||||
$ default=f$parse(f$environment("PROCEDURE"),,,"DEVICE","SYNTAX_ONLY")+ -
|
||||
f$parse(f$environment("PROCEDURE"),,,"DIRECTORY","SYNTAX_ONLY")
|
||||
$ set def 'default'
|
||||
$
|
||||
$ call cc ods2 'p1'
|
||||
$ call cc rms 'p1'
|
||||
$ call cc direct 'p1'
|
||||
$ call cc access 'p1'
|
||||
$ call cc device 'p1'
|
||||
$ call cc cache 'p1'
|
||||
$ call cc phyvms 'p1'
|
||||
$ call cc update 'p1'
|
||||
$ call cc vmstime 'p1'
|
||||
$
|
||||
$ write sys$error "''f$time()' Linking..."
|
||||
$ if gccflag.nes."" .and. f$getsyi("HW_MODEL").lt.1024
|
||||
$ then library = ",vaxcrtl.tmp/option"
|
||||
$ create vaxcrtl.tmp
|
||||
sys$share:vaxcrtl/share
|
||||
$ endif
|
||||
$ link 'p2' ods2,rms,direct,access,device,cache,phyvms,vmstime,update 'library'
|
||||
$ write sys$error "''f$time()' Done"
|
||||
$ exit
|
||||
$
|
||||
$cc: subroutine
|
||||
$ if f$search(p1+".obj;").nes."" then if f$cvtime(f$file(p1+".obj;","CDT")).ges.f$cvtime(f$file(p1+".c;","CDT")) then exit
|
||||
$ write sys$error "''f$time()' Compiling ''p1'..."
|
||||
$ cc 'p2' 'p1'
|
||||
$ exit
|
||||
$ endsubroutine
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Cache.c v1.2 Caching control routines */
|
||||
/* Cache.c v1.3 Caching control routines */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -10,24 +10,41 @@
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
/* Caching seems to have a big impact on performance!!!
|
||||
This version based on number of objects - probably
|
||||
should change it to use space occupied by objects.
|
||||
Currently use vanilla binary trees - could either
|
||||
use hashing or balanced trees for better performance. */
|
||||
/*
|
||||
The theory is that all cachable objects share a common cache pool.
|
||||
Any object with a reference count of zero is a candidate for
|
||||
destruction. All cacheable objects have a 'struct CACHE' as the
|
||||
first item of the object so that cache pointers and object pointers
|
||||
are 'interchangeable'. All cache objects are also part of a binary
|
||||
tree so that they can be located. There are many instances of these
|
||||
binary trees: for files on a volume, file windows, file chunks
|
||||
(segments) etc. Also each object can have an object manager: a
|
||||
routine to handle special object deletion requirements (for example
|
||||
to remove all file chunks before removing a file), or to flush
|
||||
objects (write modified chunks to disk).
|
||||
|
||||
/* The theory is that all cachable objects share a common
|
||||
cache pool. Any object with a reference count of zero
|
||||
is a candidate for destruction. All cacheable objects
|
||||
have a 'struct CACHE' as the first item of the object
|
||||
so that cache pointers and object pointers are interchangeable.
|
||||
All cache objects are also part of a binary tree so that
|
||||
they can be located. There are many instances of these
|
||||
binary trees: for files on a volume, for chunks (segments)
|
||||
of files, etc. Also each object can have an object manager:
|
||||
a routine to handle special object deletion requirements
|
||||
(for example to remove all file chunks before removing a
|
||||
file), or to flush objects (write modified chunks to disk). */
|
||||
The main routines is cache_find() which is used to search for and
|
||||
place objects in a binary tree which is located by a tree pointer.
|
||||
cache_touch() and cache_untouch() are used to bump and decrement
|
||||
reference counts. Any object with a reference count of zero is a
|
||||
candidate for destruction - but if it requires special action
|
||||
before it is destroyed, such as deleting a subtree, flushing data
|
||||
to disk, etc, then it should have an 'object manager' function
|
||||
assigned which will be called at deletion time to take care of these
|
||||
needs.
|
||||
|
||||
This version of the cache routines attempts to maintain binary tree
|
||||
balance by dynamically changing tree shape during search functions.
|
||||
All objects remain in the binary tree until destruction so that they
|
||||
can be re-used at any time. Objects with a zero reference count are
|
||||
special in that they are kept in a 'least recently used' linked list.
|
||||
When the reference count is decemented a flag is used to indicate
|
||||
whether the object is likely to be referenced again so that the object
|
||||
can be put in the 'correct' end of this list.
|
||||
|
||||
Note: These routines are 'general' in that do not know anything
|
||||
about ODS2 objects or structures....
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -37,373 +54,308 @@
|
||||
#include "cache.h"
|
||||
|
||||
|
||||
#define DEBUG on
|
||||
#define DEBUG /* Debug mode? */
|
||||
#define IMBALANCE 5 /* Tree imbalance limit */
|
||||
#define CACHELIM 256 /* Free object limit */
|
||||
#define CACHEGOAL 128 /* Free object goal */
|
||||
|
||||
/* Set limits for number of unaccessed cache entries... */
|
||||
|
||||
#define CACHELIM 64
|
||||
#define CACHEGOAL 25
|
||||
|
||||
int cachesearches = 0;
|
||||
int cachefinds = 0;
|
||||
int cachecreated = 0;
|
||||
int cachedeleted = 0;
|
||||
int cachepurges = 0;
|
||||
int cachepeak = 0;
|
||||
int cachecount = 0;
|
||||
int cachefreecount = 0;
|
||||
int cachedeletes = 0;
|
||||
|
||||
struct CACHE cachelist = {NULL,NULL,NULL,&cachelist,&cachelist,NULL,0,0,1};
|
||||
int cachedeleteing = 0; /* Cache deletion in progress... */
|
||||
|
||||
struct CACHE lrulist = {&lrulist,&lrulist,NULL,NULL,NULL,NULL,0,0,1,0};
|
||||
|
||||
|
||||
/* cacheshow - to print cache statistics */
|
||||
/* cache_show() - to print cache statistics */
|
||||
|
||||
void cacheshow(void)
|
||||
void cache_show(void)
|
||||
{
|
||||
printf("CACHESHOW Searches: %d Created: %d Peak: %d Count: %d Free: %d\n",
|
||||
cachesearches,cachecreated,cachepeak,cachecount,cachefreecount);
|
||||
printf("CACHE_SHOW Find %d Create %d Purge %d Peak %d Count %d Free %d\n",
|
||||
cachefinds,cachecreated,cachepurges,cachepeak,cachecount,cachefreecount);
|
||||
if (cachecreated - cachedeletes != cachecount) printf(" - Deleted %d\n",cachedeletes);
|
||||
}
|
||||
|
||||
|
||||
void cachedump(void)
|
||||
{
|
||||
register struct CACHE *cacheobj = cachelist.lstcache;
|
||||
printf("%8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s cachelist\n","Object",
|
||||
"Parent","Left","Right","Value","Status","Count");
|
||||
while (cacheobj != &cachelist) {
|
||||
printf("%8p %8p %8p %8p %8x %8x %8d\n",
|
||||
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
|
||||
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
|
||||
cacheobj = cacheobj->lstcache;
|
||||
}
|
||||
}
|
||||
/* cache_refcount() - compute reference count for cache subtree... */
|
||||
|
||||
|
||||
/* cacheprint - debugging tool to print out a cache subtree... */
|
||||
|
||||
void cacheprint(struct CACHE *cacheobj,int level)
|
||||
{
|
||||
if (cacheobj != NULL) {
|
||||
int i;
|
||||
cacheprint(cacheobj->left,level + 1);
|
||||
for (i = 0; i < level; i++) printf(" ");
|
||||
printf("%8p %8x %8x %d\n",
|
||||
cacheobj,cacheobj->keyval,cacheobj->status,cacheobj->refcount);
|
||||
cacheprint(cacheobj->right,level + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cacherefcount - compute reference count for cache subtree... */
|
||||
|
||||
int cacherefcount(struct CACHE *cacheobj)
|
||||
int cache_refcount(struct CACHE *cacheobj)
|
||||
{
|
||||
register int refcount = 0;
|
||||
if (cacheobj != NULL) {
|
||||
if (cacheobj->left != NULL) refcount += cacherefcount(cacheobj->left);
|
||||
if (cacheobj->right != NULL) refcount += cacherefcount(cacheobj->right);
|
||||
refcount += cacheobj->refcount;
|
||||
refcount = cacheobj->refcount;
|
||||
if (cacheobj->left != NULL) refcount += cache_refcount(cacheobj->left);
|
||||
if (cacheobj->right != NULL) refcount += cache_refcount(cacheobj->right);
|
||||
}
|
||||
return refcount;
|
||||
}
|
||||
|
||||
|
||||
/* cachefree - blow away item from cache - allow item to select a proxy (!)
|
||||
/* cache_delete() - blow away item from cache - allow item to select a proxy (!)
|
||||
and adjust 'the tree' containing the item. */
|
||||
|
||||
int freeactive = 0; /* In case object managers re-call cachefree... :-( */
|
||||
|
||||
struct CACHE *cachefree(struct CACHE *cacheobj)
|
||||
struct CACHE *cache_delete(struct CACHE *cacheobj)
|
||||
{
|
||||
if (cacheobj->refcount != 0) {
|
||||
char str[100];
|
||||
printf("cachelist, object to delete still inuse?\n");
|
||||
printf("%8p %8p %8p %8p %8x %8x %8d\n",
|
||||
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
|
||||
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
|
||||
printf("Type RETURN: ");
|
||||
fgets(str, sizeof(str)-1, stdin);
|
||||
return NULL;
|
||||
} else {
|
||||
while (cacheobj->objmanager != NULL) {
|
||||
register struct CACHE *proxyobj;
|
||||
while (cacheobj->objmanager != NULL) {
|
||||
freeactive = 1;
|
||||
proxyobj = (*cacheobj->objmanager) (cacheobj);
|
||||
freeactive = 0;
|
||||
if (proxyobj == NULL) return NULL;
|
||||
if (proxyobj == cacheobj) break;
|
||||
cacheobj = proxyobj;
|
||||
}
|
||||
if ((cacheobj->status & CACHE_MODIFIED) && cacheobj->objmanager == NULL)
|
||||
printf("cachelist No manager to write modified cache\n");
|
||||
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
|
||||
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
|
||||
if (cacheobj->parent != NULL) { /* Check if in tree... */
|
||||
if (cacheobj->left == NULL) {
|
||||
if (cacheobj->right == NULL) {
|
||||
*(cacheobj->parent) = NULL;
|
||||
} else {
|
||||
cacheobj->right->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->right;
|
||||
}
|
||||
} else {
|
||||
if (cacheobj->right == NULL) {
|
||||
cacheobj->left->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->left;
|
||||
} else {
|
||||
register struct CACHE *leftpath = cacheobj->left;
|
||||
register struct CACHE *rightpath = cacheobj->right;
|
||||
while (1) {
|
||||
if (leftpath->right == NULL) {
|
||||
leftpath->right = cacheobj->right;
|
||||
cacheobj->right->parent = &leftpath->right;
|
||||
cacheobj->left->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->left;
|
||||
break;
|
||||
} else {
|
||||
if (rightpath->left == NULL) {
|
||||
rightpath->left = cacheobj->left;
|
||||
cacheobj->left->parent = &rightpath->left;
|
||||
cacheobj->right->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->right;
|
||||
break;
|
||||
} else {
|
||||
leftpath = leftpath->right;
|
||||
rightpath = rightpath->left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (--cachecount < 0) printf("cachelist, cache current too small\n");
|
||||
cachefreecount--;
|
||||
cachedeleted--;
|
||||
#ifdef DEBUG
|
||||
cacheobj->parent = NULL;
|
||||
cacheobj->left = NULL;
|
||||
cacheobj->right = NULL;
|
||||
cacheobj->nxtcache = NULL;
|
||||
cacheobj->lstcache = NULL;
|
||||
cacheobj->objmanager = NULL;
|
||||
cacheobj->keyval = 0;
|
||||
cacheobj->status = 0;
|
||||
cacheobj->refcount = 0;
|
||||
#endif
|
||||
free(cacheobj);
|
||||
return cacheobj;
|
||||
cachedeleteing = 1;
|
||||
proxyobj = (*cacheobj->objmanager) (cacheobj,0);
|
||||
cachedeleteing = 0;
|
||||
if (proxyobj == NULL) return NULL;
|
||||
if (proxyobj == cacheobj) break;
|
||||
cacheobj = proxyobj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cachepurge - trim size of free list */
|
||||
|
||||
void cachepurge()
|
||||
{
|
||||
register struct CACHE *cacheobj = cachelist.lstcache;
|
||||
while (cachefreecount > CACHEGOAL && cacheobj != &cachelist) {
|
||||
register struct CACHE *lastobj = cacheobj->lstcache;
|
||||
#ifdef DEBUG
|
||||
if (cacheobj->lstcache->nxtcache != cacheobj ||
|
||||
cacheobj->nxtcache->lstcache != cacheobj ||
|
||||
*(cacheobj->parent) != cacheobj) {
|
||||
printf("CACHE pointers in bad shape! %p %p %p - %p\n",
|
||||
cacheobj->lstcache->nxtcache,cacheobj,cacheobj->nxtcache->lstcache,*(cacheobj->parent));
|
||||
}
|
||||
if (cachedeleteing != 0) printf("CACHE deletion while delete in progress\n");
|
||||
#endif
|
||||
if (cacheobj->refcount == 0) {
|
||||
if (cachefree(cacheobj) != lastobj) cacheobj = lastobj;
|
||||
if (cacheobj->refcount != 0) {
|
||||
#ifdef DEBUG
|
||||
printf("CACHE attempt to delete referenced object %d:%d\n",
|
||||
cacheobj->objtype,cacheobj->hashval);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
cacheobj->lastlru->nextlru = cacheobj->nextlru;
|
||||
cacheobj->nextlru->lastlru = cacheobj->lastlru;
|
||||
if (cacheobj->left == NULL) {
|
||||
if (cacheobj->right == NULL) {
|
||||
*(cacheobj->parent) = NULL;
|
||||
} else {
|
||||
cacheobj = lastobj;
|
||||
cacheobj->right->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* cacheflush - flush modified entries in cache */
|
||||
|
||||
void cacheflush()
|
||||
{
|
||||
register struct CACHE *cacheobj = cachelist.lstcache;
|
||||
while (cacheobj != &cachelist) {
|
||||
if (cacheobj->status & CACHE_MODIFIED) {
|
||||
if (cacheobj->objmanager != NULL) {
|
||||
(*cacheobj->objmanager) (cacheobj);
|
||||
} else {
|
||||
printf("CACHEFLUSH No manager to write modified cache\n");
|
||||
} else {
|
||||
if (cacheobj->right == NULL) {
|
||||
cacheobj->left->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = cacheobj->left;
|
||||
} else {
|
||||
register struct CACHE *path = cacheobj->right;
|
||||
if (path->left != NULL) {
|
||||
do {
|
||||
path = path->left;
|
||||
} while (path->left != NULL);
|
||||
*(path->parent) = path->right;
|
||||
if (path->right != NULL) path->right->parent = path->parent;
|
||||
path->right = cacheobj->right;
|
||||
path->right->parent = &path->right;
|
||||
}
|
||||
path->left = cacheobj->left;
|
||||
path->left->parent = &path->left;
|
||||
path->parent = cacheobj->parent;
|
||||
*(cacheobj->parent) = path;
|
||||
path->balance = 0;
|
||||
}
|
||||
cacheobj = cacheobj->lstcache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cachedelete - delete an object from cache */
|
||||
|
||||
struct CACHE *cachedelete(struct CACHE *cacheobj)
|
||||
{
|
||||
if (cacheobj != NULL) {
|
||||
register struct CACHE *cachedel;
|
||||
do {
|
||||
cachedel = cachefree(cacheobj);
|
||||
} while (cachedel != NULL && cachedel != cacheobj);
|
||||
}
|
||||
cachecount--;
|
||||
cachefreecount--;
|
||||
cachedeletes++;
|
||||
#ifdef DEBUG
|
||||
cacheobj->nextlru = NULL;
|
||||
cacheobj->lastlru = NULL;
|
||||
cacheobj->left = NULL;
|
||||
cacheobj->right = NULL;
|
||||
cacheobj->parent = NULL;
|
||||
cacheobj->objmanager = NULL;
|
||||
cacheobj->hashval = 0;
|
||||
cacheobj->balance = 0;
|
||||
cacheobj->refcount = 0;
|
||||
#endif
|
||||
free(cacheobj);
|
||||
return cacheobj;
|
||||
}
|
||||
|
||||
|
||||
/* cache_purge() - trim size of free list */
|
||||
|
||||
/* cachedeltree: delete cache subtree */
|
||||
void cache_purge(void)
|
||||
{
|
||||
if (cachedeleteing == 0) {
|
||||
register struct CACHE *cacheobj = lrulist.lastlru;
|
||||
cachepurges++;
|
||||
while (cachefreecount > CACHEGOAL && cacheobj != &lrulist) {
|
||||
register struct CACHE *lastobj = cacheobj->lastlru;
|
||||
#ifdef DEBUG
|
||||
if (cacheobj->lastlru->nextlru != cacheobj ||
|
||||
cacheobj->nextlru->lastlru != cacheobj ||
|
||||
*(cacheobj->parent) != cacheobj) {
|
||||
printf("CACHE pointers in bad shape!\n");
|
||||
}
|
||||
#endif
|
||||
if (cacheobj->refcount == 0) {
|
||||
if (cache_delete(cacheobj) != lastobj) cacheobj = lastobj;
|
||||
} else {
|
||||
cacheobj = lastobj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cachedeltree(struct CACHE *cacheobj)
|
||||
|
||||
|
||||
/* cache_flush() - flush modified entries in cache */
|
||||
|
||||
void cache_flush(void)
|
||||
{
|
||||
register struct CACHE *cacheobj = lrulist.lastlru;
|
||||
while (cacheobj != &lrulist) {
|
||||
if (cacheobj->objmanager != NULL) {
|
||||
(*cacheobj->objmanager) (cacheobj,1);
|
||||
}
|
||||
cacheobj = cacheobj->lastlru;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* cache_remove() - delete all possible objects from cache subtree */
|
||||
|
||||
void cache_remove(struct CACHE *cacheobj)
|
||||
{
|
||||
if (cacheobj != NULL) {
|
||||
if (cacheobj->left != NULL) cachedeltree(cacheobj->left);
|
||||
if (cacheobj->right != NULL) cachedeltree(cacheobj->right);
|
||||
if (cacheobj->refcount == 0) cachedelete(cacheobj);
|
||||
if (cacheobj->left != NULL) cache_remove(cacheobj->left);
|
||||
if (cacheobj->right != NULL) cache_remove(cacheobj->right);
|
||||
if (cacheobj->refcount == 0) {
|
||||
struct CACHE *delobj;
|
||||
do {
|
||||
delobj = cache_delete(cacheobj);
|
||||
} while (delobj != NULL && delobj != cacheobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cache_touch() - to increase the access count on an object... */
|
||||
|
||||
|
||||
|
||||
/* cacheuntouch - decrement object reference count */
|
||||
|
||||
unsigned cacheuntouch(struct CACHE *cacheobj,unsigned reuse,unsigned modflg)
|
||||
void cache_touch(struct CACHE *cacheobj)
|
||||
{
|
||||
if (cacheobj->refcount < 1) {
|
||||
char str[100];
|
||||
printf("%8p %8p %8p %8p %8x %8x %8d\n",
|
||||
cacheobj,cacheobj->parent,cacheobj->left,cacheobj->right,
|
||||
cacheobj->keyval,cacheobj->status,cacheobj->refcount);
|
||||
printf("CACHE untouch TOO FAR!\n");
|
||||
printf("Type RETURN: ");
|
||||
fgets(str, sizeof(str), stdin);
|
||||
return 64;
|
||||
} else {
|
||||
if (modflg) {
|
||||
if ((cacheobj->status & CACHE_WRITE) == 0) return SS$_WRITLCK;
|
||||
cacheobj->status |= CACHE_MODIFIED;
|
||||
}
|
||||
if (--cacheobj->refcount == 0) {
|
||||
/* Move to new list position... */
|
||||
if (reuse == 0 && cacheobj != cachelist.lstcache) {
|
||||
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
|
||||
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
|
||||
cacheobj->nxtcache = &cachelist;
|
||||
cacheobj->lstcache = cachelist.lstcache;
|
||||
cachelist.lstcache->nxtcache = cacheobj;
|
||||
cachelist.lstcache = cacheobj;
|
||||
}
|
||||
cacheobj->status &= ~CACHE_WRITE;
|
||||
if (++cachefreecount > CACHELIM && freeactive == 0) cachepurge();
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* cachetouch - add one to reference count */
|
||||
|
||||
void cachetouch(struct CACHE *cacheobj)
|
||||
{
|
||||
if (cacheobj->refcount++ < 1) {
|
||||
if (cacheobj->refcount++ == 0) {
|
||||
#ifdef DEBUG
|
||||
if (cacheobj->lstcache->nxtcache != cacheobj ||
|
||||
cacheobj->nxtcache->lstcache != cacheobj ||
|
||||
*(cacheobj->parent) != cacheobj) {
|
||||
printf("CACHE pointers in bad shape! %p %p %p - %p\n",
|
||||
cacheobj->lstcache->nxtcache,cacheobj,cacheobj->nxtcache->lstcache,*(cacheobj->parent));
|
||||
if (cacheobj->nextlru == NULL || cacheobj->lastlru == NULL) {
|
||||
printf("CACHE LRU pointers corrupt!\n");
|
||||
}
|
||||
#endif
|
||||
cacheobj->nextlru->lastlru = cacheobj->lastlru;
|
||||
cacheobj->lastlru->nextlru = cacheobj->nextlru;
|
||||
cacheobj->nextlru = NULL;
|
||||
cacheobj->lastlru = NULL;
|
||||
cachefreecount--;
|
||||
}
|
||||
/* Move object to head of list... */
|
||||
if (cacheobj != cachelist.nxtcache) {
|
||||
cacheobj->lstcache->nxtcache = cacheobj->nxtcache;
|
||||
cacheobj->nxtcache->lstcache = cacheobj->lstcache;
|
||||
cacheobj->lstcache = &cachelist;
|
||||
cacheobj->nxtcache = cachelist.nxtcache;
|
||||
cachelist.nxtcache->lstcache = cacheobj;
|
||||
cachelist.nxtcache = cacheobj;
|
||||
}
|
||||
}
|
||||
|
||||
/* cache_untouch() - to deaccess an object... */
|
||||
|
||||
/* cachesearch - to find or create cache entries...
|
||||
void cache_untouch(struct CACHE *cacheobj,int recycle)
|
||||
{
|
||||
if (cacheobj->refcount > 0) {
|
||||
if (--cacheobj->refcount == 0) {
|
||||
if (++cachefreecount >= CACHELIM) cache_purge();
|
||||
#ifdef DEBUG
|
||||
if (cacheobj->nextlru != NULL || cacheobj->lastlru != NULL) {
|
||||
printf("CACHE LRU pointers corrupt\n");
|
||||
}
|
||||
#endif
|
||||
if (recycle) {
|
||||
cacheobj->nextlru = lrulist.nextlru;
|
||||
cacheobj->lastlru = &lrulist;
|
||||
cacheobj->nextlru->lastlru = cacheobj;
|
||||
lrulist.nextlru = cacheobj;
|
||||
} else {
|
||||
cacheobj->lastlru = lrulist.lastlru;
|
||||
cacheobj->nextlru = &lrulist;
|
||||
cacheobj->lastlru->nextlru = cacheobj;
|
||||
lrulist.lastlru = cacheobj;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
} else {
|
||||
printf("CACHE untouch limit exceeded\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* cache_find() - to find or create cache entries...
|
||||
|
||||
The grand plan here was to use a hash code as a quick key
|
||||
and call a compare function for duplicates. So far no data
|
||||
type actually works like this - they either have a unique binary
|
||||
key, or all records rely on the compare function - sigh!
|
||||
Never mind, the potential is there! :-) */
|
||||
Never mind, the potential is there! :-)
|
||||
|
||||
void *cachesearch(void **root,unsigned keyval,unsigned keylen,void *key,
|
||||
int (*cmpfunc) (unsigned keylen,void *key,void *node),
|
||||
unsigned *createsize)
|
||||
This version will call a creation function to allocate and
|
||||
initialize an object if it is not found.
|
||||
*/
|
||||
|
||||
void *cache_find(void **root,unsigned hashval,void *keyval,unsigned *retsts,
|
||||
int (*compare_func) (unsigned hashval,void *keyval,void *node),
|
||||
void *(*create_func) (unsigned hashval,void *keyval,unsigned *retsts))
|
||||
{
|
||||
register struct CACHE *parentobj = NULL;
|
||||
register struct CACHE *cacheobj,**parent = (struct CACHE **) root;
|
||||
cachesearches++;
|
||||
cachefinds++;
|
||||
while ((cacheobj = *parent) != NULL) {
|
||||
parentobj = cacheobj;
|
||||
if (cacheobj->keyval == keyval) {
|
||||
register int cmp = 0;
|
||||
if (cmpfunc != NULL)
|
||||
cmp = (*cmpfunc) (keylen,key,(void *) cacheobj);
|
||||
if (cmp == 0) {
|
||||
cachetouch(cacheobj);
|
||||
return cacheobj;
|
||||
register int cmp = hashval - cacheobj->hashval;
|
||||
#ifdef DEBUG
|
||||
if (cacheobj->parent != parent) {
|
||||
printf("CACHE Parent pointer is corrupt\n");
|
||||
}
|
||||
#endif
|
||||
if (cmp == 0 && compare_func != NULL) cmp = (*compare_func) (hashval,keyval,cacheobj);
|
||||
if (cmp == 0) {
|
||||
cache_touch(cacheobj);
|
||||
if (retsts != NULL) *retsts = SS$_NORMAL;
|
||||
return cacheobj;
|
||||
}
|
||||
if (cmp < 0) {
|
||||
#ifdef IMBALANCE
|
||||
register struct CACHE *left_path = cacheobj->left;
|
||||
if (left_path != NULL && cacheobj->balance-- < -IMBALANCE) {
|
||||
cacheobj->left = left_path->right;
|
||||
if (cacheobj->left != NULL) cacheobj->left->parent = &cacheobj->left;
|
||||
left_path->right = cacheobj;
|
||||
cacheobj->parent = &left_path->right;
|
||||
*parent = left_path;
|
||||
left_path->parent = parent;
|
||||
cacheobj->balance = 0;
|
||||
} else {
|
||||
if (cmp < 0) {
|
||||
parent = &cacheobj->left;
|
||||
} else {
|
||||
parent = &cacheobj->right;
|
||||
}
|
||||
parent = &cacheobj->left;
|
||||
}
|
||||
} else {
|
||||
if (cacheobj->keyval < keyval) {
|
||||
parent = &cacheobj->left;
|
||||
register struct CACHE *right_path = cacheobj->right;
|
||||
if (right_path != NULL && cacheobj->balance++ > IMBALANCE) {
|
||||
cacheobj->right = right_path->left;
|
||||
if (cacheobj->right != NULL) cacheobj->right->parent = &cacheobj->right;
|
||||
right_path->left = cacheobj;
|
||||
cacheobj->parent = &right_path->left;
|
||||
*parent = right_path;
|
||||
right_path->parent = parent;
|
||||
cacheobj->balance = 0;
|
||||
} else {
|
||||
parent = &cacheobj->right;
|
||||
}
|
||||
#else
|
||||
parent = &cacheobj->left;
|
||||
} else {
|
||||
parent = &cacheobj->right;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if (*createsize > sizeof(struct CACHE)) {
|
||||
cacheobj = (struct CACHE *) malloc(*createsize);
|
||||
if (create_func == NULL) {
|
||||
if (retsts != NULL) *retsts = SS$_ITEMNOTFOUND;
|
||||
} else {
|
||||
cacheobj = (*create_func) (hashval,keyval,retsts);
|
||||
if (cacheobj != NULL) {
|
||||
cacheobj->parent = parent;
|
||||
cacheobj->nextlru = NULL;
|
||||
cacheobj->lastlru = NULL;
|
||||
cacheobj->left = NULL;
|
||||
cacheobj->right = NULL;
|
||||
cacheobj->objmanager = NULL;
|
||||
cacheobj->keyval = keyval;
|
||||
cacheobj->status = 0;
|
||||
cacheobj->parent = parent;
|
||||
cacheobj->hashval = hashval;
|
||||
cacheobj->balance = 0;
|
||||
cacheobj->refcount = 1;
|
||||
*parent = cacheobj;
|
||||
*createsize = 0;
|
||||
cachecreated++;
|
||||
/* Add to cache list... */
|
||||
cacheobj->lstcache = &cachelist;
|
||||
cacheobj->nxtcache = cachelist.nxtcache;
|
||||
cachelist.nxtcache->lstcache = cacheobj;
|
||||
cachelist.nxtcache = cacheobj;
|
||||
if (parentobj != NULL) {
|
||||
/* Attempt to mix up the tree a little... */
|
||||
if (parentobj->left == NULL) {
|
||||
*parentobj->parent = cacheobj;
|
||||
cacheobj->parent = parentobj->parent;
|
||||
parentobj->parent = &cacheobj->left;
|
||||
cacheobj->left = parentobj;
|
||||
parentobj->right = NULL;
|
||||
} else {
|
||||
if (parentobj->right == NULL) {
|
||||
*parentobj->parent = cacheobj;
|
||||
cacheobj->parent = parentobj->parent;
|
||||
parentobj->parent = &cacheobj->right;
|
||||
cacheobj->right = parentobj;
|
||||
parentobj->left = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cachecount++ >= cachepeak) cachepeak = cachecount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Cache.h v1.2 Definitions for cache routines */
|
||||
/* Cache.h v1.3 Definitions for cache routines */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -10,35 +10,38 @@
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
#ifndef CACHE_WRITE
|
||||
#ifndef CACHE_LOADED
|
||||
|
||||
#define CACHE_WRITE 1
|
||||
#define CACHE_MODIFIED 2
|
||||
#define CACHE_LOADED
|
||||
|
||||
#ifndef VAXC /* Stupid VAX C doesn't allow "signed" keyword */
|
||||
#define signed signed
|
||||
#else
|
||||
#define signed
|
||||
#endif
|
||||
|
||||
struct CACHE {
|
||||
struct CACHE **parent;
|
||||
struct CACHE *left;
|
||||
struct CACHE *right;
|
||||
struct CACHE *nxtcache;
|
||||
struct CACHE *lstcache;
|
||||
struct CACHE *(*objmanager) (struct CACHE * cacheobj);
|
||||
unsigned keyval;
|
||||
unsigned status;
|
||||
int refcount;
|
||||
struct CACHE *nextlru; /* next object on least recently used list */
|
||||
struct CACHE *lastlru; /* last object on least recently used list */
|
||||
struct CACHE *left; /* left branch of binary tree */
|
||||
struct CACHE *right; /* right branch of binary tree */
|
||||
struct CACHE **parent; /* address of pointer to this object */
|
||||
void *(*objmanager) (struct CACHE * cacheobj,int flushonly);
|
||||
unsigned hashval; /* object hash value */
|
||||
short refcount; /* object reference count */
|
||||
signed char balance; /* object tree imbalance factor */
|
||||
signed char objtype; /* object type (for debugging) */
|
||||
};
|
||||
|
||||
void cacheshow(void);
|
||||
void cachedump(void);
|
||||
void cacheprint(struct CACHE *cacheobj,int level);
|
||||
void cacheflush(void);
|
||||
int cacherefcount(struct CACHE *cacheobj);
|
||||
void cachedeltree(struct CACHE *cacheobj);
|
||||
void cachetouch(struct CACHE *cacheobj);
|
||||
unsigned cacheuntouch(struct CACHE *cacheobj,unsigned reuse,unsigned modflg);
|
||||
struct CACHE *cachefree(struct CACHE *cacheobj);
|
||||
struct CACHE *cachedelete(struct CACHE *cacheobj);
|
||||
struct CACHE *cachemake(struct CACHE **parent,unsigned length);
|
||||
void *cachesearch(void **root,unsigned keyval,unsigned keylen,void *key,
|
||||
int (*cmpfunc) (unsigned keylen,void *key,void *node),
|
||||
unsigned *createsize);
|
||||
void cache_show(void);
|
||||
int cache_refcount(struct CACHE *cacheobj);
|
||||
struct CACHE *cache_delete(struct CACHE *cacheobj);
|
||||
void cache_purge(void);
|
||||
void cache_flush(void);
|
||||
void cache_remove(struct CACHE *cacheobj);
|
||||
void cache_touch(struct CACHE * cacheobj);
|
||||
void cache_untouch(struct CACHE * cacheobj,int recycle);
|
||||
void *cache_find(void **root,unsigned hashval,void *keyval,unsigned *retsts,
|
||||
int (*compare_func) (unsigned hashval,void *keyval,void *node),
|
||||
void *(*create_func) (unsigned hashval,void *keyval,unsigned *retsts));
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Descrip.h v1.2 Definitions for descriptors */
|
||||
/* Descrip.h v1.4 Definitions for descriptors */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -8,27 +8,41 @@
|
||||
VMS community to use. However all derived works
|
||||
must maintain comments in their source to acknowledge
|
||||
the contibution of the original author.
|
||||
|
||||
1.4 Changed declarations NOT to define DOLLAR identifiers
|
||||
unless DOLLAR is defined (some compilers can't handle $'s!)
|
||||
Fixed definition of _DESCRIPTOR().
|
||||
1.4A Changed default DOLLAR handling to include DOLLAR
|
||||
identifers unless NO_DOLLAR is defined
|
||||
(ie #ifdef DOLLAR to #ifndef NO_DOLLAR)
|
||||
*/
|
||||
|
||||
#ifndef _DESCRIPTOR
|
||||
|
||||
#if defined(VMS) && !defined(__GNUC__)
|
||||
#ifndef NO_DOLLAR
|
||||
#ifndef $DESCRIPTOR
|
||||
#define DSC$K_DTYPE_T DSC_K_DTYPE_T
|
||||
#define DSC$K_CLASS_S DSC_K_CLASS_S
|
||||
#define dsc$descriptor dsc_descriptor
|
||||
#define dsc$w_length dsc_w_length
|
||||
#define dsc$b_dtype dsc_b_dtype
|
||||
#define dsc$b_class dsc_b_class
|
||||
#define dsc$a_pointer dsc_a_pointer
|
||||
#define $DESCRIPTOR _DESCRIPTOR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <descrip.h>
|
||||
#define DSC_K_DTYPE_T 0
|
||||
#define DSC_K_CLASS_S 0
|
||||
|
||||
#else
|
||||
|
||||
#ifndef DSC$K_DTYPE_T
|
||||
#define DSC$K_DTYPE_T 0
|
||||
#define DSC$K_CLASS_S 0
|
||||
|
||||
struct dsc$descriptor {
|
||||
unsigned short dsc$w_length;
|
||||
unsigned char dsc$w_type;
|
||||
unsigned char dsc$w_class;
|
||||
char *dsc$a_pointer;
|
||||
struct dsc_descriptor {
|
||||
unsigned short dsc_w_length;
|
||||
unsigned char dsc_b_dtype;
|
||||
unsigned char dsc_b_class;
|
||||
char *dsc_a_pointer;
|
||||
};
|
||||
|
||||
#define $DESCRIPTOR(string,name) struct dsc$descriptor name = {sizeof(sring)-1,0,0,string};
|
||||
#define _DESCRIPTOR(symbol,value) \
|
||||
struct dsc_descriptor symbol = {sizeof(value)-1,0,0,value}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
58
extracters/ods2/descrip.mms
Normal file
58
extracters/ods2/descrip.mms
Normal file
@@ -0,0 +1,58 @@
|
||||
#
|
||||
# MMS (MMK) description file to build ODS2 for VMS
|
||||
#
|
||||
# To compile on VAX using VAX C, use:
|
||||
#
|
||||
# $ mmk/macro=vaxc=1
|
||||
#
|
||||
#
|
||||
.IFDEF EXE
|
||||
.ELSE
|
||||
EXE = .EXE
|
||||
OBJ = .OBJ
|
||||
OLB = .OLB
|
||||
.ENDIF
|
||||
|
||||
.IFDEF __DEBUG__
|
||||
CFLAGS = $(CFLAGS)/DEBUG/NOOPTIMIZE
|
||||
LINKFLAGS = $(LINKFLAGS)/DEBUG
|
||||
.ELSE
|
||||
LINKFLAGS = $(LINKFLAGS)/NOTRACE
|
||||
.ENDIF
|
||||
|
||||
.IFDEF __VAXC__
|
||||
CFLAGS = $(CFLAGS)/INCLUDE=SYS$DISK:[]
|
||||
OPTFILE = ,VAXCRTL.OPT
|
||||
OPTIONS = $(OPTFILE)/OPTIONS
|
||||
.ELSE
|
||||
OPTFILE =
|
||||
OPTIONS =
|
||||
.ENDIF
|
||||
|
||||
OBJS = ODS2,RMS,DIRECT,ACCESS,DEVICE,CACHE,PHYVMS,UPDATE,VMSTIME
|
||||
|
||||
ODS2$(EXE) : ODS2$(OLB)($(OBJS))$(OPTFILE)
|
||||
$(LINK)$(LINKFLAGS) ODS2$(OLB)/INCLUDE=($(OBJS))$(OPTIONS)
|
||||
|
||||
vmstime$(obj) : vmstime.c vmstime.h
|
||||
|
||||
cache$(obj) : cache.c cache.h ssdef.h
|
||||
|
||||
phyvms$(obj) : phyvms.c phyio.h ssdef.h
|
||||
|
||||
device$(obj) : device.c ssdef.h access.h phyio.h
|
||||
|
||||
access$(obj) : access.c ssdef.h access.h phyio.h
|
||||
|
||||
update$(obj) : update.c ssdef.h access.h
|
||||
|
||||
direct$(obj) : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
|
||||
rms$(obj) : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
|
||||
ods2$(obj) : ods2.c ssdef.h descrip.h access.h rms.h
|
||||
|
||||
VAXCRTL.OPT :
|
||||
@ open/write tmp $(MMS$TARGET)
|
||||
@ write tmp "SYS$SHARE:VAXCRTL.EXE/SHARE"
|
||||
@ close tmp
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Device.c v1.2 Module to remember and find devices...*/
|
||||
/* Device.c v1.3 Module to remember and find devices...*/
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -23,63 +23,72 @@
|
||||
#include "access.h"
|
||||
#include "phyio.h"
|
||||
|
||||
/* device_create() creates a device object... */
|
||||
|
||||
int devcmp(unsigned keylen,void *key,void *node)
|
||||
void *device_create(unsigned devsiz,void *keyval,unsigned *retsts)
|
||||
{
|
||||
register char *devnam = (char *) keyval;
|
||||
register struct DEV *dev = (struct DEV *) malloc(sizeof(struct DEV) + devsiz + 2);
|
||||
if (dev == NULL) {
|
||||
*retsts = SS$_INSFMEM;
|
||||
} else {
|
||||
register unsigned sts;
|
||||
struct phyio_info info;
|
||||
dev->cache.objmanager = NULL;
|
||||
dev->cache.objtype = 1;
|
||||
memcpy(dev->devnam,devnam,devsiz);
|
||||
memcpy(dev->devnam + devsiz,":",2);
|
||||
sts = phyio_init(devsiz + 1,dev->devnam,&dev->handle,&info);
|
||||
*retsts = sts;
|
||||
if (sts & 1) {
|
||||
dev->vcb = NULL;
|
||||
dev->status = info.status;
|
||||
dev->sectors = info.sectors;
|
||||
dev->sectorsize = info.sectorsize;
|
||||
} else {
|
||||
free(dev);
|
||||
dev = NULL;
|
||||
}
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* device_compare() compares a device name to that of a device object... */
|
||||
|
||||
int device_compare(unsigned keylen,void *keyval,void *node)
|
||||
{
|
||||
register struct DEV *devnode = (struct DEV *) node;
|
||||
register int cmp = keylen - devnode->devlen;
|
||||
if (cmp == 0) {
|
||||
register unsigned len = keylen;
|
||||
register char *keynam = (char *) key;
|
||||
register char *devnam = devnode->devnam;
|
||||
while (len-- > 0) {
|
||||
cmp = toupper(*keynam++) - toupper(*devnam++);
|
||||
if (cmp != 0) break;
|
||||
}
|
||||
register int cmp = 0;
|
||||
register int len = keylen;
|
||||
register char *keynam = (char *) keyval;
|
||||
register char *devnam = devnode->devnam;
|
||||
while (len-- > 0) {
|
||||
cmp = toupper(*keynam++) - toupper(*devnam++);
|
||||
if (cmp != 0) break;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
/* device_lookup() is to to find devices... */
|
||||
|
||||
struct DEV *dev_root = NULL;
|
||||
|
||||
unsigned device_lookup(unsigned devlen,char *devnam,
|
||||
int create,struct DEV **retdev)
|
||||
{
|
||||
register struct DEV *dev;
|
||||
register unsigned sts,devsiz = 0;
|
||||
unsigned devcreate = 0;
|
||||
unsigned sts = 1,devsiz = 0;
|
||||
while (devsiz < devlen) {
|
||||
if (devnam[devsiz] == ':') break;
|
||||
devsiz++;
|
||||
}
|
||||
if (create) devcreate = sizeof(struct DEV) + devsiz + 2;
|
||||
dev = (struct DEV *) cachesearch((void **) &dev_root,0,devsiz,
|
||||
(void *) devnam,devcmp,&devcreate);
|
||||
dev = (struct DEV *) cache_find((void **) &dev_root,devsiz,devnam,&sts,
|
||||
device_compare,create ? device_create : NULL);
|
||||
if (dev == NULL) {
|
||||
if (create) {
|
||||
sts = SS$_INSFMEM;
|
||||
} else {
|
||||
sts = SS$_NOSUCHDEV;
|
||||
}
|
||||
if (sts == SS$_ITEMNOTFOUND) sts = SS$_NOSUCHDEV;
|
||||
} else {
|
||||
struct phyio_info info;
|
||||
*retdev = dev;
|
||||
if (create && (devcreate == 0)) {
|
||||
memcpy(dev->devnam,devnam,devsiz);
|
||||
memcpy(dev->devnam + devsiz,":",2);
|
||||
dev->devlen = devsiz;
|
||||
sts = phyio_init(devsiz + 1,dev->devnam,&dev->handle,&info);
|
||||
if (sts & 1) {
|
||||
dev->status = info.status;
|
||||
dev->sectors = info.sectors;
|
||||
dev->sectorsize = info.sectorsize;
|
||||
} else {
|
||||
cacheuntouch((struct CACHE *) dev,0,0);
|
||||
cachefree((struct CACHE *) dev);
|
||||
}
|
||||
} else {
|
||||
sts = 1;
|
||||
}
|
||||
sts = SS$_NORMAL;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Direct.c v1.2 */
|
||||
/* Direct.c v1.3 */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -13,13 +13,11 @@
|
||||
/* This module does all directory file handling - mostly
|
||||
lookups of filenames in directory files... */
|
||||
|
||||
/* This version takes relative version from last seen directory record
|
||||
- this is no good if there are multiple directory records for a file! */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include "ssdef.h"
|
||||
#include "descrip.h"
|
||||
#include "fibdef.h"
|
||||
@@ -27,40 +25,49 @@
|
||||
#include "direct.h"
|
||||
|
||||
#define DEBUGx on
|
||||
#define BLOCKSIZE 512
|
||||
#define MAXREC (BLOCKSIZE - 2)
|
||||
|
||||
|
||||
int directlookups = 0;
|
||||
int directsearches = 0;
|
||||
int directdels = 0;
|
||||
int directchecks = 0;
|
||||
int directmatches = 0;
|
||||
/* Some statistical counters... */
|
||||
|
||||
int direct_lookups = 0;
|
||||
int direct_searches = 0;
|
||||
int direct_deletes = 0;
|
||||
int direct_inserts = 0;
|
||||
int direct_splits = 0;
|
||||
int direct_checks = 0;
|
||||
int direct_matches = 0;
|
||||
|
||||
|
||||
/* directshow - to print directory statistics */
|
||||
/* direct_show - to print directory statistics */
|
||||
|
||||
void directshow(void)
|
||||
void direct_show(void)
|
||||
{
|
||||
printf("DIRECTSHOW Lookups: %d Searches: %d Deletes: %d Checks: %d Matches: %d\n",
|
||||
directlookups,directsearches,directdels,directchecks,directmatches);
|
||||
printf("DIRECT_SHOW Lookups: %d Searches: %d Deletes: %d Inserts: %d Splits: %d\n",
|
||||
direct_lookups,direct_searches,direct_deletes,direct_inserts,direct_splits);
|
||||
}
|
||||
|
||||
|
||||
/* namecheck - take a name specification and return name length without
|
||||
/* name_check() - take a name specification and return name length without
|
||||
the version number, an integer version number, and a wildcard flag */
|
||||
|
||||
unsigned namecheck(char *str,int len,int *retlen,int *retver,int *wildflag)
|
||||
unsigned name_check(char *str,int len,int *retlen,int *retver,int *wildflag)
|
||||
{
|
||||
int wildcard = 0;
|
||||
char *spcbeg = str;
|
||||
char *name_start = str;
|
||||
register int dots = 0;
|
||||
register char *spc = spcbeg;
|
||||
register char *spcend = spc + len;
|
||||
directchecks++;
|
||||
while (spc < spcend) {
|
||||
register char ch = *spc++;
|
||||
register char *name = name_start;
|
||||
register char *name_end = name + len;
|
||||
direct_checks++;
|
||||
|
||||
/* Go through the specification checking for illegal characters */
|
||||
|
||||
while (name < name_end) {
|
||||
register char ch = *name++;
|
||||
if (ch == '.') {
|
||||
if ((spc - spcbeg) > 40) return SS$_BADFILENAME;
|
||||
spcbeg = spc;
|
||||
if ((name - name_start) > 40) return SS$_BADFILENAME;
|
||||
name_start = name;
|
||||
if (dots++ > 1) break;
|
||||
} else {
|
||||
if (ch == ';') {
|
||||
@@ -75,23 +82,26 @@ unsigned namecheck(char *str,int len,int *retlen,int *retver,int *wildflag)
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((spc - spcbeg) > 40) return SS$_BADFILENAME;
|
||||
*retlen = spc - str - 1;
|
||||
if ((name - name_start) > 40) return SS$_BADFILENAME;
|
||||
|
||||
/* Return the name length and start checking the version */
|
||||
|
||||
*retlen = name - str - 1;
|
||||
dots = 0;
|
||||
if (spc < spcend) {
|
||||
register char ch = *spc;
|
||||
if (name < name_end) {
|
||||
register char ch = *name;
|
||||
if (ch == '*') {
|
||||
if (++spc < spcend) return SS$_BADFILENAME;
|
||||
dots = 32768;
|
||||
if (++name < name_end) return SS$_BADFILENAME;
|
||||
dots = 32768; /* Wildcard representation of version! */
|
||||
wildcard = 1;
|
||||
} else {
|
||||
register int sign = 1;
|
||||
if (ch == '-') {
|
||||
spc++;
|
||||
name++;
|
||||
sign = -1;
|
||||
}
|
||||
while (spc < spcend) {
|
||||
ch = *spc++;
|
||||
while (name < name_end) {
|
||||
ch = *name++;
|
||||
if (!isdigit(ch)) return SS$_BADFILENAME;
|
||||
dots = dots * 10 + (ch - '0');
|
||||
}
|
||||
@@ -100,9 +110,6 @@ unsigned namecheck(char *str,int len,int *retlen,int *retver,int *wildflag)
|
||||
}
|
||||
*retver = dots;
|
||||
*wildflag = wildcard;
|
||||
#ifdef DEBUG
|
||||
printf("Namecheck %d %d %d\n",*retlen,*retver,*wildflag);
|
||||
#endif
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
@@ -113,219 +120,386 @@ unsigned namecheck(char *str,int len,int *retlen,int *retver,int *wildflag)
|
||||
#define MAT_GT 2
|
||||
#define MAT_NE 3
|
||||
|
||||
/* namematch - compare a name specification with a directory entry
|
||||
/* name_match() - compare a name specification with a directory entry
|
||||
and determine if there is a match, too big, too small... */
|
||||
|
||||
int namematch(char *spec,int speclen,char *entry,int entrylen)
|
||||
int name_match(char *spec,int spec_len,char *dirent,int dirent_len)
|
||||
{
|
||||
int percent = 0;
|
||||
register char *spc = spec,*ent = entry;
|
||||
register char *spcend = spc + speclen,*entend = ent + entrylen;
|
||||
directmatches++;
|
||||
/* See how much matches without wildcards... */
|
||||
if (spc < spcend && ent < entend) {
|
||||
register int count = speclen;
|
||||
if (entrylen < count) count = entrylen;
|
||||
do {
|
||||
register char sch = *spc,ech = *ent;
|
||||
int percent = MAT_GT;
|
||||
register char *name = spec,*entry = dirent;
|
||||
register char *name_end = name + spec_len,*entry_end = entry + dirent_len;
|
||||
direct_matches++;
|
||||
|
||||
/* See how much name matches without wildcards... */
|
||||
|
||||
while (name < name_end && entry < entry_end) {
|
||||
register char sch = *name;
|
||||
if (sch != '*') {
|
||||
register char ech = *entry;
|
||||
if (sch != ech) if (toupper(sch) != toupper(ech))
|
||||
if (sch == '%') {
|
||||
percent = 1;
|
||||
percent = MAT_NE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
spc++;
|
||||
ent++;
|
||||
} while (--count > 0);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
name++;
|
||||
entry++;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Namematch %3s %d %3s %d\n",spec,speclen,entry,entrylen);
|
||||
#endif
|
||||
|
||||
/* Mismatch - return result unless wildcard... */
|
||||
if (spc >= spcend) {
|
||||
if (ent >= entend) {
|
||||
|
||||
if (name >= name_end) {
|
||||
if (entry >= entry_end) {
|
||||
return MAT_EQ;
|
||||
} else {
|
||||
if (percent) {
|
||||
return MAT_NE;
|
||||
} else {
|
||||
return MAT_GT; /* Entry longer than search spec */
|
||||
}
|
||||
return percent;
|
||||
}
|
||||
} else {
|
||||
register int offset = 0;
|
||||
if (*spc != '*') {
|
||||
if (percent) return MAT_NE;
|
||||
if (ent < entend)
|
||||
if (toupper(*ent) > toupper(*spc)) return MAT_GT;
|
||||
|
||||
/* See if we can find a match with wildcards */
|
||||
|
||||
if (*name != '*') {
|
||||
if (percent == MAT_NE) return MAT_NE;
|
||||
if (entry < entry_end)
|
||||
if (toupper(*entry) > toupper(*name)) return MAT_GT;
|
||||
return MAT_LT;
|
||||
}
|
||||
/* See if we can find a match with wildcards */
|
||||
spc++;
|
||||
if (spc < spcend) {
|
||||
do {
|
||||
if (spc >= spcend) {
|
||||
if (ent >= entend) break;
|
||||
spc -= offset;
|
||||
ent -= offset - 1;
|
||||
offset = 0;
|
||||
} else {
|
||||
register char sch = toupper(*spc);
|
||||
if (sch == '*') {
|
||||
offset = 0;
|
||||
spc++;
|
||||
if (spc >= spcend) break;
|
||||
/* Strip out wildcard(s) - if end then we match! */
|
||||
|
||||
do {
|
||||
name++;
|
||||
} while (name < name_end && *name == '*');
|
||||
if (name >= name_end) return MAT_EQ;
|
||||
|
||||
/* Proceed to examine the specification past the wildcard... */
|
||||
|
||||
while (name < name_end) {
|
||||
register int offset = 1;
|
||||
register char fch = toupper(*name++);
|
||||
|
||||
/* See if can can find a match for the first character... */
|
||||
|
||||
if (fch != '%') {
|
||||
while (entry < entry_end) {
|
||||
if (toupper(*entry) != fch) {
|
||||
entry++;
|
||||
} else {
|
||||
if (ent < entend) {
|
||||
register char ech = toupper(*ent);
|
||||
if (sch == ech || sch == '%') {
|
||||
offset++;
|
||||
spc++;
|
||||
ent++;
|
||||
} else {
|
||||
spc -= offset;
|
||||
ent -= offset - 1;
|
||||
offset = 0;
|
||||
}
|
||||
} else {
|
||||
return MAT_NE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
/* Give up if we can't find that one lousy character... */
|
||||
|
||||
if (entry >= entry_end) return MAT_NE;
|
||||
entry++;
|
||||
|
||||
/* See how much of the rest we can match... */
|
||||
|
||||
while (name < name_end && entry < entry_end) {
|
||||
register char sch = *name,ech;
|
||||
if (sch == '*') break;
|
||||
if (sch != (ech = *entry)) if (toupper(sch) != toupper(ech))
|
||||
if (sch != '%') break;
|
||||
name++;
|
||||
entry++;
|
||||
offset++;
|
||||
}
|
||||
|
||||
/* If matching died because of a wildcard we are OK... */
|
||||
|
||||
if (name < name_end && *name == '*') {
|
||||
do {
|
||||
name++;
|
||||
} while (name < name_end && *name == '*');
|
||||
if (name >= name_end) return MAT_EQ;
|
||||
|
||||
/* Otherwise we finished OK or we need to try again... */
|
||||
|
||||
} else {
|
||||
if (name >= name_end && entry >= entry_end) return MAT_EQ;
|
||||
name -= offset;
|
||||
entry -= offset - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No more specification - match depends on remainder of entry... */
|
||||
|
||||
if (entry < entry_end) return MAT_NE;
|
||||
return MAT_EQ;
|
||||
}
|
||||
|
||||
|
||||
unsigned freesize(char *buffer)
|
||||
{
|
||||
struct dir$rec *dr = (struct dir$rec *) buffer;
|
||||
do {
|
||||
register char *nr = (char *) dr + dr->dir$size + 2;
|
||||
if (nr >= buffer + 512) break;
|
||||
dr = (struct dir$rec *) nr;
|
||||
} while (1);
|
||||
return (char *) dr - buffer - 2;
|
||||
}
|
||||
/* insert_ent() - procedure to add a directory entry at record dr entry de */
|
||||
|
||||
unsigned insrec(void)
|
||||
unsigned insert_ent(struct FCB * fcb,unsigned eofblk,unsigned curblk,
|
||||
struct VIOC * vioc,char *buffer,
|
||||
struct dir$rec * dr,struct dir$ent * de,
|
||||
char *filename,unsigned filelen,
|
||||
unsigned version,struct fiddef * fid)
|
||||
{
|
||||
printf("Insert directory record\n");
|
||||
return 0;
|
||||
}
|
||||
register unsigned sts = 1;
|
||||
register int inuse = 0;
|
||||
|
||||
unsigned insent(struct FCB *fcb,struct VIOC *vioc,unsigned curblk,
|
||||
struct dir$rec *dr,struct dir$ent *de,
|
||||
char *buffer,unsigned eofblk)
|
||||
{
|
||||
printf("Insert directory entry\n");
|
||||
if (freesize(buffer) >= sizeof(struct dir$ent)) {
|
||||
char *ne = (char *) de + sizeof(struct dir$ent);
|
||||
memcpy(de,ne,512 - (ne - buffer));
|
||||
dr->dir$size -= sizeof(struct dir$ent);
|
||||
/* Compute space required... */
|
||||
|
||||
register int addlen = sizeof(struct dir$ent);
|
||||
direct_inserts++;
|
||||
if (de == NULL)
|
||||
addlen += (filelen + sizeof(struct dir$rec)) & ~1;
|
||||
|
||||
/* Compute block space in use ... */
|
||||
|
||||
{
|
||||
char invalid_dr = 1;
|
||||
do {
|
||||
register int sizecheck;
|
||||
register struct dir$rec *nr = (struct dir$rec *) (buffer + inuse);
|
||||
if (dr == nr) invalid_dr = 0;
|
||||
sizecheck = VMSWORD(nr->dir$size);
|
||||
if (sizecheck == 0xffff)
|
||||
break;
|
||||
sizecheck += 2;
|
||||
inuse += sizecheck;
|
||||
sizecheck -= (nr->dir$namecount + sizeof(struct dir$rec)) & ~1;
|
||||
if (inuse > MAXREC || (inuse & 1) || sizecheck <= 0 ||
|
||||
sizecheck % sizeof(struct dir$ent) != 0) {
|
||||
deaccesschunk(vioc,0,0,0);
|
||||
return SS$_BADIRECTORY;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if (invalid_dr) {
|
||||
printf("BUGCHECK invalid dr\n");
|
||||
exit(0);
|
||||
}
|
||||
if (de != NULL) {
|
||||
if (VMSWORD(dr->dir$size) > MAXREC || (char *) de < dr->dir$name +
|
||||
dr->dir$namecount || (char *) de > (char *) dr + VMSWORD(dr->dir$size) + 2) {
|
||||
printf("BUGCHECK invalid de\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* If not enough space free extend the directory... */
|
||||
|
||||
if (addlen > MAXREC - inuse) {
|
||||
register struct dir$rec *nr;
|
||||
unsigned keep_new = 0;
|
||||
char *newbuf;
|
||||
struct VIOC *newvioc;
|
||||
unsigned newblk = eofblk + 1;
|
||||
direct_splits++;
|
||||
printf("Splitting record... %d %d\n",dr,de);
|
||||
if (newblk > fcb->hiblock) {
|
||||
printf("I can't extend a directory yet!!\n");
|
||||
exit(0);
|
||||
}
|
||||
fcb->highwater = 0;
|
||||
sts = accesschunk(fcb,newblk,&newvioc,&newbuf,NULL,1);
|
||||
if (sts & 1) {
|
||||
while (newblk > curblk + 1) {
|
||||
char *frombuf;
|
||||
struct VIOC *fromvioc;
|
||||
sts = accesschunk(fcb,newblk - 1,&fromvioc,&frombuf,NULL,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
memcpy(newbuf,frombuf,BLOCKSIZE);;
|
||||
sts = deaccesschunk(newvioc,newblk,1,1);
|
||||
newvioc = fromvioc;
|
||||
newbuf = frombuf;
|
||||
newblk--;
|
||||
if ((sts & 1) == 0) break;
|
||||
}
|
||||
} else {
|
||||
newvioc = NULL;
|
||||
}
|
||||
if ((sts & 1) == 0) {
|
||||
if (newvioc != NULL) deaccesschunk(newvioc,0,0,0);
|
||||
deaccesschunk(vioc,0,0,0);
|
||||
return sts;
|
||||
}
|
||||
memset(newbuf,0,BLOCKSIZE);
|
||||
eofblk++;
|
||||
fcb->head->fh2$w_recattr.fat$l_efblk = VMSWORD(eofblk + 1);
|
||||
|
||||
/* First find where the next record is... */
|
||||
|
||||
nr = dr;
|
||||
if (VMSWORD(nr->dir$size) <= MAXREC)
|
||||
nr = (struct dir$rec *) ((char *) nr + VMSWORD(nr->dir$size) + 2);
|
||||
|
||||
/* Can we split between records? */
|
||||
|
||||
if (de == NULL || (char *) dr != buffer || VMSWORD(nr->dir$size) <= MAXREC) {
|
||||
register struct dir$rec *sp = dr;
|
||||
if ((char *) dr == buffer && de != NULL) sp = nr;
|
||||
memcpy(newbuf,sp,((buffer + BLOCKSIZE) - (char *) sp));
|
||||
memset(sp,0,((buffer + BLOCKSIZE) - (char *) sp));
|
||||
sp->dir$size = VMSWORD(0xffff);
|
||||
if (sp == dr && (de != NULL || (char *) sp >= buffer + MAXREC - addlen)) {
|
||||
if (de != NULL)
|
||||
de = (struct dir$ent *)
|
||||
(newbuf + ((char *) de - (char *) sp));
|
||||
dr = (struct dir$rec *) (newbuf + ((char *) dr - (char *) sp));
|
||||
keep_new = 1;
|
||||
}
|
||||
/* OK, we have to split the record then.. */
|
||||
|
||||
} else {
|
||||
register unsigned reclen = (dr->dir$namecount +
|
||||
sizeof(struct dir$rec)) & ~1;
|
||||
register struct dir$rec *nbr = (struct dir$rec *) newbuf;
|
||||
printf("Super split %d %d\n",dr,de);
|
||||
memcpy(newbuf,buffer,reclen);
|
||||
memcpy(newbuf + reclen,de,((char *) nr - (char *) de) + 2);
|
||||
nbr->dir$size = VMSWORD(reclen + ((char *) nr - (char *) de) - 2);
|
||||
|
||||
memset((char *) de + 2,0,((char *) nr - (char *) de));
|
||||
((struct dir$rec *) de)->dir$size = VMSWORD(0xffff);
|
||||
dr->dir$size = VMSWORD(((char *) de - (char *) dr) - 2);
|
||||
if ((char *) de >= (char *) nr) {
|
||||
dr = (struct dir$rec *) newbuf;
|
||||
de = (struct dir$ent *) (newbuf + reclen);
|
||||
keep_new = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Need to decide which buffer we are going to keep (to write to) */
|
||||
|
||||
if (keep_new) {
|
||||
sts = deaccesschunk(vioc,curblk,1,1);
|
||||
curblk = newblk;
|
||||
vioc = newvioc;
|
||||
buffer = newbuf;
|
||||
} else {
|
||||
sts = deaccesschunk(newvioc,newblk,1,1);
|
||||
}
|
||||
if ((sts & 1) == 0) printf("Bad status %d\n",sts);
|
||||
}
|
||||
/* After that we can just add the record or entry as appropriate... */
|
||||
|
||||
if (de == NULL) {
|
||||
memmove((char *) dr + addlen,dr,BLOCKSIZE - (((char *) dr + addlen) - buffer));
|
||||
dr->dir$size = VMSWORD(addlen - 2);
|
||||
dr->dir$verlimit = 0;
|
||||
dr->dir$flags = 0;
|
||||
dr->dir$namecount = filelen;
|
||||
memcpy(dr->dir$name,filename,filelen);
|
||||
de = (struct dir$ent *) ((char *) dr + (addlen - sizeof(struct dir$ent)));
|
||||
} else {
|
||||
dr->dir$size = VMSWORD(VMSWORD(dr->dir$size) + addlen);
|
||||
memmove((char *) de + addlen,de,BLOCKSIZE - (((char *) de + addlen) - buffer));
|
||||
}
|
||||
|
||||
/* Write the entry values are we are done! */
|
||||
|
||||
de->dir$version = VMSWORD(version);
|
||||
fid_copy(&de->dir$fid,fid,0);
|
||||
return deaccesschunk(vioc,curblk,1,1);
|
||||
}
|
||||
|
||||
/* delent - delete a directory entry */
|
||||
|
||||
unsigned delent(struct FCB *fcb,struct VIOC *vioc,unsigned curblk,
|
||||
struct dir$rec *dr,struct dir$ent *de,
|
||||
char *buffer,unsigned modmask,unsigned eofblk)
|
||||
/* delete_ent() - delete a directory entry */
|
||||
|
||||
unsigned delete_ent(struct FCB * fcb,struct VIOC * vioc,unsigned curblk,
|
||||
struct dir$rec * dr,struct dir$ent * de,
|
||||
char *buffer,unsigned eofblk)
|
||||
{
|
||||
unsigned sts = 1;
|
||||
unsigned ent;
|
||||
directdels++;
|
||||
ent = (dr->dir$size - sizeof(struct dir$rec)
|
||||
direct_deletes++;
|
||||
ent = (VMSWORD(dr->dir$size) - sizeof(struct dir$rec)
|
||||
- dr->dir$namecount + 3) / sizeof(struct dir$ent);
|
||||
printf("DELENT ent = %d %d %d\n",ent,curblk,eofblk);
|
||||
if (ent > 1) {
|
||||
char *ne = (char *) de + sizeof(struct dir$ent);
|
||||
memcpy(de,ne,512 - (ne - buffer));
|
||||
dr->dir$size -= sizeof(struct dir$ent);
|
||||
memcpy(de,ne,BLOCKSIZE - (ne - buffer));
|
||||
dr->dir$size = VMSWORD(VMSWORD(dr->dir$size) - sizeof(struct dir$ent));
|
||||
} else {
|
||||
char *nr = (char *) dr + dr->dir$size + 2;
|
||||
char *nr = (char *) dr + VMSWORD(dr->dir$size) + 2;
|
||||
if (eofblk == 1 || (char *) dr > buffer ||
|
||||
(nr <= buffer + 510 && (unsigned short) *nr < 512)) {
|
||||
memcpy(dr,nr,512 - (nr - buffer));
|
||||
(nr <= buffer + MAXREC && (unsigned short) *nr < BLOCKSIZE)) {
|
||||
memcpy(dr,nr,BLOCKSIZE - (nr - buffer));
|
||||
} else {
|
||||
printf("DELENT shrinking file size %d %d\n",curblk,eofblk);
|
||||
while (curblk < eofblk) {
|
||||
char *nxtbuffer;
|
||||
struct VIOC *nxtvioc;
|
||||
unsigned nxtmodmask;
|
||||
sts = accesschunk(fcb,++curblk,&nxtvioc,&nxtbuffer,NULL,1,&nxtmodmask);
|
||||
sts = accesschunk(fcb,curblk + 1,&nxtvioc,&nxtbuffer,NULL,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
memcpy(buffer,nxtbuffer,512);
|
||||
sts = deaccesschunk(vioc,modmask,1);
|
||||
memcpy(buffer,nxtbuffer,BLOCKSIZE);
|
||||
sts = deaccesschunk(vioc,curblk++,1,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
buffer = nxtbuffer;
|
||||
vioc = nxtvioc;
|
||||
modmask = nxtmodmask;
|
||||
}
|
||||
if (sts & 1) {
|
||||
fcb->head->fh2$w_recattr.fat$l_efblk[0] = eofblk >> 16;
|
||||
fcb->head->fh2$w_recattr.fat$l_efblk[1] = (eofblk & 0xffff);
|
||||
fcb->head->fh2$w_recattr.fat$l_efblk = VMSSWAP(eofblk);
|
||||
eofblk--;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
unsigned retsts = deaccesschunk(vioc,modmask,1);
|
||||
unsigned retsts = deaccesschunk(vioc,curblk,1,1);
|
||||
if (sts & 1) sts = retsts;
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* retent - return information about a directory entry */
|
||||
/* return_ent() - return information about a directory entry */
|
||||
|
||||
unsigned retent(struct FCB *fcb,struct VIOC *vioc,unsigned curblk,
|
||||
struct dir$rec *dr,struct dir$ent *de,struct fibdef *fib,
|
||||
unsigned short *reslen,struct dsc$descriptor *resdsc,
|
||||
int wildcard)
|
||||
unsigned return_ent(struct FCB * fcb,struct VIOC * vioc,unsigned curblk,
|
||||
struct dir$rec * dr,struct dir$ent * de,struct fibdef * fib,
|
||||
unsigned short *reslen,struct dsc_descriptor * resdsc,
|
||||
int wildcard)
|
||||
{
|
||||
register int scale = 10;
|
||||
register int version = de->dir$version;
|
||||
register int version = VMSWORD(de->dir$version);
|
||||
register int length = dr->dir$namecount;
|
||||
register char *ptr = resdsc->dsc$a_pointer;
|
||||
register char *ptr = resdsc->dsc_a_pointer;
|
||||
register int outlen = resdsc->dsc_w_length;
|
||||
if (length > outlen) length = outlen;
|
||||
memcpy(ptr,dr->dir$name,length);
|
||||
while (version >= scale) scale *= 10;
|
||||
ptr += length++;
|
||||
*ptr++ = ';';
|
||||
do {
|
||||
scale /= 10;
|
||||
*ptr++ = version / scale + '0';
|
||||
version %= scale;
|
||||
ptr += length;
|
||||
if (length < outlen) {
|
||||
*ptr++ = ';';
|
||||
length++;
|
||||
} while (scale > 1);
|
||||
do {
|
||||
if (length >= outlen) break;
|
||||
scale /= 10;
|
||||
*ptr++ = version / scale + '0';
|
||||
version %= scale;
|
||||
length++;
|
||||
} while (scale > 1);
|
||||
}
|
||||
*reslen = length;
|
||||
memcpy(&fib->fib$w_fid_num,&de->dir$fid,sizeof(struct fiddef));
|
||||
fid_copy((struct fiddef *)&fib->fib$w_fid_num,&de->dir$fid,0);
|
||||
if (fib->fib$b_fid_rvn == 0) fib->fib$b_fid_rvn = fcb->rvn;
|
||||
if (wildcard || (fib->fib$w_nmctl & FIB$M_WILD)) {
|
||||
fib->fib$l_wcc = curblk;
|
||||
} else {
|
||||
fib->fib$l_wcc = 0;
|
||||
}
|
||||
return deaccesschunk(vioc,0,1);
|
||||
return deaccesschunk(vioc,0,0,1);
|
||||
}
|
||||
|
||||
|
||||
/* searchent - search for a directory entry */
|
||||
/* search_ent() - search for a directory entry */
|
||||
|
||||
unsigned searchent(struct FCB * fcb,
|
||||
struct dsc$descriptor * fibdsc,struct dsc$descriptor * filedsc,
|
||||
unsigned short *reslen,struct dsc$descriptor * resdsc,unsigned eofblk,unsigned action)
|
||||
unsigned search_ent(struct FCB * fcb,
|
||||
struct dsc_descriptor * fibdsc,struct dsc_descriptor * filedsc,
|
||||
unsigned short *reslen,struct dsc_descriptor * resdsc,unsigned eofblk,unsigned action)
|
||||
{
|
||||
register unsigned sts,curblk;
|
||||
struct VIOC *vioc = NULL;
|
||||
unsigned modmask;
|
||||
char *searchspec,*buffer;
|
||||
int searchlen,version,wildcard,wcc_flag;
|
||||
struct fibdef *fib = (struct fibdef *) fibdsc->dsc$a_pointer;
|
||||
directlookups++;
|
||||
struct fibdef *fib = (struct fibdef *) fibdsc->dsc_a_pointer;
|
||||
direct_lookups++;
|
||||
|
||||
/* 1) Generate start block (wcc gives start point)
|
||||
2) Search for start
|
||||
@@ -333,14 +507,14 @@ unsigned searchent(struct FCB * fcb,
|
||||
|
||||
curblk = fib->fib$l_wcc;
|
||||
if (curblk != 0) {
|
||||
searchspec = resdsc->dsc$a_pointer;
|
||||
sts = namecheck(searchspec,*reslen,&searchlen,&version,&wildcard);
|
||||
if (action || wildcard) return SS$_BADFILENAME;
|
||||
searchspec = resdsc->dsc_a_pointer;
|
||||
sts = name_check(searchspec,*reslen,&searchlen,&version,&wildcard);
|
||||
if (action || wildcard) sts = SS$_BADFILENAME;
|
||||
wcc_flag = 1;
|
||||
} else {
|
||||
searchspec = filedsc->dsc$a_pointer;
|
||||
sts = namecheck(searchspec,filedsc->dsc$w_length,&searchlen,&version,&wildcard);
|
||||
if ((action && wildcard) || (action > 1 && version < 0)) return SS$_BADFILENAME;
|
||||
searchspec = filedsc->dsc_a_pointer;
|
||||
sts = name_check(searchspec,filedsc->dsc_w_length,&searchlen,&version,&wildcard);
|
||||
if ((action && wildcard) || (action > 1 && version < 0)) sts = SS$_BADFILENAME;
|
||||
wcc_flag = 0;
|
||||
}
|
||||
if ((sts & 1) == 0) return sts;
|
||||
@@ -357,35 +531,30 @@ unsigned searchent(struct FCB * fcb,
|
||||
register int cmp;
|
||||
register unsigned newblk;
|
||||
register struct dir$rec *dr;
|
||||
directsearches++;
|
||||
sts = accesschunk(fcb,curblk,&vioc,&buffer,NULL,action ? 1 : 0,&modmask);
|
||||
direct_searches++;
|
||||
sts = accesschunk(fcb,curblk,&vioc,&buffer,NULL,action ? 1 : 0);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
dr = (struct dir$rec *) buffer;
|
||||
if (dr->dir$size > 510) {
|
||||
if (VMSWORD(dr->dir$size) > MAXREC) {
|
||||
cmp = MAT_GT;
|
||||
} else {
|
||||
cmp = namematch(searchspec,searchlen,dr->dir$name,dr->dir$namecount);
|
||||
cmp = name_match(searchspec,searchlen,dr->dir$name,dr->dir$namecount);
|
||||
if (cmp == MAT_EQ) {
|
||||
if (wildcard || version < 1 || version > 32767) {
|
||||
cmp = MAT_NE; /* no match - want to find start */
|
||||
} else {
|
||||
register struct dir$ent *de =
|
||||
(struct dir$ent *) (dr->dir$name + ((dr->dir$namecount + 1) & ~1));
|
||||
if (de->dir$version < version) {
|
||||
if (VMSWORD(de->dir$version) < version) {
|
||||
cmp = MAT_GT; /* too far... */
|
||||
} else {
|
||||
if (de->dir$version > version) {
|
||||
if (VMSWORD(de->dir$version) > version) {
|
||||
cmp = MAT_LT; /* further ahead... */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Direct %6.6s %d %6.6s %d (%d<%d<%d)-> %d\n",
|
||||
searchspec,searchlen,dr->dir$name,dr->dir$namecount,
|
||||
loblk,curblk,hiblk,cmp);
|
||||
#endif
|
||||
switch (cmp) {
|
||||
case MAT_LT:
|
||||
if (curblk == fib->fib$l_wcc) {
|
||||
@@ -404,7 +573,7 @@ unsigned searchent(struct FCB * fcb,
|
||||
newblk = hiblk = loblk = curblk;
|
||||
}
|
||||
if (newblk != curblk) {
|
||||
sts = deaccesschunk(vioc,0,1);
|
||||
sts = deaccesschunk(vioc,0,0,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
vioc = NULL;
|
||||
curblk = newblk;
|
||||
@@ -415,99 +584,154 @@ unsigned searchent(struct FCB * fcb,
|
||||
|
||||
/* Now to read sequentially to find entry... */
|
||||
|
||||
while ((sts & 1) && curblk <= eofblk) {
|
||||
register struct dir$rec *dr;
|
||||
if (vioc == NULL) {
|
||||
sts = accesschunk(fcb,curblk,&vioc,&buffer,NULL,action ? 1 : 0,&modmask);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
}
|
||||
dr = (struct dir$rec *) buffer;
|
||||
do {
|
||||
register int cmp;
|
||||
register char *nr = (char *) dr + dr->dir$size + 2;
|
||||
if (nr >= buffer + 512) break;
|
||||
cmp = namematch(searchspec,searchlen,dr->dir$name,dr->dir$namecount);
|
||||
#ifdef DEBUF
|
||||
printf("Direct %6.6s %d %6.6s %d -> %d\n",
|
||||
searchspec,searchlen,dr->dir$name,dr->dir$namecount,cmp);
|
||||
#endif
|
||||
if (cmp == MAT_GT) {
|
||||
if (wcc_flag) {
|
||||
{
|
||||
char last_name[80];
|
||||
unsigned last_len = 0;
|
||||
register int relver = 0;
|
||||
while ((sts & 1) && curblk <= eofblk) {
|
||||
register struct dir$rec *dr;
|
||||
register int cmp = MAT_LT;
|
||||
|
||||
/* Access a directory block. Reset relative version if it starts
|
||||
with a record we haven't seen before... */
|
||||
|
||||
if (vioc == NULL) {
|
||||
sts = accesschunk(fcb,curblk,&vioc,&buffer,NULL,action ? 1 : 0);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
}
|
||||
dr = (struct dir$rec *) buffer;
|
||||
if (last_len != dr->dir$namecount) {
|
||||
relver = 0;
|
||||
} else {
|
||||
if (name_match(last_name,last_len,dr->dir$name,last_len) != MAT_EQ) {
|
||||
relver = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now loop through the records seeing which match our spec... */
|
||||
|
||||
do {
|
||||
register char *nr = (char *) dr + VMSWORD(dr->dir$size) + 2;
|
||||
if (nr >= buffer + BLOCKSIZE) break;
|
||||
if (dr->dir$name + dr->dir$namecount >= nr) break;
|
||||
cmp = name_match(searchspec,searchlen,dr->dir$name,dr->dir$namecount);
|
||||
if (cmp == MAT_GT && wcc_flag) {
|
||||
wcc_flag = 0;
|
||||
searchspec = filedsc->dsc$a_pointer;
|
||||
sts = namecheck(searchspec,filedsc->dsc$w_length,&searchlen,&version,&wildcard);
|
||||
searchspec = filedsc->dsc_a_pointer;
|
||||
sts = name_check(searchspec,filedsc->dsc_w_length,&searchlen,&version,&wildcard);
|
||||
if ((sts & 1) == 0) break;
|
||||
} else {
|
||||
curblk = eofblk; /* give up */
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cmp == MAT_EQ) {
|
||||
register int relver = 0;
|
||||
register struct dir$ent *de = (struct dir$ent *) (dr->dir$name +
|
||||
((dr->dir$namecount + 1) & ~1));
|
||||
while ((char *) de < nr) {
|
||||
if (version >= de->dir$version || (version < 1 && version >= relver)) {
|
||||
cmp = MAT_GT;
|
||||
if (version > 32767 || version == relver ||
|
||||
version == de->dir$version) cmp = MAT_EQ;
|
||||
if (wcc_flag) {
|
||||
wcc_flag = 0;
|
||||
searchspec = filedsc->dsc$a_pointer;
|
||||
sts = namecheck(searchspec,filedsc->dsc$w_length,&searchlen,&version,&wildcard);
|
||||
if ((sts & 1) == 0) break;
|
||||
if (namematch(searchspec,searchlen,dr->dir$name,
|
||||
dr->dir$namecount) != MAT_EQ) {
|
||||
break;
|
||||
}
|
||||
if (cmp == MAT_EQ) {
|
||||
cmp = MAT_LT;
|
||||
} else {
|
||||
cmp = MAT_LT;
|
||||
if (version >= de->dir$version || (version < 1 && version >= relver)) {
|
||||
cmp = MAT_GT;
|
||||
if (version > 32767 || version == relver ||
|
||||
version == de->dir$version) cmp = MAT_EQ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cmp == MAT_EQ) {
|
||||
switch (action) {
|
||||
case 0:
|
||||
return
|
||||
retent(fcb,vioc,curblk,dr,de,fib,reslen,resdsc,wildcard);
|
||||
case 1:
|
||||
return
|
||||
delent(fcb,vioc,curblk,dr,de,buffer,modmask,eofblk);
|
||||
default:
|
||||
sts = SS$_DUPFILENAME;
|
||||
de = (struct dir$ent *) nr;
|
||||
}
|
||||
} else {
|
||||
if (cmp == MAT_GT) break;
|
||||
if (cmp == MAT_EQ) {
|
||||
register struct dir$ent *de = (struct dir$ent *) (dr->dir$name +
|
||||
((dr->dir$namecount + 1) & ~1));
|
||||
if (version == 0 && action == 2) {
|
||||
version = VMSWORD(de->dir$version) + 1;
|
||||
if (version > 32767) {
|
||||
sts = SS$_BADFILENAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Look at each directory entry to see
|
||||
if it is what we want... */
|
||||
|
||||
if ((char *) dr != buffer) relver = 0;
|
||||
cmp = MAT_LT;
|
||||
while ((char *) de < nr) {
|
||||
if ((version < 1) ? (relver > version) : (version < VMSWORD(de->dir$version))) {
|
||||
relver--;
|
||||
de++;
|
||||
} else {
|
||||
if (version > 32767 || version == relver || version == VMSWORD(de->dir$version)) {
|
||||
cmp = MAT_EQ;
|
||||
} else {
|
||||
cmp = MAT_GT;
|
||||
}
|
||||
if (wcc_flag == 0) {
|
||||
break;
|
||||
} else {
|
||||
wcc_flag = 0;
|
||||
searchspec = filedsc->dsc_a_pointer;
|
||||
sts = name_check(searchspec,filedsc->dsc_w_length,&searchlen,&version,&wildcard);
|
||||
if ((sts & 1) == 0) break;
|
||||
if (name_match(searchspec,searchlen,dr->dir$name,
|
||||
dr->dir$namecount) != MAT_EQ) {
|
||||
cmp = MAT_NE;
|
||||
break;
|
||||
}
|
||||
if (version < 0) {
|
||||
relver = -32768;
|
||||
cmp = MAT_GT;
|
||||
break;
|
||||
}
|
||||
if (cmp == MAT_EQ) {
|
||||
relver--;
|
||||
de++;
|
||||
}
|
||||
cmp = MAT_LT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((sts & 1) == 0) break;
|
||||
|
||||
/* Decide what to do with the entry we have found... */
|
||||
|
||||
if (cmp == MAT_EQ) {
|
||||
switch (action) {
|
||||
case 0:
|
||||
return return_ent(fcb,vioc,curblk,dr,de,fib,reslen,resdsc,wildcard);
|
||||
case 1:
|
||||
return delete_ent(fcb,vioc,curblk,dr,de,buffer,eofblk);
|
||||
default:
|
||||
sts = SS$_DUPFILENAME;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cmp != MAT_NE && action == 2) {
|
||||
return insert_ent(fcb,eofblk,curblk,vioc,buffer,dr,de,
|
||||
searchspec,searchlen,version,(struct fiddef *) & fib->fib$w_fid_num);
|
||||
}
|
||||
}
|
||||
relver--;
|
||||
de++;
|
||||
}
|
||||
if ((sts & 1) == 0) break;
|
||||
if (action == 2) {
|
||||
return insent(fcb,vioc,curblk,dr,de,buffer,eofblk);
|
||||
/* Finish unless we expect more... */
|
||||
|
||||
if (cmp == MAT_GT && wildcard == 0) break;
|
||||
|
||||
/* If this is the last record in the block store the name
|
||||
so that if it continues into the next block we can get
|
||||
the relative version right! Sigh! */
|
||||
|
||||
if (VMSWORD(((struct dir$rec *) nr)->dir$size) > MAXREC) {
|
||||
last_len = dr->dir$namecount;
|
||||
if (last_len > sizeof(last_name)) last_len = sizeof(last_name);
|
||||
memcpy(last_name,dr->dir$name,last_len);
|
||||
dr = (struct dir$rec *) nr;
|
||||
break;
|
||||
}
|
||||
dr = (struct dir$rec *) nr;
|
||||
}
|
||||
dr = (struct dir$rec *) nr;
|
||||
} while (1); /* dr records within block */
|
||||
|
||||
/* We release the buffer ready to get the next one - unless it is the
|
||||
last one in which case we can't defer an insert any longer!! */
|
||||
|
||||
if ((sts & 1) == 0 || action != 2 || (cmp != MAT_GT && curblk < eofblk)) {
|
||||
register unsigned dests = deaccesschunk(vioc,0,0,1);
|
||||
if ((dests & 1) == 0) {
|
||||
sts = dests;
|
||||
break;
|
||||
}
|
||||
vioc = NULL;
|
||||
curblk++;
|
||||
} else {
|
||||
if (version == 0) version = 1;
|
||||
return insert_ent(fcb,eofblk,curblk,vioc,buffer,dr,NULL,
|
||||
searchspec,searchlen,version,(struct fiddef *) & fib->fib$w_fid_num);
|
||||
}
|
||||
} while (1);
|
||||
{
|
||||
register unsigned dests = deaccesschunk(vioc,0,1);
|
||||
vioc = NULL;
|
||||
if (sts & 1) sts = dests;
|
||||
}
|
||||
curblk++;
|
||||
}
|
||||
if (action == 2) {
|
||||
return insrec();
|
||||
} /* curblk blocks within file */
|
||||
}
|
||||
|
||||
/* We achieved nothing! Report the failure... */
|
||||
|
||||
if (sts & 1) {
|
||||
fib->fib$l_wcc = 0;
|
||||
if (wcc_flag || wildcard) {
|
||||
@@ -520,24 +744,24 @@ delent(fcb,vioc,curblk,dr,de,buffer,modmask,eofblk);
|
||||
}
|
||||
|
||||
|
||||
/* direct - this routine handles all directory manipulations:-
|
||||
/* direct() - this routine handles all directory manipulations:-
|
||||
action 0 - find directory entry
|
||||
1 - delete entry
|
||||
2 - create an entry */
|
||||
|
||||
unsigned direct(struct VCB *vcb,struct dsc$descriptor * fibdsc,
|
||||
struct dsc$descriptor *filedsc,unsigned short *reslen,
|
||||
struct dsc$descriptor *resdsc,unsigned action)
|
||||
unsigned direct(struct VCB * vcb,struct dsc_descriptor * fibdsc,
|
||||
struct dsc_descriptor * filedsc,unsigned short *reslen,
|
||||
struct dsc_descriptor * resdsc,unsigned action)
|
||||
{
|
||||
struct FCB *fcb;
|
||||
register unsigned sts,eofblk;
|
||||
register struct fibdef *fib = (struct fibdef *) fibdsc->dsc$a_pointer;
|
||||
register struct fibdef *fib = (struct fibdef *) fibdsc->dsc_a_pointer;
|
||||
sts = accessfile(vcb,(struct fiddef *) & fib->fib$w_did_num,&fcb,action);
|
||||
if (sts & 1) {
|
||||
if (fcb->head->fh2$l_filechar & FH2$M_DIRECTORY) {
|
||||
eofblk = swapw(fcb->head->fh2$w_recattr.fat$l_efblk);
|
||||
if (fcb->head->fh2$w_recattr.fat$w_ffbyte == 0) --eofblk;
|
||||
sts = searchent(fcb,fibdsc,filedsc,reslen,resdsc,eofblk,action);
|
||||
if (VMSLONG(fcb->head->fh2$l_filechar) & FH2$M_DIRECTORY) {
|
||||
eofblk = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_efblk);
|
||||
if (VMSWORD(fcb->head->fh2$w_recattr.fat$w_ffbyte) == 0) --eofblk;
|
||||
sts = search_ent(fcb,fibdsc,filedsc,reslen,resdsc,eofblk,action);
|
||||
} else {
|
||||
sts = SS$_BADIRECTORY;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Direct.h v1.2 Definitions for directory access routines */
|
||||
/* Direct.h v1.3 Definitions for directory access routines */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -13,19 +13,19 @@
|
||||
|
||||
|
||||
struct dir$rec {
|
||||
u_word dir$size;
|
||||
u_word dir$verlimit;
|
||||
u_byte dir$flags;
|
||||
u_byte dir$namecount;
|
||||
vmsword dir$size;
|
||||
vmsword dir$verlimit;
|
||||
vmsbyte dir$flags;
|
||||
vmsbyte dir$namecount;
|
||||
char dir$name[1];
|
||||
};
|
||||
|
||||
struct dir$ent {
|
||||
u_word dir$version;
|
||||
vmsword dir$version;
|
||||
struct fiddef dir$fid;
|
||||
};
|
||||
|
||||
|
||||
unsigned direct(struct VCB *vcb,struct dsc$descriptor * fibdsc,
|
||||
struct dsc$descriptor *filedsc,unsigned short *reslen,
|
||||
struct dsc$descriptor *resdsc,unsigned action);
|
||||
unsigned direct(struct VCB *vcb,struct dsc_descriptor *fibdsc,
|
||||
struct dsc_descriptor *filedsc,unsigned short *reslen,
|
||||
struct dsc_descriptor *resdsc,unsigned action);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Fibdef.h v1.2 Definition of 'struct fibdef' */
|
||||
/* Fibdef.h v1.3 Definition of 'struct fibdef' */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -11,11 +11,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#if defined(VMS) && !defined(__GNUC__)
|
||||
|
||||
#include <fibdef.h>
|
||||
|
||||
#else
|
||||
#ifndef FIM$M_WILD
|
||||
|
||||
#define FIB$M_WILD 0x100
|
||||
|
||||
|
||||
189
extracters/ods2/header.h
Normal file
189
extracters/ods2/header.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/* Header.h v1.0 Definitions for ODS2 file headers */
|
||||
|
||||
/* Small macro to swap words in a longword */
|
||||
|
||||
#define swapw(w) (w[0]<<16 | w[1])
|
||||
|
||||
/* File characteristic definitions */
|
||||
|
||||
#define FCH$M_NOBACKUP 0x2
|
||||
#define FCH$M_CONTIGB 0x20
|
||||
#define FCH$M_LOCKED 0x40
|
||||
#define FCH$M_CONTIG 0x80
|
||||
#define FCH$M_DIRECTORY 0x2000
|
||||
#define FCH$M_MARKDEL 0x8000
|
||||
#define FCH$M_ERASE 0x20000
|
||||
|
||||
/* File and record attribute definitions */
|
||||
|
||||
#define FAT$C_FIXED 0x1
|
||||
#define FAT$C_VARIABLE 0x2
|
||||
#define FAT$C_VFC 0x3
|
||||
#define FAT$C_UNDEFINED 0x0
|
||||
#define FAT$C_STREAM 0x4
|
||||
#define FAT$C_STREAMLF 0x5
|
||||
#define FAT$C_STREAMCR 0x6
|
||||
|
||||
#define FAT$C_DIRECT 0x3
|
||||
#define FAT$C_INDEXED 0x2
|
||||
#define FAT$C_RELATIVE 0x1
|
||||
#define FAT$C_SEQUENTIAL 0x0
|
||||
|
||||
#define FAT$M_FORTRANCC 0x1
|
||||
#define FAT$M_IMPLIEDCC 0x2
|
||||
#define FAT$M_PRINTCC 0x4
|
||||
#define FAT$M_NOSPAN 0x8
|
||||
#define FAT$M_MSBRCW 0x10
|
||||
|
||||
/* Type definitions for basic data types */
|
||||
|
||||
typedef unsigned char u_byte;
|
||||
typedef unsigned short u_word;
|
||||
typedef unsigned int u_long;
|
||||
|
||||
/* Structure of time */
|
||||
|
||||
struct TIME {
|
||||
unsigned char time[8];
|
||||
};
|
||||
|
||||
/* Definition of a UIC */
|
||||
|
||||
struct UIC {
|
||||
u_word uic$w_mem;
|
||||
u_word uic$w_grp;
|
||||
};
|
||||
|
||||
/* Definition for a FID */
|
||||
|
||||
struct fiddef {
|
||||
u_word fid$w_num;
|
||||
u_word fid$w_seq;
|
||||
u_byte fid$b_rvn;
|
||||
u_byte fid$b_nmx;
|
||||
};
|
||||
|
||||
/* RMS record definition */
|
||||
|
||||
struct RECATTR {
|
||||
u_byte fat$b_rtype;
|
||||
u_byte fat$b_rattrib;
|
||||
u_word fat$w_rsize;
|
||||
u_word fat$l_hiblk[2];
|
||||
u_word fat$l_efblk[2];
|
||||
u_word fat$w_ffbyte;
|
||||
u_byte fat$b_bktsize;
|
||||
u_byte fat$b_vfcsize;
|
||||
u_word fat$w_maxrec;
|
||||
u_word fat$w_defext;
|
||||
u_word fat$w_gbc;
|
||||
u_byte fat$_UU0[8];
|
||||
u_word fat$w_versions;
|
||||
};
|
||||
|
||||
/* Layout of the volume home block... */
|
||||
|
||||
struct HOME {
|
||||
u_long hm2$l_homelbn;
|
||||
u_long hm2$l_alhomelbn;
|
||||
u_long hm2$l_altidxlbn;
|
||||
u_word hm2$w_struclev;
|
||||
u_word hm2$w_cluster;
|
||||
u_word hm2$w_homevbn;
|
||||
u_word hm2$w_alhomevbn;
|
||||
u_word hm2$w_altidxvbn;
|
||||
u_word hm2$w_ibmapvbn;
|
||||
u_long hm2$l_ibmaplbn;
|
||||
u_long hm2$l_maxfiles;
|
||||
u_word hm2$w_ibmapsize;
|
||||
u_word hm2$w_resfiles;
|
||||
u_word hm2$w_devtype;
|
||||
u_word hm2$w_rvn;
|
||||
u_word hm2$w_setcount;
|
||||
u_word hm2$w_volchar;
|
||||
struct UIC hm2$w_volowner;
|
||||
u_long hm2$l_reserved1;
|
||||
u_word hm2$w_protect;
|
||||
u_word hm2$w_fileprot;
|
||||
u_word hm2$w_reserved2;
|
||||
u_word hm2$w_checksum1;
|
||||
struct TIME hm2$q_credate;
|
||||
u_byte hm2$b_window;
|
||||
u_byte hm2$b_lru_lim;
|
||||
u_word hm2$w_extend;
|
||||
struct TIME hm2$q_retainmin;
|
||||
struct TIME hm2$q_retainmax;
|
||||
struct TIME hm2$q_revdate;
|
||||
u_byte hm2$r_min_class[20];
|
||||
u_byte hm2$r_max_class[20];
|
||||
u_byte hm2$t_reserved3[320];
|
||||
u_long hm2$l_serialnum;
|
||||
char hm2$t_strucname[12];
|
||||
char hm2$t_volname[12];
|
||||
char hm2$t_ownername[12];
|
||||
char hm2$t_format[12];
|
||||
u_word hm2$w_reserved4;
|
||||
u_word hm2$w_checksum2;
|
||||
};
|
||||
|
||||
/* Structure of the header identification area */
|
||||
|
||||
struct IDENT {
|
||||
char fi2$t_filename[20];
|
||||
u_word fi2$w_revision;
|
||||
struct TIME fi2$q_credate;
|
||||
struct TIME fi2$q_revdate;
|
||||
struct TIME fi2$q_expdate;
|
||||
struct TIME fi2$q_bakdate;
|
||||
char fi2$t_filenamext[66];
|
||||
};
|
||||
|
||||
/* File header layout */
|
||||
|
||||
struct HEAD {
|
||||
u_byte fh2$b_idoffset;
|
||||
u_byte fh2$b_mpoffset;
|
||||
u_byte fh2$b_acoffset;
|
||||
u_byte fh2$b_rsoffset;
|
||||
u_word fh2$w_seg_num;
|
||||
u_word fh2$w_struclev;
|
||||
struct fiddef fh2$w_fid;
|
||||
struct fiddef fh2$w_ext_fid;
|
||||
struct RECATTR fh2$w_recattr;
|
||||
u_long fh2$l_filechar;
|
||||
u_word fh2$w_reserved1;
|
||||
u_byte fh2$b_map_inuse;
|
||||
u_byte fh2$b_acc_mode;
|
||||
struct UIC fh2$l_fileowner;
|
||||
u_word fh2$w_fileprot;
|
||||
struct fiddef fh2$w_backlink;
|
||||
u_byte fh2$b_journal;
|
||||
u_byte fh2$b_ru_active;
|
||||
u_word fh2$w_reserved2;
|
||||
u_long fh2$l_highwater;
|
||||
u_byte fh2$b_reserved3[8];
|
||||
u_byte fh2$r_class_prot[20];
|
||||
u_byte fh2$r_restofit[402];
|
||||
u_word fh2$w_checksum;
|
||||
};
|
||||
|
||||
/* Storage control block layout */
|
||||
|
||||
struct SCB {
|
||||
u_word scb$w_struclev;
|
||||
u_word scb$w_cluster;
|
||||
u_long scb$l_volsize;
|
||||
u_long scb$l_blksize;
|
||||
u_long scb$l_sectors;
|
||||
u_long scb$l_tracks;
|
||||
u_long scb$l_cylinders;
|
||||
u_long scb$l_status;
|
||||
u_long scb$l_status2;
|
||||
u_word scb$w_writecnt;
|
||||
char scb$t_volockname[12];
|
||||
struct TIME scb$q_mounttime;
|
||||
u_word scb$w_backrev;
|
||||
u_long scb$q_genernum[2];
|
||||
char scb$b_reserved[446];
|
||||
u_word scb$w_checksum;
|
||||
};
|
||||
53
extracters/ods2/makefile.nt
Normal file
53
extracters/ods2/makefile.nt
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
CCFLAGS = "-Oxs"
|
||||
|
||||
DEFS = "-DVERSION=\"v1.3\""
|
||||
|
||||
all : ods2
|
||||
|
||||
OBJS = ods2.obj \
|
||||
rms.obj \
|
||||
direct.obj \
|
||||
update.obj \
|
||||
access.obj \
|
||||
device.obj \
|
||||
phynt.obj \
|
||||
cache.obj \
|
||||
vmstime.obj
|
||||
|
||||
ods2 : $(OBJS) wnaspi32.lib
|
||||
$(CC) $(CCFLAGS) -oods2 $(OBJS) wnaspi32.lib
|
||||
|
||||
vmstime.obj : vmstime.c vmstime.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) vmstime.c
|
||||
|
||||
cache.obj : cache.c cache.h ssdef.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) cache.c
|
||||
|
||||
phynt.obj : phynt.c phyio.h ssdef.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) phynt.c
|
||||
|
||||
device.obj : device.c ssdef.h access.h phyio.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) device.c
|
||||
|
||||
access.obj : access.c ssdef.h access.h phyio.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) access.c
|
||||
|
||||
update.obj : update.c ssdef.h access.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) update.c
|
||||
|
||||
direct.obj : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) direct.c
|
||||
|
||||
rms.obj : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) rms.c
|
||||
|
||||
ods2.obj : ods2.c ssdef.h descrip.h access.h rms.h
|
||||
$(CC) -c $(CCFLAGS) $(DEFS) ods2.c
|
||||
|
||||
wnaspi32.lib : wnaspi32.def
|
||||
LIB /DEF:WNASPI32.DEF /MACHINE:IX86
|
||||
|
||||
clean:
|
||||
del *.obj
|
||||
del *.exe
|
||||
36
extracters/ods2/makefile.solaris
Normal file
36
extracters/ods2/makefile.solaris
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
CCFLAGS = "-g"
|
||||
|
||||
DEFS = "-DVERSION=\"v1.3\""
|
||||
|
||||
all : ods2
|
||||
|
||||
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
gcc $(CCFLAGS) -oods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
|
||||
vmstime.o : vmstime.c vmstime.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) vmstime.c
|
||||
|
||||
cache.o : cache.c cache.h ssdef.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) cache.c
|
||||
|
||||
phyunix.o : phyunix.c phyio.h ssdef.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) phyunix.c
|
||||
|
||||
device.o : device.c ssdef.h access.h phyio.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) device.c
|
||||
|
||||
access.o : access.c ssdef.h access.h phyio.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) access.c
|
||||
|
||||
update.o : update.c ssdef.h access.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) update.c
|
||||
|
||||
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) direct.c
|
||||
|
||||
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) rms.c
|
||||
|
||||
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
|
||||
gcc -c $(CCFLAGS) $(DEFS) ods2.c
|
||||
34
extracters/ods2/makefile.tru64
Normal file
34
extracters/ods2/makefile.tru64
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
CCFLAGS = "-g"
|
||||
|
||||
all : ods2
|
||||
|
||||
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
cc $(CCFLAGS) -o ods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
|
||||
vmstime.o : vmstime.c vmstime.h
|
||||
cc -c $(CCFLAGS) $(DEFS) vmstime.c
|
||||
|
||||
cache.o : cache.c cache.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) cache.c
|
||||
|
||||
phyunix.o : phyunix.c phyio.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) phyunix.c
|
||||
|
||||
device.o : device.c ssdef.h access.h phyio.h
|
||||
cc -c $(CCFLAGS) $(DEFS) device.c
|
||||
|
||||
access.o : access.c ssdef.h access.h phyio.h
|
||||
cc -c $(CCFLAGS) $(DEFS) access.c
|
||||
|
||||
update.o : update.c ssdef.h access.h
|
||||
cc -c $(CCFLAGS) $(DEFS) update.c
|
||||
|
||||
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) direct.c
|
||||
|
||||
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) rms.c
|
||||
|
||||
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
|
||||
cc -c $(CCFLAGS) $(DEFS) ods2.c
|
||||
36
extracters/ods2/makefile.unix
Normal file
36
extracters/ods2/makefile.unix
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
CCFLAGS = "-g"
|
||||
|
||||
DEFS = "-DVERSION=\"v1.3\""
|
||||
|
||||
all : ods2
|
||||
|
||||
ods2 : ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
cc $(CCFLAGS) -oods2 ods2.o rms.o direct.o update.o access.o device.o phyunix.o cache.o vmstime.o
|
||||
|
||||
vmstime.o : vmstime.c vmstime.h
|
||||
cc -c $(CCFLAGS) $(DEFS) vmstime.c
|
||||
|
||||
cache.o : cache.c cache.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) cache.c
|
||||
|
||||
phyunix.o : phyunix.c phyio.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) phyunix.c
|
||||
|
||||
device.o : device.c ssdef.h access.h phyio.h
|
||||
cc -c $(CCFLAGS) $(DEFS) device.c
|
||||
|
||||
access.o : access.c ssdef.h access.h phyio.h
|
||||
cc -c $(CCFLAGS) $(DEFS) access.c
|
||||
|
||||
update.o : update.c ssdef.h access.h
|
||||
cc -c $(CCFLAGS) $(DEFS) update.c
|
||||
|
||||
direct.o : direct.c direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) direct.c
|
||||
|
||||
rms.o : rms.c rms.h direct.h access.h fibdef.h descrip.h ssdef.h
|
||||
cc -c $(CCFLAGS) $(DEFS) rms.c
|
||||
|
||||
ods2.o : ods2.c ssdef.h descrip.h access.h rms.h
|
||||
cc -c $(CCFLAGS) $(DEFS) ods2.c
|
||||
3
extracters/ods2/memory.h
Normal file
3
extracters/ods2/memory.h
Normal file
@@ -0,0 +1,3 @@
|
||||
/*
|
||||
* Empty placeholder file for VAX C, which doesn't have (or need) <memory.h>
|
||||
*/
|
||||
@@ -1,4 +1,7 @@
|
||||
/* ODS2.C v1.2 Mainline ODS2 program */
|
||||
#define MODULE_NAME ODS2
|
||||
#define MODULE_IDENT "V1.3"
|
||||
|
||||
/* Ods2.c v1.3 Mainline ODS2 program */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -32,6 +35,15 @@
|
||||
access.c,device.c,cache.c,phyos2.c,vmstime.c
|
||||
*/
|
||||
|
||||
/* Modified by:
|
||||
*
|
||||
* 31-AUG-2001 01:04 Hunter Goatley <goathunter@goatley.com>
|
||||
*
|
||||
* For VMS, added routine getcmd() to read commands with full
|
||||
* command recall capabilities.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This version will compile and run using normal VMS I/O by
|
||||
defining VMSIO
|
||||
*/
|
||||
@@ -46,6 +58,16 @@
|
||||
(sorry! - could be easily fixed though!)
|
||||
*/
|
||||
|
||||
#ifdef VMS
|
||||
#ifdef __DECC
|
||||
#pragma module MODULE_NAME MODULE_IDENT
|
||||
#else
|
||||
#ifdef vaxc
|
||||
#module MODULE_NAME MODULE_IDENT
|
||||
#endif /* vaxc */
|
||||
#endif /* __DECC */
|
||||
#endif /* VMS */
|
||||
|
||||
#define DEBUGx on
|
||||
#define VMSIOx on
|
||||
|
||||
@@ -53,18 +75,37 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "descrip.h"
|
||||
#include "ssdef.h"
|
||||
|
||||
|
||||
#ifdef VMSIO
|
||||
#include <ssdef.h>
|
||||
#include <descrip.h>
|
||||
#include <starlet.h>
|
||||
#include <rms.h>
|
||||
unsigned sys$setddir();
|
||||
#else
|
||||
#include "rms.h"
|
||||
#include "access.h"
|
||||
#endif
|
||||
#include <fiddef.h>
|
||||
#define sys_parse sys$parse
|
||||
#define sys_search sys$search
|
||||
#define sys_open sys$open
|
||||
#define sys_close sys$close
|
||||
#define sys_connect sys$connect
|
||||
#define sys_disconnect sys$disconnect
|
||||
#define sys_get sys$get
|
||||
#define sys_put sys$put
|
||||
#define sys_create sys$create
|
||||
#define sys_erase sys$erase
|
||||
#define sys_extend sys$extend
|
||||
#define sys_asctim sys$asctim
|
||||
#define sys_setddir sys$setddir
|
||||
#define dsc_descriptor dsc$descriptor
|
||||
#define dsc_w_length dsc$w_length
|
||||
#define dsc_a_pointer dsc$a_pointer
|
||||
|
||||
#else
|
||||
#include "ssdef.h"
|
||||
#include "descrip.h"
|
||||
#include "access.h"
|
||||
#include "rms.h"
|
||||
#endif
|
||||
|
||||
#define PRINT_ATTR (FAB$M_CR | FAB$M_PRN | FAB$M_FTN)
|
||||
|
||||
@@ -125,7 +166,7 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
||||
fab.fab$l_dna = "*.*;*";
|
||||
fab.fab$b_dns = strlen(fab.fab$l_dna);
|
||||
options = checkquals(dirquals,qualc,qualv);
|
||||
sts = sys$parse(&fab);
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & 1) {
|
||||
char dir[NAM$C_MAXRSS + 1];
|
||||
int namelen;
|
||||
@@ -140,7 +181,7 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
||||
nam.nam$l_rsa = rsa;
|
||||
nam.nam$b_rss = NAM$C_MAXRSS;
|
||||
fab.fab$l_fop = FAB$M_NAM;
|
||||
while ((sts = sys$search(&fab)) & 1) {
|
||||
while ((sts = sys_search(&fab)) & 1) {
|
||||
if (dirlen != nam.nam$b_dev + nam.nam$b_dir ||
|
||||
memcmp(rsa,dir,nam.nam$b_dev + nam.nam$b_dir) != 0) {
|
||||
if (dirfiles > 0) {
|
||||
@@ -184,11 +225,11 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
||||
} else {
|
||||
printf("%-19s",rsa + dirlen);
|
||||
}
|
||||
sts = sys$open(&fab);
|
||||
sts = sys_open(&fab);
|
||||
if ((sts & 1) == 0) {
|
||||
printf("Open error: %d\n",sts);
|
||||
} else {
|
||||
sts = sys$close(&fab);
|
||||
sts = sys_close(&fab);
|
||||
if (options & 2) {
|
||||
char fileid[100];
|
||||
sprintf(fileid,"(%d,%d,%d)",
|
||||
@@ -204,10 +245,10 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
||||
}
|
||||
if (options & 1) {
|
||||
char tim[24];
|
||||
struct dsc$descriptor timdsc;
|
||||
timdsc.dsc$w_length = 23;
|
||||
timdsc.dsc$a_pointer = tim;
|
||||
sts = sys$asctim(0,&timdsc,&dat.xab$q_cdt,0);
|
||||
struct dsc_descriptor timdsc;
|
||||
timdsc.dsc_w_length = 23;
|
||||
timdsc.dsc_a_pointer = tim;
|
||||
sts = sys_asctim(0,&timdsc,dat.xab$q_cdt,0);
|
||||
if ((sts & 1) == 0) printf("Asctim error: %d\n",sts);
|
||||
tim[23] = '\0';
|
||||
printf(" %s",tim);
|
||||
@@ -253,9 +294,11 @@ unsigned dir(int argc,char *argv[],int qualc,char *qualv[])
|
||||
|
||||
#define MAXREC 32767
|
||||
|
||||
char *copyquals[] = {"binary",NULL};
|
||||
|
||||
unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
int sts;
|
||||
int sts,options;
|
||||
struct NAM nam = cc$rms_nam;
|
||||
struct FAB fab = cc$rms_fab;
|
||||
char res[NAM$C_MAXRSS + 1],rsa[NAM$C_MAXRSS + 1];
|
||||
@@ -265,20 +308,21 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
fab.fab$l_nam = &nam;
|
||||
fab.fab$l_fna = argv[1];
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
sts = sys$parse(&fab);
|
||||
options = checkquals(copyquals,qualc,qualv);
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & 1) {
|
||||
nam.nam$l_rsa = rsa;
|
||||
nam.nam$b_rss = NAM$C_MAXRSS;
|
||||
fab.fab$l_fop = FAB$M_NAM;
|
||||
while ((sts = sys$search(&fab)) & 1) {
|
||||
sts = sys$open(&fab);
|
||||
while ((sts = sys_search(&fab)) & 1) {
|
||||
sts = sys_open(&fab);
|
||||
if ((sts & 1) == 0) {
|
||||
printf("%%COPY-F-OPENFAIL, Open error: %d\n",sts);
|
||||
perror("-COPY-F-ERR ");
|
||||
} else {
|
||||
struct RAB rab = cc$rms_rab;
|
||||
rab.rab$l_fab = &fab;
|
||||
if ((sts = sys$connect(&rab)) & 1) {
|
||||
if ((sts = sys_connect(&rab)) & 1) {
|
||||
FILE *tof;
|
||||
char name[NAM$C_MAXRSS + 1];
|
||||
unsigned records = 0;
|
||||
@@ -308,7 +352,15 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
}
|
||||
*out++ = '\0';
|
||||
}
|
||||
#ifndef _WIN32
|
||||
tof = fopen(name,"w");
|
||||
#else
|
||||
if ((options & 1) == 0 && fab.fab$b_rat & PRINT_ATTR) {
|
||||
tof = fopen(name,"w");
|
||||
} else {
|
||||
tof = fopen(name,"wb");
|
||||
}
|
||||
#endif
|
||||
if (tof == NULL) {
|
||||
printf("%%COPY-F-OPENOUT, Could not open %s\n",name);
|
||||
perror("-COPY-F-ERR ");
|
||||
@@ -317,9 +369,10 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
filecount++;
|
||||
rab.rab$l_ubf = rec;
|
||||
rab.rab$w_usz = MAXREC;
|
||||
while ((sts = sys$get(&rab)) & 1) {
|
||||
while ((sts = sys_get(&rab)) & 1) {
|
||||
unsigned rsz = rab.rab$w_rsz;
|
||||
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
|
||||
if ((options & 1) == 0 &&
|
||||
fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
|
||||
if (fwrite(rec,rsz,1,tof) == 1) {
|
||||
records++;
|
||||
} else {
|
||||
@@ -333,15 +386,17 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
perror("-COPY-F-ERR ");
|
||||
}
|
||||
}
|
||||
sys$disconnect(&rab);
|
||||
sys_disconnect(&rab);
|
||||
rsa[nam.nam$b_rsl] = '\0';
|
||||
if (sts == RMS$_EOF) {
|
||||
rsa[nam.nam$b_rsl] = '\0';
|
||||
printf("%%COPY-S-COPIED, %s copied to %s (%d record%s)\n",
|
||||
rsa,name,records,(records == 1 ? "" : "s"));
|
||||
} else {
|
||||
printf("%%COPY-F-ERROR Status: %d for %s\n",sts,rsa);
|
||||
sts = 1;
|
||||
}
|
||||
}
|
||||
sys$close(&fab);
|
||||
sys_close(&fab);
|
||||
}
|
||||
}
|
||||
if (sts == RMS$_NMF) sts = 1;
|
||||
@@ -355,6 +410,44 @@ unsigned copy(int argc,char *argv[],int qualc,char *qualv[])
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* import: a file copy routine */
|
||||
|
||||
|
||||
unsigned import(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
int sts;
|
||||
FILE *fromf;
|
||||
fromf = fopen(argv[1],"r");
|
||||
if (fromf != NULL) {
|
||||
struct FAB fab = cc$rms_fab;
|
||||
fab.fab$l_fna = argv[2];
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
if ((sts = sys_create(&fab)) & 1) {
|
||||
struct RAB rab = cc$rms_rab;
|
||||
rab.rab$l_fab = &fab;
|
||||
if ((sts = sys_connect(&rab)) & 1) {
|
||||
char rec[MAXREC + 2];
|
||||
rab.rab$l_rbf = rec;
|
||||
rab.rab$w_usz = MAXREC;
|
||||
while (fgets(rec,sizeof(rec),fromf) != NULL) {
|
||||
rab.rab$w_rsz = strlen(rec);
|
||||
sts = sys_put(&rab);
|
||||
if ((sts & 1) == 0) break;
|
||||
}
|
||||
sys_disconnect(&rab);
|
||||
}
|
||||
sys_close(&fab);
|
||||
}
|
||||
fclose(fromf);
|
||||
if (!(sts & 1)) {
|
||||
printf("%%IMPORT-F-ERROR Status: %d\n",sts);
|
||||
}
|
||||
} else {
|
||||
printf("Can't open %s\n",argv[1]);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/* diff: a simple file difference routine */
|
||||
|
||||
@@ -371,14 +464,14 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
|
||||
printf("Could not open file %s\n",argv[1]);
|
||||
sts = 0;
|
||||
} else {
|
||||
if ((sts = sys$open(&fab)) & 1) {
|
||||
if ((sts = sys_open(&fab)) & 1) {
|
||||
struct RAB rab = cc$rms_rab;
|
||||
rab.rab$l_fab = &fab;
|
||||
if ((sts = sys$connect(&rab)) & 1) {
|
||||
if ((sts = sys_connect(&rab)) & 1) {
|
||||
char rec[MAXREC + 2],cpy[MAXREC + 1];
|
||||
rab.rab$l_ubf = rec;
|
||||
rab.rab$w_usz = MAXREC;
|
||||
while ((sts = sys$get(&rab)) & 1) {
|
||||
while ((sts = sys_get(&rab)) & 1) {
|
||||
strcpy(rec + rab.rab$w_rsz,"\n");
|
||||
fgets(cpy,MAXREC,tof);
|
||||
if (strcmp(rec,cpy) != 0) {
|
||||
@@ -389,9 +482,9 @@ unsigned diff(int argc,char *argv[],int qualc,char *qualv[])
|
||||
records++;
|
||||
}
|
||||
}
|
||||
sys$disconnect(&rab);
|
||||
sys_disconnect(&rab);
|
||||
}
|
||||
sys$close(&fab);
|
||||
sys_close(&fab);
|
||||
}
|
||||
fclose(tof);
|
||||
if (sts == RMS$_EOF) sts = 1;
|
||||
@@ -414,23 +507,23 @@ unsigned typ(int argc,char *argv[],int qualc,char *qualv[])
|
||||
struct FAB fab = cc$rms_fab;
|
||||
fab.fab$l_fna = argv[1];
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
if ((sts = sys$open(&fab)) & 1) {
|
||||
if ((sts = sys_open(&fab)) & 1) {
|
||||
struct RAB rab = cc$rms_rab;
|
||||
rab.rab$l_fab = &fab;
|
||||
if ((sts = sys$connect(&rab)) & 1) {
|
||||
if ((sts = sys_connect(&rab)) & 1) {
|
||||
char rec[MAXREC + 2];
|
||||
rab.rab$l_ubf = rec;
|
||||
rab.rab$w_usz = MAXREC;
|
||||
while ((sts = sys$get(&rab)) & 1) {
|
||||
while ((sts = sys_get(&rab)) & 1) {
|
||||
unsigned rsz = rab.rab$w_rsz;
|
||||
if (fab.fab$b_rat & PRINT_ATTR) rec[rsz++] = '\n';
|
||||
rec[rsz++] = '\0';
|
||||
fputs(rec,stdout);
|
||||
records++;
|
||||
}
|
||||
sys$disconnect(&rab);
|
||||
sys_disconnect(&rab);
|
||||
}
|
||||
sys$close(&fab);
|
||||
sys_close(&fab);
|
||||
if (sts == RMS$_EOF) sts = 1;
|
||||
}
|
||||
if ((sts & 1) == 0) {
|
||||
@@ -470,25 +563,25 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
fab.fab$l_dna = "";
|
||||
fab.fab$b_dns = strlen(fab.fab$l_dna);
|
||||
sts = sys$parse(&fab);
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & 1) {
|
||||
nam.nam$l_rsa = rsa;
|
||||
nam.nam$b_rss = NAM$C_MAXRSS;
|
||||
fab.fab$l_fop = FAB$M_NAM;
|
||||
while ((sts = sys$search(&fab)) & 1) {
|
||||
sts = sys$open(&fab);
|
||||
while ((sts = sys_search(&fab)) & 1) {
|
||||
sts = sys_open(&fab);
|
||||
if ((sts & 1) == 0) {
|
||||
printf("%%SEARCH-F-OPENFAIL, Open error: %d\n",sts);
|
||||
} else {
|
||||
struct RAB rab = cc$rms_rab;
|
||||
rab.rab$l_fab = &fab;
|
||||
if ((sts = sys$connect(&rab)) & 1) {
|
||||
if ((sts = sys_connect(&rab)) & 1) {
|
||||
int printname = 1;
|
||||
char rec[MAXREC + 2];
|
||||
filecount++;
|
||||
rab.rab$l_ubf = rec;
|
||||
rab.rab$w_usz = MAXREC;
|
||||
while ((sts = sys$get(&rab)) & 1) {
|
||||
while ((sts = sys_get(&rab)) & 1) {
|
||||
register char *strng = rec;
|
||||
register char *strngend = strng + (rab.rab$w_rsz - (searend - searstr));
|
||||
while (strng < strngend) {
|
||||
@@ -517,13 +610,13 @@ unsigned search(int argc,char *argv[],int qualc,char *qualv[])
|
||||
}
|
||||
}
|
||||
}
|
||||
sys$disconnect(&rab);
|
||||
sys_disconnect(&rab);
|
||||
}
|
||||
if (sts == SS$_NOTINSTALL) {
|
||||
printf("%%SEARCH-W-NOIMPLEM, file operation not implemented\n");
|
||||
sts = 1;
|
||||
}
|
||||
sys$close(&fab);
|
||||
sys_close(&fab);
|
||||
}
|
||||
}
|
||||
if (sts == RMS$_NMF || sts == RMS$_FNF) sts = 1;
|
||||
@@ -555,8 +648,7 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
|
||||
fab.fab$l_nam = &nam;
|
||||
fab.fab$l_fna = argv[1];
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
printf("WARNING! This bit is broken - volume corruption VERY likely!\n");
|
||||
sts = sys$parse(&fab);
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & 1) {
|
||||
if (nam.nam$b_ver < 2) {
|
||||
printf("%%DELETE-F-NOVER, you must specify a version!!\n");
|
||||
@@ -564,8 +656,8 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
|
||||
nam.nam$l_rsa = rsa;
|
||||
nam.nam$b_rss = NAM$C_MAXRSS;
|
||||
fab.fab$l_fop = FAB$M_NAM;
|
||||
while ((sts = sys$search(&fab)) & 1) {
|
||||
sts = sys$erase(&fab);
|
||||
while ((sts = sys_search(&fab)) & 1) {
|
||||
sts = sys_erase(&fab);
|
||||
if ((sts & 1) == 0) {
|
||||
printf("%%DELETE-F-DELERR, Delete error: %d\n",sts);
|
||||
} else {
|
||||
@@ -587,6 +679,40 @@ unsigned del(int argc,char *argv[],int qualc,char *qualv[])
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* test: you don't want to know! */
|
||||
struct VCB *test_vcb;
|
||||
|
||||
unsigned test(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
int sts = 0;
|
||||
struct fiddef fid;
|
||||
sts = update_create(test_vcb,NULL,"Test.File",&fid,NULL);
|
||||
printf("Test status of %d (%s)\n",sts,argv[1]);
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* more test code... */
|
||||
|
||||
unsigned extend(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
int sts;
|
||||
struct FAB fab = cc$rms_fab;
|
||||
fab.fab$l_fna = argv[1];
|
||||
fab.fab$b_fns = strlen(fab.fab$l_fna);
|
||||
fab.fab$b_fac = FAB$M_UPD;
|
||||
if ((sts = sys_open(&fab)) & 1) {
|
||||
fab.fab$l_alq = 32;
|
||||
sts = sys_extend(&fab);
|
||||
sys_close(&fab);
|
||||
}
|
||||
if ((sts & 1) == 0) {
|
||||
printf("%%EXTEND-F-ERROR Status: %d\n",sts);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* show: the show command */
|
||||
|
||||
@@ -596,10 +722,10 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[])
|
||||
if (keycomp(argv[1],"default")) {
|
||||
unsigned short curlen;
|
||||
char curdir[NAM$C_MAXRSS + 1];
|
||||
struct dsc$descriptor curdsc;
|
||||
curdsc.dsc$w_length = NAM$C_MAXRSS;
|
||||
curdsc.dsc$a_pointer = curdir;
|
||||
if ((sts = sys$setddir(NULL,&curlen,&curdsc)) & 1) {
|
||||
struct dsc_descriptor curdsc;
|
||||
curdsc.dsc_w_length = NAM$C_MAXRSS;
|
||||
curdsc.dsc_a_pointer = curdir;
|
||||
if ((sts = sys_setddir(NULL,&curlen,&curdsc)) & 1) {
|
||||
curdir[curlen] = '\0';
|
||||
printf(" %s\n",curdir);
|
||||
} else {
|
||||
@@ -607,14 +733,19 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[])
|
||||
}
|
||||
} else {
|
||||
if (keycomp(argv[1],"time")) {
|
||||
unsigned sts;
|
||||
char timstr[24];
|
||||
unsigned short timlen;
|
||||
struct dsc$descriptor timdsc;
|
||||
timdsc.dsc$w_length = 23;
|
||||
timdsc.dsc$a_pointer = timstr;
|
||||
sys$asctim(&timlen,&timdsc,NULL,0);
|
||||
timstr[timlen] = '\0';
|
||||
printf(" %s\n",timstr);
|
||||
struct dsc_descriptor timdsc;
|
||||
timdsc.dsc_w_length = 20;
|
||||
timdsc.dsc_a_pointer = timstr;
|
||||
sts = sys_asctim(&timlen,&timdsc,NULL,0);
|
||||
if (sts & 1) {
|
||||
timstr[timlen] = '\0';
|
||||
printf(" %s\n",timstr);
|
||||
} else {
|
||||
printf("%%SHOW-W-TIMERR error %d\n",sts);
|
||||
}
|
||||
} else {
|
||||
printf("%%SHOW-W-WHAT '%s'?\n",argv[1]);
|
||||
}
|
||||
@@ -622,18 +753,28 @@ unsigned show(int argc,char *argv[],int qualc,char *qualv[])
|
||||
return sts;
|
||||
}
|
||||
|
||||
unsigned setdef_count = 0;
|
||||
|
||||
void setdef(char *newdef)
|
||||
{
|
||||
register unsigned sts;
|
||||
struct dsc_descriptor defdsc;
|
||||
defdsc.dsc_a_pointer = newdef;
|
||||
defdsc.dsc_w_length = strlen(defdsc.dsc_a_pointer);
|
||||
if ((sts = sys_setddir(&defdsc,NULL,NULL)) & 1) {
|
||||
setdef_count++;
|
||||
} else {
|
||||
printf("Error %d setting default to %s\n",sts,newdef);
|
||||
}
|
||||
}
|
||||
|
||||
/* set: the set command */
|
||||
|
||||
unsigned set(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
unsigned sts = 1;
|
||||
if (keycomp(argv[1],"default")) {
|
||||
struct dsc$descriptor defdsc;
|
||||
defdsc.dsc$a_pointer = argv[2];
|
||||
defdsc.dsc$w_length = strlen(defdsc.dsc$a_pointer);
|
||||
if (((sts = sys$setddir(&defdsc,NULL,NULL)) & 1) == 0) {
|
||||
printf("Error %d setting default to %s\n",sts,argv[2]);
|
||||
}
|
||||
setdef(argv[2]);
|
||||
} else {
|
||||
printf("%%SET-W-WHAT '%s'?\n",argv[1]);
|
||||
}
|
||||
@@ -660,6 +801,8 @@ unsigned dodismount(int argc,char *argv[],int qualc,char *qualv[])
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *mouquals[] = {"write",NULL};
|
||||
|
||||
unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
|
||||
@@ -697,6 +840,15 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
|
||||
if (vcb->vcbdev[i].dev != NULL)
|
||||
printf("%%MOUNT-I-MOUNTED, Volume %12.12s mounted on %s\n",
|
||||
vcb->vcbdev[i].home.hm2$t_volname,vcb->vcbdev[i].dev->devnam);
|
||||
if (setdef_count == 0) {
|
||||
char *colon,defdir[256];
|
||||
strcpy(defdir,vcb->vcbdev[0].dev->devnam);
|
||||
colon = strchr(defdir,':');
|
||||
if (colon != NULL) *colon = '\0';
|
||||
strcpy(defdir + strlen(defdir),":[000000]");
|
||||
setdef(defdir);
|
||||
test_vcb = vcb;
|
||||
}
|
||||
} else {
|
||||
printf("Mount failed with %d\n",sts);
|
||||
}
|
||||
@@ -705,7 +857,7 @@ unsigned domount(int argc,char *argv[],int qualc,char *qualv[])
|
||||
}
|
||||
|
||||
|
||||
void directshow(void);
|
||||
void direct_show(void);
|
||||
void phyio_show(void);
|
||||
|
||||
/* statis: print some simple statistics */
|
||||
@@ -713,20 +865,12 @@ void phyio_show(void);
|
||||
unsigned statis(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
printf("Statistics:-\n");
|
||||
directshow();
|
||||
cacheshow();
|
||||
direct_show();
|
||||
cache_show();
|
||||
phyio_show();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* dump: a simple debugging aid */
|
||||
|
||||
unsigned dump(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
printf("Cache Dump:-\n");
|
||||
cachedump();
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -734,14 +878,14 @@ unsigned dump(int argc,char *argv[],int qualc,char *qualv[])
|
||||
|
||||
unsigned help(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
printf("\nODS2 v1.2\n");
|
||||
printf("\nODS2 %s\n", MODULE_IDENT);
|
||||
printf(" Please send problems/comments to Paulnank@au1.ibm.com\n");
|
||||
printf(" Commands are:\n");
|
||||
printf(" copy difference directory exit\n");
|
||||
printf(" mount show_default show_time search\n");
|
||||
printf(" set_default type\n");
|
||||
printf(" Example:-\n $ mount e:\n");
|
||||
printf(" $ search e:[vms$common.decc*...]*.h rms$_wld\n");
|
||||
printf(" $ search e:[vms_common.decc*...]*.h rms$_wld\n");
|
||||
printf(" $ set default e:[sys0.sysmgr]\n");
|
||||
printf(" $ copy *.com;-1 c:\\*.*\n");
|
||||
printf(" $ directory/file/size/date [-.sys*...].%%\n");
|
||||
@@ -755,13 +899,16 @@ unsigned help(int argc,char *argv[],int qualc,char *qualv[])
|
||||
struct CMDSET {
|
||||
char *name;
|
||||
unsigned (*proc) (int argc,char *argv[],int qualc,char *qualv[]);
|
||||
unsigned int minlen;
|
||||
unsigned int minargs;
|
||||
unsigned int maxargs;
|
||||
unsigned int maxquals;
|
||||
int minlen;
|
||||
int minargs;
|
||||
int maxargs;
|
||||
int maxquals;
|
||||
} cmdset[] = {
|
||||
{
|
||||
"copy",copy,3,3,3,0
|
||||
"copy",copy,3,3,3,1
|
||||
},
|
||||
{
|
||||
"import",import,3,3,3,0
|
||||
},
|
||||
{
|
||||
"delete",del,3,2,2,0
|
||||
@@ -774,9 +921,15 @@ struct CMDSET {
|
||||
},
|
||||
{
|
||||
"exit",NULL,2,0,0,0
|
||||
},
|
||||
{
|
||||
"extend",extend,3,2,2,0
|
||||
},
|
||||
{
|
||||
"help",help,2,1,1,0
|
||||
},
|
||||
{
|
||||
"quit",NULL,2,0,0,0
|
||||
},
|
||||
{
|
||||
"show",show,2,2,2,0
|
||||
@@ -796,11 +949,11 @@ struct CMDSET {
|
||||
},
|
||||
{
|
||||
"statistics",statis,3,1,1,0
|
||||
},
|
||||
{
|
||||
"dump",dump,3,1,1,0
|
||||
},
|
||||
#endif
|
||||
{
|
||||
"test",test,4,2,2,0
|
||||
},
|
||||
{
|
||||
"type",typ,3,2,2,0
|
||||
},
|
||||
@@ -812,7 +965,7 @@ struct CMDSET {
|
||||
|
||||
/* cmdexecute: identify and execute a command */
|
||||
|
||||
int cmdexecute(unsigned int argc,char *argv[],unsigned int qualc,char *qualv[])
|
||||
int cmdexecute(int argc,char *argv[],int qualc,char *qualv[])
|
||||
{
|
||||
char *ptr = argv[0];
|
||||
struct CMDSET *cmd = cmdset;
|
||||
@@ -835,7 +988,7 @@ int cmdexecute(unsigned int argc,char *argv[],unsigned int qualc,char *qualv[])
|
||||
} else {
|
||||
(*cmd->proc) (argc,argv,qualc,qualv);
|
||||
#ifndef VMSIO
|
||||
cacheflush();
|
||||
/* cache_flush(); */
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -879,18 +1032,89 @@ int cmdsplit(char *str)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef VMS
|
||||
#include <smgdef.h>
|
||||
#include <smg$routines.h>
|
||||
|
||||
char *getcmd(char *inp, char *prompt)
|
||||
{
|
||||
struct dsc_descriptor prompt_d = {strlen(prompt),DSC$K_DTYPE_T,
|
||||
DSC$K_CLASS_S, prompt};
|
||||
struct dsc_descriptor input_d = {1024,DSC$K_DTYPE_T,
|
||||
DSC$K_CLASS_S, inp};
|
||||
int status;
|
||||
char *retstat;
|
||||
static unsigned long key_table_id = 0;
|
||||
static unsigned long keyboard_id = 0;
|
||||
|
||||
if (key_table_id == 0)
|
||||
{
|
||||
status = smg$create_key_table (&key_table_id);
|
||||
if (status & 1)
|
||||
status = smg$create_virtual_keyboard (&keyboard_id);
|
||||
if (!(status & 1)) return (NULL);
|
||||
}
|
||||
|
||||
status = smg$read_composed_line (&keyboard_id, &key_table_id,
|
||||
&input_d, &prompt_d, &input_d, 0,0,0,0,0,0,0);
|
||||
|
||||
if (status == SMG$_EOF)
|
||||
retstat = NULL;
|
||||
else
|
||||
{
|
||||
inp[input_d.dsc_w_length] = '\0';
|
||||
retstat = inp;
|
||||
}
|
||||
|
||||
return(retstat);
|
||||
}
|
||||
#endif /* VMS */
|
||||
|
||||
|
||||
/* main: the simple mainline of this puppy... */
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
char str[2048];
|
||||
str[sizeof(str)-1] = 0;
|
||||
printf(" ODS2 v1.2\n");
|
||||
FILE *atfile = NULL;
|
||||
printf(" ODS2 %s\n", MODULE_IDENT);
|
||||
while (1) {
|
||||
printf("$> ");
|
||||
if (fgets(str, sizeof(str)-1, stdin) == NULL) break;
|
||||
if (strlen(str)) if ((cmdsplit(str) & 1) == 0) break;
|
||||
char *ptr;
|
||||
if (atfile != NULL) {
|
||||
if (fgets(str,sizeof(str),atfile) == NULL) {
|
||||
fclose(atfile);
|
||||
atfile = NULL;
|
||||
*str = '\0';
|
||||
} else {
|
||||
ptr = strchr(str,'\n');
|
||||
if (ptr != NULL) *ptr = '\0';
|
||||
printf("$> %s\n",str);
|
||||
}
|
||||
} else {
|
||||
#ifdef VMS
|
||||
if (getcmd (str, "$> ") == NULL) break;
|
||||
#else
|
||||
printf("$> ");
|
||||
if (gets(str) == NULL) break;
|
||||
#endif
|
||||
}
|
||||
ptr = str;
|
||||
while (*ptr == ' ' || *ptr == '\t') ptr++;
|
||||
if (strlen(ptr) && *ptr != '!') {
|
||||
if (*ptr == '@') {
|
||||
if (atfile != NULL) {
|
||||
printf("%%ODS2-W-INDIRECT, indirect indirection not permitted\n");
|
||||
} else {
|
||||
if ((atfile = fopen(ptr + 1,"r")) == NULL) {
|
||||
perror("%%Indirection failed");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((cmdsplit(ptr) & 1) == 0) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (atfile != NULL) fclose(atfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
109
extracters/ods2/ods2.rc
Normal file
109
extracters/ods2/ods2.rc
Normal file
@@ -0,0 +1,109 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
#ifndef _MAC
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,0,0,3
|
||||
PRODUCTVERSION 1,0,0,3
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x1L
|
||||
FILESUBTYPE 0x0L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "This application reads ODS-2 (VMS) disks under Windows NT and Windows 2000\0"
|
||||
VALUE "CompanyName", "Paul Nankervis <paulnank@au1.ibm.com>\0"
|
||||
VALUE "FileDescription", "ODS-2 Reader for Windows\0"
|
||||
VALUE "FileVersion", "V1.3\0"
|
||||
VALUE "InternalName", "ODS2\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2001\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "ODS2.EXE\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", "ODS2\0"
|
||||
VALUE "ProductVersion", "V1.3\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
|
||||
#endif // !_MAC
|
||||
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
BIN
extracters/ods2/ods2_alpha.exe
Normal file
BIN
extracters/ods2/ods2_alpha.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_solaris_intel.exe
Normal file
BIN
extracters/ods2/ods2_solaris_intel.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_solaris_sparc.exe
Normal file
BIN
extracters/ods2/ods2_solaris_sparc.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_tru64.exe
Normal file
BIN
extracters/ods2/ods2_tru64.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_vax_decc.exe
Normal file
BIN
extracters/ods2/ods2_vax_decc.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_vax_vaxc.exe
Normal file
BIN
extracters/ods2/ods2_vax_vaxc.exe
Normal file
Binary file not shown.
BIN
extracters/ods2/ods2_win32.exe
Normal file
BIN
extracters/ods2/ods2_win32.exe
Normal file
Binary file not shown.
@@ -1,4 +1,4 @@
|
||||
/* Phy.h v1.2 Definition of Physical I/O routines */
|
||||
/* Phyio.h v1.2-2 Definition of Physical I/O routines */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* PHYNT.C v1.2 Physical I/O module for Windows NT */
|
||||
/* PHYNT.C v1.2-2 Physical I/O module for Windows NT */
|
||||
|
||||
/* W95 code now included with code to automatically determine
|
||||
if we are running under NT...
|
||||
@@ -8,15 +8,13 @@
|
||||
|
||||
|
||||
|
||||
/* This version built and tested under Visual C++. To support
|
||||
CD drives this version requires ASPI run-time support. For
|
||||
SCSI drives probably any old ASPI library will do. But for
|
||||
ATAPI drives on NT there are 'ASPI libraries and there are
|
||||
ASPI libraries'. I have had success with an older version of
|
||||
Adaptec's APSI (version 2,4,0,0) and with Symbios Logic
|
||||
libraries. But I have NOT been able to make the latest
|
||||
Adaptec routines work on NT!
|
||||
Note: Windows 95 comes with APSI by default! */
|
||||
/* This version built and tested under Visual C++ 6.0 and LCC.
|
||||
To support CD drives this version requires ASPI run-time
|
||||
support.. Windows 95/98 come with ASPI but NT/2000 require
|
||||
that a version of ASPI be install and started before running
|
||||
this program!! (One verion is NTASPI available from
|
||||
www.symbios.com) */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -26,48 +24,13 @@
|
||||
#include <ctype.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "phyio.h"
|
||||
#include "ssdef.h"
|
||||
|
||||
|
||||
unsigned init_count = 0; /* Some counters so we can report */
|
||||
unsigned read_count = 0; /* How often we get called */
|
||||
unsigned write_count = 0;
|
||||
|
||||
void phyio_show(void)
|
||||
{
|
||||
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
|
||||
init_count,read_count,write_count);
|
||||
}
|
||||
|
||||
|
||||
unsigned phyio_write(unsigned handle,unsigned block,unsigned length,char *buffer)
|
||||
{
|
||||
write_count++;
|
||||
return SS$_WRITLCK; /* Not implemented yet!! */
|
||||
}
|
||||
|
||||
|
||||
/* This routine figures out whether this is an NT system or not... */
|
||||
|
||||
unsigned is_NT = 2;
|
||||
OSVERSIONINFO sysver;
|
||||
|
||||
void getsysversion()
|
||||
{
|
||||
memset(&sysver,0,sizeof(OSVERSIONINFO));
|
||||
sysver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&sysver);
|
||||
if (sysver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
||||
is_NT = 1;
|
||||
} else {
|
||||
is_NT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
To read from CD APSI run-time support is required (wnaspi32.dll).
|
||||
NT does not come with APSI support so you need to install it first.
|
||||
To read from CD ASPI run-time support is required (wnaspi32.dll).
|
||||
NT does not come with ASPI support so you need to install it first.
|
||||
(ASPI is also required for things like Digital Audio Extraction
|
||||
and was origionally loaded on my machine to make MP3 audio files.)
|
||||
One downside is that ASPI on NT does not have a way to match SCSI
|
||||
@@ -79,108 +42,205 @@ void getsysversion()
|
||||
you find a better way please let me know... Paulnank@au1.ibm.com
|
||||
*/
|
||||
|
||||
#if defined (USE_WNASPI)
|
||||
|
||||
#include "wnaspi32.h"
|
||||
#include "scsidefs.h"
|
||||
|
||||
unsigned cd_initialized = 0; /* Flag for CD read to go... */
|
||||
unsigned cd_adaptor,cd_target; /* Adaptor & SCSI #'s */
|
||||
HANDLE ASPICompletion; /* Windows event for ASPI wait */
|
||||
unsigned ASPI_status = 0; /* Temporary status indicator */
|
||||
unsigned ASPI_HaStat = 0; /* Temporary status indicator */
|
||||
unsigned ASPI_TargStat = 0; /* Temporary status indicator */
|
||||
|
||||
HANDLE ASPI_event; /* Windows event for ASPI wait */
|
||||
SRB_ExecSCSICmd ASPI_srb; /* SRB buffer for ASPI commands */
|
||||
|
||||
/* Get ASPI ready and locate the first CD drive... */
|
||||
|
||||
unsigned cd_initialize()
|
||||
unsigned aspi_execute(short bus,short id,BYTE Flags,DWORD BufLen,
|
||||
BYTE *BufPointer,BYTE CDBLen,BYTE CDBByte)
|
||||
{
|
||||
if (cd_initialized) {
|
||||
printf("Can only support one (first) ASPI device\n");
|
||||
return 8;
|
||||
} else {
|
||||
DWORD ASPIStatus;
|
||||
ASPI_srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
ASPI_srb.SRB_Status = SS_PENDING;
|
||||
ASPI_srb.SRB_HaId = bus;
|
||||
ASPI_srb.SRB_Flags = Flags | SRB_EVENT_NOTIFY;
|
||||
ASPI_srb.SRB_Hdr_Rsvd = 0;
|
||||
ASPI_srb.SRB_Target = id;
|
||||
ASPI_srb.SRB_Lun = 0;
|
||||
ASPI_srb.SRB_Rsvd1 = 0;
|
||||
ASPI_srb.SRB_BufLen = BufLen;
|
||||
ASPI_srb.SRB_BufPointer = BufPointer;
|
||||
ASPI_srb.SRB_SenseLen = SENSE_LEN;
|
||||
ASPI_srb.SRB_CDBLen = CDBLen;
|
||||
ASPI_srb.SRB_HaStat = 0;
|
||||
ASPI_srb.SRB_TargStat = 0;
|
||||
ASPI_srb.SRB_PostProc = ASPI_event;
|
||||
ASPI_srb.SRB_Rsvd2 = NULL;
|
||||
memset(ASPI_srb.SRB_Rsvd3,0,sizeof(ASPI_srb.SRB_Rsvd3));
|
||||
ASPI_srb.CDBByte[0] = CDBByte;
|
||||
SendASPI32Command(&ASPI_srb); /* Perform the command... */
|
||||
while (ASPI_srb.SRB_Status == SS_PENDING)
|
||||
WaitForSingleObject(ASPI_event,INFINITE);
|
||||
ResetEvent(ASPI_event);
|
||||
ASPI_status = ASPI_srb.SRB_Status;
|
||||
ASPI_HaStat = ASPI_srb.SRB_HaStat;
|
||||
ASPI_TargStat = ASPI_srb.SRB_TargStat;
|
||||
if (ASPI_srb.SRB_Status != SS_COMP) return SS$_PARITY;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Read a sector using ASPI... */
|
||||
|
||||
unsigned aspi_read(short bus,short id,unsigned sector,unsigned sectorsize,char *buffer)
|
||||
{
|
||||
|
||||
ASPI_srb.CDBByte[1] = 0;
|
||||
ASPI_srb.CDBByte[2] = (sector >> 24);
|
||||
ASPI_srb.CDBByte[3] = (sector >> 16) & 0xff;
|
||||
ASPI_srb.CDBByte[4] = (sector >> 8) & 0xff;
|
||||
ASPI_srb.CDBByte[5] = sector & 0xff;
|
||||
ASPI_srb.CDBByte[6] = 0;
|
||||
ASPI_srb.CDBByte[7] = 0;
|
||||
ASPI_srb.CDBByte[8] = 1; /* Read a single sector */
|
||||
ASPI_srb.CDBByte[9] = 0;
|
||||
return aspi_execute(bus,id,SRB_DIR_IN,sectorsize,buffer,10,SCSI_READ10);
|
||||
}
|
||||
|
||||
|
||||
/* Write a sector using ASPI... */
|
||||
|
||||
unsigned aspi_write(short bus,short id,unsigned sector,unsigned sectorsize,char *buffer)
|
||||
{
|
||||
|
||||
ASPI_srb.CDBByte[1] = 0;
|
||||
ASPI_srb.CDBByte[2] = (sector >> 24);
|
||||
ASPI_srb.CDBByte[3] = (sector >> 16) & 0xff;
|
||||
ASPI_srb.CDBByte[4] = (sector >> 8) & 0xff;
|
||||
ASPI_srb.CDBByte[5] = sector & 0xff;
|
||||
ASPI_srb.CDBByte[6] = 0;
|
||||
ASPI_srb.CDBByte[7] = 0;
|
||||
ASPI_srb.CDBByte[8] = 1; /* Read a single sector */
|
||||
ASPI_srb.CDBByte[9] = 0;
|
||||
return aspi_execute(bus,id,SRB_DIR_OUT,sectorsize,buffer,10,SCSI_WRITE10);
|
||||
}
|
||||
|
||||
|
||||
/* Routine to identify a device found by ASPI */
|
||||
|
||||
unsigned aspi_identify(short bus,short id,unsigned *sectsize)
|
||||
{
|
||||
struct SCSI_Inquiry {
|
||||
unsigned char device;
|
||||
unsigned char dev_qual2;
|
||||
unsigned char version;
|
||||
unsigned char response_format;
|
||||
unsigned char additional_length;
|
||||
unsigned char unused[2];
|
||||
unsigned char flags;
|
||||
char vendor[8];
|
||||
char product[16];
|
||||
char revision[4];
|
||||
unsigned char extra[60];
|
||||
} InquiryBuffer;
|
||||
unsigned sts;
|
||||
ASPI_srb.CDBByte[1] = 0; /* SCSI Inquiry packet */
|
||||
ASPI_srb.CDBByte[2] = 0;
|
||||
ASPI_srb.CDBByte[3] = 0;
|
||||
ASPI_srb.CDBByte[4] = sizeof(InquiryBuffer);
|
||||
ASPI_srb.CDBByte[5] = 0;
|
||||
sts = aspi_execute(bus,id,SRB_DIR_IN,sizeof(InquiryBuffer),(BYTE *)&InquiryBuffer,6,SCSI_INQUIRY);
|
||||
if (sts & 1) {
|
||||
ASPI_srb.CDBByte[1] = 0;/* SCSI TEST if ready packet */
|
||||
ASPI_srb.CDBByte[2] = 0;
|
||||
ASPI_srb.CDBByte[3] = 0;
|
||||
ASPI_srb.CDBByte[4] = 0;
|
||||
ASPI_srb.CDBByte[5] = 0;
|
||||
sts = aspi_execute(bus,id,0,0,NULL,6,SCSI_TST_U_RDY);
|
||||
if ((sts & 1) == 0) {
|
||||
ASPI_srb.CDBByte[1] = 0; /* SCSI START STOP packet */
|
||||
ASPI_srb.CDBByte[2] = 0;
|
||||
ASPI_srb.CDBByte[3] = 0;
|
||||
ASPI_srb.CDBByte[4] = 1; /* Start unit */
|
||||
ASPI_srb.CDBByte[5] = 0;
|
||||
sts = aspi_execute(bus,id,0,0,NULL,6,SCSI_START_STP);
|
||||
}
|
||||
if (sts & 1) {
|
||||
struct {
|
||||
unsigned char blocks[4];
|
||||
unsigned char sectsz[4];
|
||||
} CapBuffer;
|
||||
memset(ASPI_srb.CDBByte,0,sizeof(ASPI_srb.CDBByte));
|
||||
sts = aspi_execute(bus,id,SRB_DIR_IN,sizeof(CapBuffer),(BYTE *)&CapBuffer,10,SCSI_RD_CAPAC);
|
||||
if (sts & 1) {
|
||||
*sectsize = (CapBuffer.sectsz[0] << 24) | (CapBuffer.sectsz[1] << 16) |
|
||||
(CapBuffer.sectsz[2] << 8) | CapBuffer.sectsz[3];
|
||||
}
|
||||
}
|
||||
printf("ASPI (Bus %d,ID %d) %8.8s %16.16s %4.4s %s %d\n",bus,id,
|
||||
InquiryBuffer.vendor,InquiryBuffer.product,InquiryBuffer.revision,
|
||||
(InquiryBuffer.dev_qual2 & 0x80) ? "Removable" : "Fixed",*sectsize);
|
||||
|
||||
}
|
||||
if ((sts & 1) == 0) {
|
||||
int i;
|
||||
printf("ASPI Error sense %x %x %x - ",ASPI_status,ASPI_HaStat,ASPI_TargStat);
|
||||
for (i = 0; i < SENSE_LEN; i++) printf(" %x",ASPI_srb.SenseArea[i]);
|
||||
printf("\n");
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned ASPI_adapters = 0; /* Count of ASPI adapters */
|
||||
unsigned ASPI_devices = 0; /* Count of ASPI devices we have accessed */
|
||||
|
||||
/* Get ASPI ready and locate the next ASPI drive... */
|
||||
|
||||
unsigned aspi_initialize(short *dev_type,short *dev_bus,short *dev_id,unsigned *sectsize)
|
||||
{
|
||||
short aspi_bus,aspi_id;
|
||||
unsigned aspi_devcount = 0;
|
||||
DWORD ASPIStatus;
|
||||
SRB_GDEVBlock Ssrb;
|
||||
if (ASPI_adapters == 0) {
|
||||
ASPIStatus = GetASPI32SupportInfo();
|
||||
if (HIBYTE(LOWORD(ASPIStatus)) == SS_COMP) {
|
||||
BYTE NumAdapters;
|
||||
SRB_GDEVBlock Ssrb;
|
||||
Ssrb.SRB_Cmd = SC_GET_DEV_TYPE;
|
||||
Ssrb.SRB_HaId = 0;
|
||||
Ssrb.SRB_Flags = SRB_EVENT_NOTIFY;
|
||||
Ssrb.SRB_Hdr_Rsvd = 0;
|
||||
Ssrb.SRB_Target = 0;
|
||||
Ssrb.SRB_Lun = 0;
|
||||
NumAdapters = LOWORD(LOBYTE(ASPIStatus));
|
||||
for (cd_adaptor = 0; cd_adaptor < NumAdapters; cd_adaptor++) {
|
||||
for (cd_target = 0; cd_target <= 7; cd_target++) {
|
||||
Ssrb.SRB_HaId = cd_adaptor;
|
||||
Ssrb.SRB_Target = cd_target;
|
||||
ASPIStatus = SendASPI32Command(&Ssrb);
|
||||
if (ASPIStatus == SS_COMP && Ssrb.SRB_DeviceType == 5) break;
|
||||
}
|
||||
if (cd_target <= 7) break;
|
||||
}
|
||||
if (cd_adaptor < NumAdapters) {
|
||||
if ((ASPICompletion = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL) return 8;
|
||||
cd_initialized = 1;
|
||||
return 1;
|
||||
} else {
|
||||
printf("Could not find ASPI CD device\n");
|
||||
return 8;
|
||||
}
|
||||
} else {
|
||||
ASPI_status = ASPIStatus;
|
||||
if (HIBYTE(LOWORD(ASPIStatus)) != SS_COMP) {
|
||||
printf("Could not initialize ASPI (%x)\n",ASPIStatus);
|
||||
printf("Please check that ASPI is installed and started properly\n");
|
||||
return 8;
|
||||
} else {
|
||||
ASPI_adapters = LOWORD(LOBYTE(ASPIStatus));
|
||||
if ((ASPI_event = CreateEvent(NULL,FALSE,FALSE,NULL)) == NULL) return 8;
|
||||
}
|
||||
}
|
||||
Ssrb.SRB_Cmd = SC_GET_DEV_TYPE;
|
||||
Ssrb.SRB_HaId = 0;
|
||||
Ssrb.SRB_Flags = SRB_EVENT_NOTIFY;
|
||||
Ssrb.SRB_Hdr_Rsvd = 0;
|
||||
Ssrb.SRB_Lun = 0;
|
||||
for (aspi_bus = 0; aspi_bus < ASPI_adapters; aspi_bus++) {
|
||||
for (aspi_id = 0; aspi_id <= 7; aspi_id++) {
|
||||
Ssrb.SRB_HaId = aspi_bus;
|
||||
Ssrb.SRB_Target = aspi_id;
|
||||
ASPIStatus = SendASPI32Command(&Ssrb);
|
||||
ASPI_status = ASPIStatus;
|
||||
if (ASPIStatus == SS_COMP) {
|
||||
if (Ssrb.SRB_DeviceType == DTYPE_CROM || Ssrb.SRB_DeviceType == DTYPE_OPTI) {
|
||||
if (++aspi_devcount > ASPI_devices) {
|
||||
unsigned sts = aspi_identify(aspi_bus,aspi_id,sectsize);
|
||||
*dev_type = Ssrb.SRB_DeviceType;
|
||||
*dev_bus = aspi_bus;
|
||||
*dev_id = aspi_id;
|
||||
ASPI_devices++;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Could not find suitable ASPI device\n");
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
/* Read a sector from CD using ASPI... */
|
||||
|
||||
unsigned cd_read(unsigned sector,char *buffer)
|
||||
{
|
||||
DWORD ASPIEventStatus;
|
||||
SRB_ExecSCSICmd Esrb;
|
||||
Esrb.SRB_Cmd = SC_EXEC_SCSI_CMD;
|
||||
Esrb.SRB_HaId = cd_adaptor;
|
||||
Esrb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
|
||||
Esrb.SRB_Hdr_Rsvd = 0;
|
||||
Esrb.SRB_Target = cd_target;
|
||||
Esrb.SRB_Lun = 0;
|
||||
Esrb.SRB_BufLen = 2352;
|
||||
Esrb.SRB_BufPointer = buffer;
|
||||
Esrb.SRB_SenseLen = 0;
|
||||
Esrb.SRB_CDBLen = 10;
|
||||
Esrb.SRB_PostProc = ASPICompletion;
|
||||
Esrb.CDBByte[0] = 0x28; /* Build SCSI read command packet... */
|
||||
Esrb.CDBByte[1] = 0;
|
||||
Esrb.CDBByte[2] = (sector >> 24);
|
||||
Esrb.CDBByte[3] = (sector >> 16) & 0xff;
|
||||
Esrb.CDBByte[4] = (sector >> 8) & 0xff;
|
||||
Esrb.CDBByte[5] = sector & 0xff;
|
||||
Esrb.CDBByte[6] = 0;
|
||||
Esrb.CDBByte[7] = 0;
|
||||
Esrb.CDBByte[8] = 1;
|
||||
Esrb.CDBByte[9] = 0;
|
||||
Esrb.CDBByte[10] = 0;
|
||||
SendASPI32Command(&Esrb); /* Perform the read... */
|
||||
while (Esrb.SRB_Status == SS_PENDING)
|
||||
ASPIEventStatus = WaitForSingleObject(ASPICompletion,INFINITE);
|
||||
/* if (ASPIEventStatus == WAIT_OBJECT_0) */ResetEvent(ASPICompletion);
|
||||
if (Esrb.SRB_Status != SS_COMP) return SS$_PARITY;
|
||||
return 1;
|
||||
}
|
||||
#else /* !defined(USE_WNASPI) */
|
||||
|
||||
unsigned cd_initialize()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned cd_read(unsigned sector,char *buffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(USE_WNASPI) */
|
||||
|
||||
|
||||
/* Some NT definitions... */
|
||||
@@ -218,7 +278,7 @@ BOOL
|
||||
sizeof(*dGeometry),
|
||||
&ReturnedByteCount,
|
||||
NULL
|
||||
);
|
||||
);
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -279,6 +339,22 @@ typedef struct _DEVICEPARAM {
|
||||
|
||||
|
||||
|
||||
/* This routine figures out whether this is an NT system or not... */
|
||||
|
||||
unsigned is_NT = 2;
|
||||
OSVERSIONINFO sysver;
|
||||
|
||||
void getsysversion(void)
|
||||
{
|
||||
memset(&sysver,0,sizeof(OSVERSIONINFO));
|
||||
sysver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||||
GetVersionEx(&sysver);
|
||||
if (sysver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
|
||||
is_NT = 1;
|
||||
} else {
|
||||
is_NT = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Each device we talk to has a channel entry so that we can
|
||||
remember its details... */
|
||||
@@ -290,154 +366,24 @@ struct CHANTAB {
|
||||
char *IoBuffer; /* Pointer to a buffer for the device */
|
||||
unsigned sectorsize; /* Device sector size */
|
||||
unsigned last_sector; /* Last sector no read (still in buffer) */
|
||||
short device_type; /* Flag for 'normal' or ASPI I/O */
|
||||
short device_status; /* Device status bits */
|
||||
short device_name; /* Drive letter (A, B, C, ...) */
|
||||
short device_dtype; /* Type of disk... */
|
||||
short device_bus; /* ASPI device bus */
|
||||
short device_id; /* ASPI device id */
|
||||
} chantab[CHAN_MAX];
|
||||
|
||||
|
||||
|
||||
|
||||
/* Initialize device by opening it, locking it and getting it ready.. */
|
||||
|
||||
unsigned phyio_init(int devlen,char *devnam,unsigned *chanptr,struct phyio_info *info)
|
||||
{
|
||||
unsigned sts = 1;
|
||||
unsigned chan = chan_count;
|
||||
if (is_NT > 1) getsysversion();
|
||||
if (chan < CHAN_MAX - 1 && devlen == 2 &&
|
||||
toupper(*devnam) >= 'A' && *(devnam + 1) == ':') {
|
||||
HANDLE hDrive;
|
||||
chantab[chan].device_name = toupper(*devnam);
|
||||
chantab[chan].device_type = 0;
|
||||
|
||||
/* NT stuff */
|
||||
|
||||
if (is_NT) {
|
||||
char ntname[32];
|
||||
DISK_GEOMETRY Geometry;
|
||||
sprintf(ntname,"\\\\.\\%s",devnam);
|
||||
chantab[chan].handle = hDrive = CreateFileA(
|
||||
ntname,
|
||||
GENERIC_READ,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_NO_BUFFERING,
|
||||
NULL
|
||||
);
|
||||
if (hDrive == INVALID_HANDLE_VALUE) {
|
||||
printf("Open %s failed %d\n",devnam,GetLastError());
|
||||
return SS$_NOSUCHDEV;
|
||||
}
|
||||
if (LockVolume(hDrive) == FALSE) {
|
||||
printf("LockVolume %s failed %d\n",devnam,GetLastError());
|
||||
return 72;
|
||||
}
|
||||
if (!GetDiskGeometry(hDrive,&Geometry)) {
|
||||
printf("GetDiskGeometry %s failed %d\n",devnam,GetLastError());
|
||||
return 80;
|
||||
}
|
||||
/* If this is a 2048 byte sector device past C treat it as a CD... */
|
||||
|
||||
chantab[chan].device_type = 0;
|
||||
if (Geometry.BytesPerSector == 2048 && toupper(*devnam) > 'C') {
|
||||
sts = cd_initialize();
|
||||
if ((sts & 1) == 0) return sts;
|
||||
chantab[chan].device_type = 1;
|
||||
}
|
||||
chantab[chan].sectorsize = Geometry.BytesPerSector;
|
||||
info->sectors = (unsigned)(Geometry.Cylinders.QuadPart * Geometry.TracksPerCylinder *
|
||||
Geometry.SectorsPerTrack);
|
||||
|
||||
} else {
|
||||
|
||||
#if defined(USE_WIN95)
|
||||
/* W95 stuff */
|
||||
|
||||
|
||||
if (chantab[chan].device_name > 'C') { /* Assume above C are CDs.. */
|
||||
sts = cd_initialize();
|
||||
if ((sts & 1) == 0) return sts;
|
||||
chantab[chan].device_type = 1;
|
||||
chantab[chan].sectorsize = 2048;
|
||||
} else {
|
||||
DIOC_REGISTERS reg;
|
||||
DEVICEPARAM deviceparam;
|
||||
BOOL fResult;
|
||||
DWORD cb;
|
||||
chantab[chan].handle = hDrive = CreateFileA(
|
||||
"\\\\.\\vwin32",
|
||||
0,0,
|
||||
NULL,
|
||||
0,
|
||||
FILE_FLAG_DELETE_ON_CLOSE,
|
||||
NULL);
|
||||
if (hDrive == INVALID_HANDLE_VALUE) {
|
||||
printf("Open %s failed %d\n",devnam,GetLastError());
|
||||
return SS$_NOSUCHDEV;
|
||||
}
|
||||
reg.reg_EAX = 0x440d;
|
||||
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
|
||||
reg.reg_ECX = 0x084a; /* Lock volume */
|
||||
reg.reg_EDX = 0;
|
||||
reg.reg_Flags = 0x0000; /* Permission */
|
||||
|
||||
fResult = DeviceIoControl(hDrive,
|
||||
VWIN32_DIOC_DOS_IOCTL,
|
||||
®,sizeof(reg),
|
||||
®,sizeof(reg),
|
||||
&cb,0);
|
||||
|
||||
if (!fResult || (reg.reg_Flags & 0x0001)) {
|
||||
printf("Volume lock failed (%d)\n",GetLastError());
|
||||
return SS$_DEVNOTALLOC;
|
||||
}
|
||||
reg.reg_EAX = 0x440d;
|
||||
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
|
||||
reg.reg_ECX = 0x0860; /* Get device parameters */
|
||||
reg.reg_EDX = (DWORD) & deviceparam;
|
||||
reg.reg_Flags = 0x0001; /* set carry flag */
|
||||
|
||||
fResult = DeviceIoControl(hDrive,
|
||||
VWIN32_DIOC_DOS_IOCTL,
|
||||
®,sizeof(reg),
|
||||
®,sizeof(reg),
|
||||
&cb,0);
|
||||
|
||||
if (!fResult || (reg.reg_Flags & 0x0001)) {
|
||||
printf("Volume get parameters failed (%d)\n",GetLastError());
|
||||
return 8;
|
||||
}
|
||||
chantab[chan].sectorsize = deviceparam.sec_size;
|
||||
}
|
||||
info->sectors = 0;
|
||||
#endif /* defined(USE_WIN95) */
|
||||
}
|
||||
|
||||
chantab[chan].IoBuffer = VirtualAlloc(NULL,
|
||||
chantab[chan].sectorsize + 304,MEM_COMMIT,PAGE_READWRITE);
|
||||
chantab[chan].last_sector = 1000;
|
||||
*chanptr = chan_count++;
|
||||
info->status = 0;
|
||||
info->sectorsize = chantab[chan].sectorsize;
|
||||
init_count++;
|
||||
return 1;
|
||||
} else {
|
||||
return SS$_IVCHAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Read a physical sector... */
|
||||
|
||||
unsigned phy_getsect(unsigned chan,unsigned sector,char **buffptr)
|
||||
unsigned phy_getsect(unsigned chan,unsigned sector)
|
||||
{
|
||||
register unsigned sts = 1;
|
||||
if (sector != chantab[chan].last_sector) {
|
||||
if (chantab[chan].device_type) {
|
||||
sts = cd_read(sector,chantab[chan].IoBuffer);
|
||||
if (chantab[chan].device_dtype >= 0) {
|
||||
sts = aspi_read(chantab[chan].device_bus,chantab[chan].device_id,sector,
|
||||
chantab[chan].sectorsize,chantab[chan].IoBuffer);
|
||||
} else {
|
||||
if (is_NT) {
|
||||
DWORD BytesRead = -1; /* NT Bytes read */
|
||||
@@ -474,15 +420,161 @@ unsigned phy_getsect(unsigned chan,unsigned sector,char **buffptr)
|
||||
}
|
||||
if (sts & 1) {
|
||||
chantab[chan].last_sector = sector;
|
||||
*buffptr = chantab[chan].IoBuffer;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/* Write a physical sector... */
|
||||
|
||||
unsigned phy_putsect(unsigned chan,unsigned sector)
|
||||
{
|
||||
register unsigned sts = 1;
|
||||
chantab[chan].last_sector = sector;
|
||||
if (chantab[chan].device_dtype >= 0) {
|
||||
sts = aspi_write(chantab[chan].device_bus,chantab[chan].device_id,sector,
|
||||
chantab[chan].sectorsize,chantab[chan].IoBuffer);
|
||||
} else {
|
||||
if (is_NT) {
|
||||
DWORD BytesRead = -1; /* NT Bytes written */
|
||||
SetFilePointer(chantab[chan].handle,
|
||||
sector * chantab[chan].sectorsize,0,FILE_BEGIN);
|
||||
if (!WriteFile(chantab[chan].handle,chantab[chan].IoBuffer,
|
||||
chantab[chan].sectorsize,&BytesRead,NULL)) sts = SS$_PARITY;
|
||||
} else {
|
||||
sts = SS$_WRITLCK; /* Not implemented yet!! */
|
||||
}
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
#include "phyio.h"
|
||||
|
||||
|
||||
/* Handle an I/O request ... need to read the approriate sectors to
|
||||
unsigned init_count = 0; /* Some counters so we can report */
|
||||
unsigned read_count = 0; /* How often we get called */
|
||||
unsigned write_count = 0;
|
||||
|
||||
void phyio_show(void)
|
||||
{
|
||||
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
|
||||
init_count,read_count,write_count);
|
||||
}
|
||||
|
||||
|
||||
/* Initialize device by opening it, locking it and getting it ready.. */
|
||||
|
||||
unsigned phyio_init(int devlen,char *devnam,unsigned *chanptr,struct phyio_info *info)
|
||||
{
|
||||
unsigned sts = 1;
|
||||
unsigned chan = chan_count;
|
||||
if (chan < CHAN_MAX - 1 && devlen == 2 &&
|
||||
toupper(*devnam) >= 'A' && *(devnam + 1) == ':') {
|
||||
HANDLE hDrive;
|
||||
chantab[chan].device_status = 0;
|
||||
chantab[chan].device_name = toupper(*devnam);
|
||||
chantab[chan].device_dtype = -1;
|
||||
|
||||
/* Use ASPI for devices past C... */
|
||||
|
||||
if (toupper(*devnam) > 'C') {
|
||||
sts = aspi_initialize(&chantab[chan].device_dtype,
|
||||
&chantab[chan].device_bus,&chantab[chan].device_id,
|
||||
&chantab[chan].sectorsize);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
} else {
|
||||
|
||||
if (is_NT > 1) getsysversion();
|
||||
|
||||
/* NT stuff */
|
||||
|
||||
if (is_NT) {
|
||||
char ntname[20];
|
||||
DISK_GEOMETRY Geometry;
|
||||
sprintf(ntname,"\\\\.\\%s",devnam);
|
||||
chantab[chan].handle = hDrive = CreateFile(ntname,
|
||||
GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
|
||||
if (hDrive == INVALID_HANDLE_VALUE) {
|
||||
printf("Open %s failed %d\n",devnam,GetLastError());
|
||||
return SS$_NOSUCHDEV;
|
||||
}
|
||||
if (LockVolume(hDrive) == FALSE) {
|
||||
printf("LockVolume %s failed %d\n",devnam,GetLastError());
|
||||
return 72;
|
||||
}
|
||||
if (!GetDiskGeometry(hDrive,&Geometry)) {
|
||||
printf("GetDiskGeometry %s failed %d\n",devnam,GetLastError());
|
||||
return 80;
|
||||
}
|
||||
chantab[chan].sectorsize = Geometry.BytesPerSector;
|
||||
info->sectors = Geometry.Cylinders.QuadPart * Geometry.TracksPerCylinder *
|
||||
Geometry.SectorsPerTrack;
|
||||
} else {
|
||||
|
||||
/* W95 stuff */
|
||||
|
||||
DIOC_REGISTERS reg;
|
||||
DEVICEPARAM deviceparam;
|
||||
BOOL fResult;
|
||||
DWORD cb;
|
||||
chantab[chan].handle = hDrive = CreateFile("\\\\.\\vwin32",
|
||||
0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
|
||||
if (hDrive == INVALID_HANDLE_VALUE) {
|
||||
printf("Open %s failed %d\n",devnam,GetLastError());
|
||||
return SS$_NOSUCHDEV;
|
||||
}
|
||||
reg.reg_EAX = 0x440d;
|
||||
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
|
||||
reg.reg_ECX = 0x084a; /* Lock volume */
|
||||
reg.reg_EDX = 0;
|
||||
reg.reg_Flags = 0x0000; /* Permission */
|
||||
|
||||
fResult = DeviceIoControl(hDrive,VWIN32_DIOC_DOS_IOCTL,
|
||||
®,sizeof(reg),®,sizeof(reg),&cb,0);
|
||||
|
||||
if (!fResult || (reg.reg_Flags & 0x0001)) {
|
||||
printf("Volume lock failed (%d)\n",GetLastError());
|
||||
return SS$_DEVNOTALLOC;
|
||||
}
|
||||
reg.reg_EAX = 0x440d;
|
||||
reg.reg_EBX = chantab[chan].device_name - 'A' + 1;
|
||||
reg.reg_ECX = 0x0860; /* Get device parameters */
|
||||
reg.reg_EDX = (DWORD) & deviceparam;
|
||||
reg.reg_Flags = 0x0001; /* set carry flag */
|
||||
|
||||
fResult = DeviceIoControl(hDrive,
|
||||
VWIN32_DIOC_DOS_IOCTL,
|
||||
®,sizeof(reg),
|
||||
®,sizeof(reg),
|
||||
&cb,0);
|
||||
|
||||
if (!fResult || (reg.reg_Flags & 0x0001)) {
|
||||
printf("Volume get parameters failed (%d)\n",GetLastError());
|
||||
return 8;
|
||||
}
|
||||
chantab[chan].sectorsize = deviceparam.sec_size;
|
||||
}
|
||||
info->sectors = 0;
|
||||
}
|
||||
|
||||
chantab[chan].IoBuffer = VirtualAlloc(NULL,chantab[chan].sectorsize,
|
||||
MEM_COMMIT,PAGE_READWRITE);
|
||||
chantab[chan].last_sector = 99999;
|
||||
*chanptr = chan_count++;
|
||||
info->status = 0;
|
||||
info->sectorsize = chantab[chan].sectorsize;
|
||||
init_count++;
|
||||
return 1;
|
||||
} else {
|
||||
return SS$_IVCHAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Handle a read request ... need to read the approriate sectors to
|
||||
complete the request... */
|
||||
|
||||
unsigned phyio_read(unsigned chan,unsigned block,unsigned length,char *buffer)
|
||||
@@ -490,28 +582,69 @@ unsigned phyio_read(unsigned chan,unsigned block,unsigned length,char *buffer)
|
||||
register unsigned sts = 1;
|
||||
|
||||
if (chan < chan_count) {
|
||||
register unsigned sectorsize = chantab[chan].sectorsize;
|
||||
register unsigned sectno = block / (sectorsize / 512);
|
||||
register unsigned offset = (block - sectno * (sectorsize / 512)) * 512;
|
||||
register unsigned sectblks = chantab[chan].sectorsize / 512;
|
||||
register unsigned sectno = block / sectblks;
|
||||
register unsigned offset = block % sectblks;
|
||||
char *sectbuff = chantab[chan].IoBuffer;
|
||||
while (length > 0) {
|
||||
register unsigned transfer;
|
||||
char *sectbuff;
|
||||
if (((sts = phy_getsect(chan,sectno,§buff)) & 1) == 0) break;
|
||||
transfer = sectorsize - offset;
|
||||
transfer = (sectblks - offset) * 512;
|
||||
if (transfer > length) transfer = length;
|
||||
memcpy(buffer,sectbuff + offset,transfer);
|
||||
if (((sts = phy_getsect(chan,sectno)) & 1) == 0) break;
|
||||
memcpy(buffer,sectbuff + (offset * 512),transfer);
|
||||
buffer += transfer;
|
||||
length -= transfer;
|
||||
sectno++;
|
||||
offset = 0;
|
||||
}
|
||||
if (sts & 1) {
|
||||
read_count++;
|
||||
} else {
|
||||
printf("PHYIO Error %d Block %d Length %d (ASPI: %x %x %x)\n",
|
||||
sts,block,length,ASPI_status,ASPI_HaStat,ASPI_TargStat);
|
||||
}
|
||||
|
||||
} else {
|
||||
sts = SS$_IVCHAN;
|
||||
}
|
||||
if (sts & 1) {
|
||||
read_count++;
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* Handle a write request ... need to read the approriate sectors to
|
||||
complete the request... */
|
||||
|
||||
unsigned phyio_write(unsigned chan,unsigned block,unsigned length,char *buffer)
|
||||
{
|
||||
register unsigned sts = 1;
|
||||
|
||||
if (chan < chan_count) {
|
||||
register unsigned sectblks = chantab[chan].sectorsize / 512;
|
||||
register unsigned sectno = block / sectblks;
|
||||
register unsigned offset = block % sectblks;
|
||||
char *sectbuff = chantab[chan].IoBuffer;
|
||||
while (length > 0) {
|
||||
register unsigned transfer;
|
||||
transfer = (sectblks - offset) * 512;
|
||||
if (transfer > length) transfer = length;
|
||||
if (transfer != sectblks * 512) {
|
||||
if (((sts = phy_getsect(chan,sectno)) & 1) == 0) break;
|
||||
}
|
||||
memcpy(buffer,sectbuff + (offset * 512),transfer);
|
||||
if (((sts = phy_putsect(chan,sectno)) & 1) == 0) break;
|
||||
buffer += transfer;
|
||||
length -= transfer;
|
||||
sectno++;
|
||||
offset = 0;
|
||||
}
|
||||
if (sts & 1) {
|
||||
write_count++;
|
||||
} else {
|
||||
printf("PHYIO Error %d Block %d Length %d (ASPI: %x %x %x)\n",
|
||||
sts,block,length,ASPI_status,ASPI_HaStat,ASPI_TargStat);
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("PHYIO Error %d Block %d Length %d\n",sts,block,length);
|
||||
sts = SS$_IVCHAN;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
102
extracters/ods2/phyunix.c
Normal file
102
extracters/ods2/phyunix.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/* PHYVMS.c v1.3 Physical I/O module for Unix */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
email address: Paulnank@au1.ibm.com
|
||||
|
||||
ODS2 is distributed freely for all members of the
|
||||
VMS community to use. However all derived works
|
||||
must maintain comments in their source to acknowledge
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
/*
|
||||
If the user mounts cd0 we open up /dev/cd0 for access.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "phyio.h"
|
||||
#include "ssdef.h"
|
||||
|
||||
#if defined(__digital__) && defined(__unix__)
|
||||
#define DEV_PREFIX "/devices/rdisk/%s"
|
||||
#else
|
||||
#ifdef sun
|
||||
#define DEV_PREFIX "/dev/dsk/%s"
|
||||
#else
|
||||
#define DEV_PREFIX "/dev/%s"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
unsigned init_count = 0;
|
||||
unsigned read_count = 0;
|
||||
unsigned write_count = 0;
|
||||
|
||||
void phyio_show(void)
|
||||
{
|
||||
printf("PHYIO_SHOW Initializations: %d Reads: %d Writes: %d\n",
|
||||
init_count,read_count,write_count);
|
||||
}
|
||||
|
||||
|
||||
unsigned phyio_init(int devlen,char *devnam,unsigned *handle,struct phyio_info *info)
|
||||
{
|
||||
int vmsfd;
|
||||
char *cp,devbuf[200];
|
||||
init_count++;
|
||||
info->status = 0; /* We don't know anything about this device! */
|
||||
info->sectors = 0;
|
||||
info->sectorsize = 0;
|
||||
sprintf(devbuf,DEV_PREFIX,devnam);
|
||||
cp = strchr(devbuf,':');
|
||||
if (cp != NULL) *cp = '\0';
|
||||
vmsfd = open(devbuf,O_RDWR);
|
||||
if (vmsfd < 0) vmsfd = open(devbuf,O_RDONLY);
|
||||
if (vmsfd < 0) return SS$_NOSUCHDEV;
|
||||
*handle = vmsfd;
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
unsigned phyio_close(unsigned handle)
|
||||
{
|
||||
close(handle);
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
unsigned phyio_read(unsigned handle,unsigned block,unsigned length,char *buffer)
|
||||
{
|
||||
int res;
|
||||
#ifdef DEBUG
|
||||
printf("Phyio read block: %d into %x (%d bytes)\n",block,buffer,length);
|
||||
#endif
|
||||
read_count++;
|
||||
if ((res = lseek(handle,block*512,0)) < 0) {
|
||||
perror("lseek ");
|
||||
printf("lseek failed %d\n",res);
|
||||
return SS$_PARITY;
|
||||
}
|
||||
if ((res = read(handle,buffer,length)) != length) {
|
||||
perror("read ");
|
||||
printf("read failed %d\n",res);
|
||||
return SS$_PARITY;
|
||||
}
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
|
||||
unsigned phyio_write(unsigned handle,unsigned block,unsigned length,char *buffer)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("Phyio write block: %d from %x (%d bytes)\n",block,buffer,length);
|
||||
#endif
|
||||
write_count++;
|
||||
if (lseek(handle,block*512,0) < 0) return SS$_PARITY;
|
||||
if (write(handle,buffer,length) != length) return SS$_PARITY;
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* PHYVMS.C v1.2 Physical I/O module for VMS */
|
||||
/* PHYVMS.c v1.3 Physical I/O module for VMS */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -16,12 +16,27 @@
|
||||
even have different command sets depending on what mode they
|
||||
are called from! Sigh. */
|
||||
|
||||
/* Modified by:
|
||||
*
|
||||
* 31-AUG-2001 01:04 Hunter Goatley <goathunter@goatley.com>
|
||||
*
|
||||
* Added checks to be sure device we're mounting is a
|
||||
* disk and that it's already physically mounted at the
|
||||
* DCL level,
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <iodef.h>
|
||||
#include <descrip.h>
|
||||
#include <ssdef.h>
|
||||
#include <dcdef.h>
|
||||
#include <dvidef.h>
|
||||
#include <mntdef.h>
|
||||
#include <devdef.h>
|
||||
#include <ssdef.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
unsigned sys$assign();
|
||||
@@ -49,13 +64,64 @@ void phyio_show(void)
|
||||
unsigned phyio_init(int devlen,char *devnam,unsigned *handle,struct phyio_info *info)
|
||||
{
|
||||
struct dsc$descriptor devdsc;
|
||||
unsigned long devclass, status;
|
||||
char devname[65];
|
||||
unsigned long devchar;
|
||||
unsigned long mntflags[2];
|
||||
struct ITMLST {
|
||||
unsigned short length;
|
||||
unsigned short itmcod;
|
||||
void *buffer;
|
||||
unsigned long *retlen;
|
||||
} dvi_itmlst[4] = {{sizeof(devclass), DVI$_DEVCLASS, &devclass, 0},
|
||||
{sizeof(devname), DVI$_ALLDEVNAM, &devname, 0},
|
||||
{sizeof(devchar), DVI$_DEVCHAR, &devchar, 0},
|
||||
{0, 0, 0, 0}},
|
||||
mnt_itmlst[3] = {{0, MNT$_DEVNAM, 0, 0},
|
||||
{sizeof(mntflags), MNT$_FLAGS, &mntflags, 0},
|
||||
{0, 0, 0, 0}};
|
||||
|
||||
devdsc.dsc$w_length = devlen;
|
||||
devdsc.dsc$a_pointer = devnam;
|
||||
|
||||
init_count++;
|
||||
info->status = 0; /* We don't know anything about this device! */
|
||||
info->sectors = 0;
|
||||
info->sectorsize = 0;
|
||||
*handle = 0;
|
||||
|
||||
/* Get some device information: device name, class, and mount status */
|
||||
status = sys$getdviw(0,0,&devdsc, &dvi_itmlst, 0,0,0,0);
|
||||
if (status & 1)
|
||||
{
|
||||
if (devclass != DC$_DISK) /* If not a disk, return an error */
|
||||
return (SS$_IVDEVNAM);
|
||||
|
||||
if (!(devchar & DEV$M_MNT))
|
||||
return (SS$_DEVNOTMOUNT);
|
||||
#if 0
|
||||
/*
|
||||
* This code will mount the disk if it's not already mounted. However,
|
||||
* there's no good way to ensure we dismount a disk we mounted (no
|
||||
* easy way to walk the list of devices at exit), so it's been #ifdefed
|
||||
* out. If you enable it, the "mount" command will mount the disk, but
|
||||
* it'll stay mounted by the process running ODS2, even after image exit.
|
||||
*/
|
||||
{
|
||||
mnt_itmlst[0].length = strlen(devname);
|
||||
mnt_itmlst[0].buffer = &devname;
|
||||
mntflags[0] = MNT$M_FOREIGN | MNT$M_NOWRITE | MNT$M_NOASSIST |
|
||||
MNT$M_NOMNTVER;
|
||||
mntflags[1] = 0;
|
||||
|
||||
status = sys$mount(&mnt_itmlst);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!(status & 1))
|
||||
return (status);
|
||||
|
||||
return sys$assign(&devdsc,handle,0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
15
extracters/ods2/resource.h
Normal file
15
extracters/ods2/resource.h
Normal file
@@ -0,0 +1,15 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by ODS2.rc
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,4 +1,5 @@
|
||||
/* Rms.c v1.2 RMS components */
|
||||
/* check for cr - return terminator - update file length */
|
||||
/* RMS.c v1.3 RMS components */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -24,11 +25,12 @@
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#define NO_DOLLAR
|
||||
#define RMS$INITIALIZE /* used by rms.h to create templates */
|
||||
#include "descrip.h"
|
||||
#include "ssdef.h"
|
||||
#include "fibdef.h"
|
||||
|
||||
#define RMS_INITIALIZE doit /* used by rms.h to create templates */
|
||||
#include "rms.h"
|
||||
#include "access.h"
|
||||
#include "direct.h"
|
||||
@@ -130,7 +132,7 @@ int dircmp(unsigned keylen,void *key,void *node)
|
||||
register struct DIRCACHE *dirnode = (struct DIRCACHE *) node;
|
||||
register int cmp = keylen - dirnode->dirlen;
|
||||
if (cmp == 0) {
|
||||
register unsigned len = keylen;
|
||||
register int len = keylen;
|
||||
register char *keynam = (char *) key;
|
||||
register char *dirnam = dirnode->dirnam;
|
||||
while (len-- > 0) {
|
||||
@@ -154,8 +156,8 @@ unsigned dircache(struct VCB *vcb,char *dirnam,int dirlen,struct fiddef *dirid)
|
||||
dirid->fid$b_nmx = 0;
|
||||
return 1;
|
||||
} else {
|
||||
unsigned create = 0;
|
||||
dir = cachesearch((void *) &vcb->dircache,0,dirlen,dirnam,dircmp,&create);
|
||||
unsigned sts;
|
||||
dir = cache_find((void *) &vcb->dircache,dirlen,dirnam,&sts,dircmp,NULL);
|
||||
if (dir != NULL) {
|
||||
memcpy(dirid,&dir->dirid,sizeof(struct fiddef));
|
||||
return 1;
|
||||
@@ -195,7 +197,7 @@ struct WCCDIR {
|
||||
int wcd_wcc;
|
||||
int wcd_prelen;
|
||||
unsigned short wcd_reslen;
|
||||
struct dsc$descriptor wcd_serdsc;
|
||||
struct dsc_descriptor wcd_serdsc;
|
||||
struct fiddef wcd_dirid;
|
||||
char wcd_sernam[1]; /* Must be last in structure */
|
||||
}; /* Directory context */
|
||||
@@ -244,7 +246,7 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
|
||||
int sts;
|
||||
struct fibdef fibblk;
|
||||
struct WCCDIR *wcc;
|
||||
struct dsc$descriptor fibdsc,resdsc;
|
||||
struct dsc_descriptor fibdsc,resdsc;
|
||||
struct NAM *nam = fab->fab$l_nam;
|
||||
wcc = &wccfile->wcf_wcd;
|
||||
if (fab->fab$w_ifi != 0) return RMS$_IFI;
|
||||
@@ -254,15 +256,15 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
|
||||
while ((wcc->wcd_status & STATUS_INIT) == 0 && wcc->wcd_next != NULL) {
|
||||
wcc = wcc->wcd_next;
|
||||
}
|
||||
fibdsc.dsc$w_length = sizeof(struct fibdef);
|
||||
fibdsc.dsc$a_pointer = (char *) &fibblk;
|
||||
fibdsc.dsc_w_length = sizeof(struct fibdef);
|
||||
fibdsc.dsc_a_pointer = (char *) &fibblk;
|
||||
while (1) {
|
||||
if ((wcc->wcd_status & STATUS_INIT) == 0 || wcc->wcd_wcc != 0) {
|
||||
wcc->wcd_status |= STATUS_INIT;
|
||||
resdsc.dsc$w_length = 256 - wcc->wcd_prelen;
|
||||
resdsc.dsc$a_pointer = wccfile->wcf_result + wcc->wcd_prelen;
|
||||
resdsc.dsc_w_length = 256 - wcc->wcd_prelen;
|
||||
resdsc.dsc_a_pointer = wccfile->wcf_result + wcc->wcd_prelen;
|
||||
memcpy(&fibblk.fib$w_did_num,&wcc->wcd_dirid,sizeof(struct fiddef));
|
||||
fibblk.fib$w_nmctl = 0; /* FIB$M_WILD; */
|
||||
fibblk.fib$w_nmctl = 0; /* FIB_M_WILD; */
|
||||
fibblk.fib$l_acctl = 0;
|
||||
fibblk.fib$w_fid_num = 0;
|
||||
fibblk.fib$w_fid_seq = 0;
|
||||
@@ -270,7 +272,7 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
|
||||
fibblk.fib$b_fid_nmx = 0;
|
||||
fibblk.fib$l_wcc = wcc->wcd_wcc;
|
||||
#ifdef DEBUG
|
||||
wcc->wcd_sernam[wcc->wcd_serdsc.dsc$w_length] = '\0';
|
||||
wcc->wcd_sernam[wcc->wcd_serdsc.dsc_w_length] = '\0';
|
||||
wccfile->wcf_result[wcc->wcd_prelen + wcc->wcd_reslen] = '\0';
|
||||
printf("Ser: '%s' (%d,%d,%d) WCC: %d Prelen: %d '%s'\n",wcc->wcd_sernam,
|
||||
fibblk.fib$w_did_num | (fibblk.fib$b_did_nmx << 16),
|
||||
@@ -361,8 +363,8 @@ unsigned do_search(struct FAB *fab,struct WCCFILE *wccfile)
|
||||
}
|
||||
wcc->wcd_next = newwcc;
|
||||
memcpy(&newwcc->wcd_dirid,&wcc->wcd_dirid,sizeof(struct fiddef));
|
||||
newwcc->wcd_serdsc.dsc$w_length = 7;
|
||||
newwcc->wcd_serdsc.dsc$a_pointer = newwcc->wcd_sernam;
|
||||
newwcc->wcd_serdsc.dsc_w_length = 7;
|
||||
newwcc->wcd_serdsc.dsc_a_pointer = newwcc->wcd_sernam;
|
||||
memcpy(newwcc->wcd_sernam,"*.DIR;1",7);
|
||||
newwcc->wcd_prelen = wcc->wcd_prelen;
|
||||
wcc = newwcc;
|
||||
@@ -447,6 +449,7 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
|
||||
{
|
||||
wccfile = (struct WCCFILE *) malloc(sizeof(struct WCCFILE) + 256);
|
||||
if (wccfile == NULL) return SS$_INSFMEM;
|
||||
memset(wccfile,0,sizeof(struct WCCFILE)+256);
|
||||
wccfile->wcf_fab = fab;
|
||||
wccfile->wcf_vcb = NULL;
|
||||
wccfile->wcf_fcb = NULL;
|
||||
@@ -610,8 +613,8 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
|
||||
wcd->wcd_reslen = 0;
|
||||
memcpy(wcd->wcd_sernam,dirnam + dirsiz,seglen);
|
||||
memcpy(wcd->wcd_sernam + seglen,".DIR;1",7);
|
||||
wcd->wcd_serdsc.dsc$w_length = seglen + 6;
|
||||
wcd->wcd_serdsc.dsc$a_pointer = wcd->wcd_sernam;
|
||||
wcd->wcd_serdsc.dsc_w_length = seglen + 6;
|
||||
wcd->wcd_serdsc.dsc_a_pointer = wcd->wcd_sernam;
|
||||
wcd->wcd_prev = wcc;
|
||||
wcd->wcd_next = wcc->wcd_next;
|
||||
if (wcc->wcd_next != NULL) wcc->wcd_next->wcd_prev = wcd;
|
||||
@@ -623,19 +626,19 @@ unsigned do_parse(struct FAB *fab,struct WCCFILE **wccret)
|
||||
wcc->wcd_wcc = 0;
|
||||
wcc->wcd_status = 0;
|
||||
wcc->wcd_reslen = 0;
|
||||
wcc->wcd_serdsc.dsc$w_length = fna_size[2] + fna_size[3] + fna_size[4];
|
||||
wcc->wcd_serdsc.dsc$a_pointer = wcc->wcd_sernam;
|
||||
wcc->wcd_serdsc.dsc_w_length = fna_size[2] + fna_size[3] + fna_size[4];
|
||||
wcc->wcd_serdsc.dsc_a_pointer = wcc->wcd_sernam;
|
||||
memcpy(wcc->wcd_sernam,wccfile->wcf_result + fna_size[0] + fna_size[1],
|
||||
wcc->wcd_serdsc.dsc$w_length);
|
||||
wcc->wcd_serdsc.dsc_w_length);
|
||||
#ifdef DEBUG
|
||||
wcc->wcd_sernam[wcc->wcd_serdsc.dsc$w_length] = '\0';
|
||||
wcc->wcd_sernam[wcc->wcd_serdsc.dsc_w_length] = '\0';
|
||||
printf("Parse spec is %s\n",wccfile->wcf_wcd.wcd_sernam);
|
||||
for (dirsiz = 0; dirsiz < 5; dirsiz++) printf(" %d",fna_size[dirsiz]);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
if (wccret != NULL) *wccret = wccfile;
|
||||
if (nam != NULL) nam->nam$l_wcc = (int) wccfile;
|
||||
if (nam != NULL) nam->nam$l_wcc = wccfile;
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
|
||||
@@ -652,15 +655,15 @@ unsigned sys_parse(struct FAB *fab)
|
||||
|
||||
/* Function to set default directory (heck we can sneak in the device...) */
|
||||
|
||||
unsigned sys_setddir(struct dsc$descriptor *newdir,unsigned short *oldlen,
|
||||
struct dsc$descriptor *olddir)
|
||||
unsigned sys_setddir(struct dsc_descriptor *newdir,unsigned short *oldlen,
|
||||
struct dsc_descriptor *olddir)
|
||||
{
|
||||
unsigned sts = 1;
|
||||
if (oldlen != NULL) {
|
||||
int retlen = default_size[0] + default_size[1];
|
||||
if (retlen > olddir->dsc$w_length) retlen = olddir->dsc$w_length;
|
||||
if (retlen > olddir->dsc_w_length) retlen = olddir->dsc_w_length;
|
||||
*oldlen = retlen;
|
||||
memcpy(olddir->dsc$a_pointer,default_name,retlen);
|
||||
memcpy(olddir->dsc_a_pointer,default_name,retlen);
|
||||
}
|
||||
if (newdir != NULL) {
|
||||
struct FAB fab = cc$rms_fab;
|
||||
@@ -669,8 +672,8 @@ unsigned sys_setddir(struct dsc$descriptor *newdir,unsigned short *oldlen,
|
||||
nam.nam$b_nop |= NAM$M_SYNCHK;
|
||||
nam.nam$b_ess = DEFAULT_SIZE;
|
||||
nam.nam$l_esa = default_buffer;
|
||||
fab.fab$b_fns = newdir->dsc$w_length;
|
||||
fab.fab$l_fna = newdir->dsc$a_pointer;
|
||||
fab.fab$b_fns = newdir->dsc_w_length;
|
||||
fab.fab$l_fna = newdir->dsc_a_pointer;
|
||||
sts = sys_parse(&fab);
|
||||
if (sts & 1) {
|
||||
if (nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver > 2) return RMS$_DIR;
|
||||
@@ -710,9 +713,12 @@ unsigned sys_disconnect(struct RAB *rab)
|
||||
|
||||
|
||||
|
||||
#define IFI_MAX 10
|
||||
#define IFI_MAX 64
|
||||
struct WCCFILE *ifi_table[] = {
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -720,157 +726,275 @@ struct WCCFILE *ifi_table[] = {
|
||||
|
||||
unsigned sys_get(struct RAB *rab)
|
||||
{
|
||||
char delim,*buffer,*output;
|
||||
unsigned cpylen,reclen,block,blocks,offset,eofblk;
|
||||
unsigned endflg,rfm,sts;
|
||||
char *buffer,*recbuff;
|
||||
unsigned block,blocks,offset;
|
||||
unsigned cpylen,reclen;
|
||||
unsigned delim,rfm,sts;
|
||||
struct VIOC *vioc;
|
||||
struct FCB *fcb = ifi_table[rab->rab$l_fab->fab$w_ifi]->wcf_fcb;
|
||||
|
||||
rfm = rab->rab$l_fab->fab$b_rfm;
|
||||
if (rfm == FAB$C_STM || rfm == FAB$C_STMCR || rfm == FAB$C_STMLF) {
|
||||
delim = 1;
|
||||
if (rfm == FAB$C_STMLF) {
|
||||
delim = '\n';
|
||||
} else {
|
||||
if (rfm == FAB$C_STMCR) delim = '\r';
|
||||
}
|
||||
reclen = rab->rab$w_usz;
|
||||
} else {
|
||||
delim = 0;
|
||||
if (rfm == FAB$C_FIX) {
|
||||
reclen = rab->rab$w_usz;
|
||||
recbuff = rab->rab$l_ubf;
|
||||
delim = 0;
|
||||
switch (rfm = rab->rab$l_fab->fab$b_rfm) {
|
||||
case FAB$C_STMLF:
|
||||
delim = 1;
|
||||
break;
|
||||
case FAB$C_STMCR:
|
||||
delim = 2;
|
||||
break;
|
||||
case FAB$C_STM:
|
||||
delim = 3;
|
||||
break;
|
||||
case FAB$C_VFC:
|
||||
reclen += rab->rab$l_fab->fab$b_fsz;
|
||||
break;
|
||||
case FAB$C_FIX:
|
||||
if (reclen < rab->rab$l_fab->fab$w_mrs) return RMS$_RTB;
|
||||
reclen = rab->rab$l_fab->fab$w_mrs;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
offset = rab->rab$w_rfa[2] + rab->rab$w_rsz;
|
||||
offset = rab->rab$w_rfa[2] % 512;
|
||||
block = (rab->rab$w_rfa[1] << 16) + rab->rab$w_rfa[0];
|
||||
if (block == 0 && offset == 0) {
|
||||
block = 1;
|
||||
} else {
|
||||
if (rab->rab$b_rac != RAB$C_RFA) {
|
||||
if (delim) {
|
||||
offset++;
|
||||
} else {
|
||||
if (rfm == FAB$C_VAR) {
|
||||
offset += 2;
|
||||
} else {
|
||||
if (rfm == FAB$C_VFC) offset += 2 + rab->rab$l_fab->fab$b_fsz;
|
||||
if (block == 0) block = 1;
|
||||
|
||||
{
|
||||
unsigned eofblk = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_efblk);
|
||||
if (block > eofblk || (block == eofblk &&
|
||||
offset >= VMSWORD(fcb->head->fh2$w_recattr.fat$w_ffbyte))) return RMS$_EOF;
|
||||
}
|
||||
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0);
|
||||
if ((sts & 1) == 0) {
|
||||
if (sts == SS$_ENDOFFILE) sts = RMS$_EOF;
|
||||
return sts;
|
||||
}
|
||||
|
||||
if (rfm == FAB$C_VAR || rfm == FAB$C_VFC) {
|
||||
vmsword *lenptr = (vmsword *) (buffer + offset);
|
||||
reclen = VMSWORD(*lenptr);
|
||||
offset += 2;
|
||||
if (reclen > rab->rab$w_usz) {
|
||||
sts = deaccesschunk(vioc,0,0,0);
|
||||
return RMS$_RTB;
|
||||
}
|
||||
}
|
||||
|
||||
cpylen = 0;
|
||||
while (1) {
|
||||
int dellen = 0;
|
||||
int seglen = blocks * 512 - offset;
|
||||
if (delim) {
|
||||
if (delim >= 3) {
|
||||
char *ptr = buffer + offset;
|
||||
if (dellen == 1 && *ptr != '\n') {
|
||||
if (cpylen >= reclen) {
|
||||
seglen = 0;
|
||||
sts = RMS$_RTB;
|
||||
} else {
|
||||
*recbuff++ = '\r';
|
||||
cpylen++;
|
||||
}
|
||||
}
|
||||
if (offset & 1) offset++;
|
||||
if (rab->rab$l_fab->fab$b_rat & FAB$M_BLK) offset = (offset + 511) / 512 * 512;
|
||||
while (seglen-- > 0) {
|
||||
char ch = *ptr++;
|
||||
if (ch == '\n' || ch == '\f' || ch == '\v') {
|
||||
if (ch == '\n') {
|
||||
dellen++;
|
||||
} else {
|
||||
dellen = 0;
|
||||
}
|
||||
delim = 99;
|
||||
break;
|
||||
}
|
||||
dellen = 0;
|
||||
if (ch == '\r') dellen = 1;
|
||||
}
|
||||
seglen = ptr - (buffer + offset) - dellen;;
|
||||
} else {
|
||||
char *ptr = buffer + offset;
|
||||
char term = '\r';
|
||||
if (delim == 1) term = '\n';
|
||||
while (seglen-- > 0) {
|
||||
if (*ptr++ == term) {
|
||||
dellen = 1;
|
||||
delim = 99;
|
||||
break;
|
||||
}
|
||||
}
|
||||
seglen = ptr - (buffer + offset) - dellen;;
|
||||
}
|
||||
block += offset / 512;
|
||||
} else {
|
||||
if (seglen > reclen - cpylen) seglen = reclen - cpylen;
|
||||
if (rfm == FAB$C_VFC && cpylen < rab->rab$l_fab->fab$b_fsz) {
|
||||
unsigned fsz = rab->rab$l_fab->fab$b_fsz - cpylen;
|
||||
if (fsz > seglen) fsz = seglen;
|
||||
if (rab->rab$l_rhb) memcpy(rab->rab$l_rhb + cpylen,buffer + offset,fsz);
|
||||
cpylen += fsz;
|
||||
offset += fsz;
|
||||
seglen -= fsz;
|
||||
}
|
||||
}
|
||||
if (seglen) {
|
||||
if (cpylen + seglen > reclen) {
|
||||
seglen = reclen - cpylen;
|
||||
sts = RMS$_RTB;
|
||||
}
|
||||
memcpy(recbuff,buffer + offset,seglen);
|
||||
recbuff += seglen;
|
||||
cpylen += seglen;
|
||||
}
|
||||
offset += seglen + dellen;
|
||||
if ((offset & 1) && (rfm == FAB$C_VAR || rfm == FAB$C_VFC)) offset++;
|
||||
deaccesschunk(vioc,0,0,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
block += offset / 512;
|
||||
offset %= 512;
|
||||
if ((delim == 0 && cpylen >= reclen) || delim == 99) {
|
||||
break;
|
||||
} else {
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0);
|
||||
if ((sts & 1) == 0) {
|
||||
if (sts == SS$_ENDOFFILE) sts = RMS$_EOF;
|
||||
return sts;
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
if (rfm == FAB$C_VFC) cpylen -= rab->rab$l_fab->fab$b_fsz;
|
||||
rab->rab$w_rsz = cpylen;
|
||||
|
||||
rab->rab$w_rfa[0] = block & 0xffff;
|
||||
rab->rab$w_rfa[1] = block >> 16;
|
||||
rab->rab$w_rfa[2] = offset = offset % 512;
|
||||
rab->rab$w_rfa[2] = offset;
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
eofblk = swapw(fcb->head->fh2$w_recattr.fat$l_efblk);
|
||||
if (block > eofblk || (block == eofblk &&
|
||||
offset >= fcb->head->fh2$w_recattr.fat$w_ffbyte)) return RMS$_EOF;
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0,NULL);
|
||||
/* put for sequential files */
|
||||
|
||||
unsigned sys_put(struct RAB *rab)
|
||||
{
|
||||
char *buffer,*recbuff;
|
||||
unsigned block,blocks,offset;
|
||||
unsigned cpylen,reclen;
|
||||
unsigned delim,rfm,sts;
|
||||
struct VIOC *vioc;
|
||||
struct FCB *fcb = ifi_table[rab->rab$l_fab->fab$w_ifi]->wcf_fcb;
|
||||
|
||||
reclen = rab->rab$w_rsz;
|
||||
recbuff = rab->rab$l_rbf;
|
||||
delim = 0;
|
||||
switch (rfm = rab->rab$l_fab->fab$b_rfm) {
|
||||
case FAB$C_STMLF:
|
||||
if (reclen < 1) {
|
||||
delim = 1;
|
||||
} else {
|
||||
if (recbuff[reclen] != '\n') delim = 1;
|
||||
}
|
||||
break;
|
||||
case FAB$C_STMCR:
|
||||
if (reclen < 1) {
|
||||
delim = 2;
|
||||
} else {
|
||||
if (recbuff[reclen] != '\r') delim = 2;
|
||||
}
|
||||
break;
|
||||
case FAB$C_STM:
|
||||
if (reclen < 2) {
|
||||
delim = 3;
|
||||
} else {
|
||||
if (recbuff[reclen-1] != '\r' || recbuff[reclen] != '\n') delim = 3;
|
||||
}
|
||||
break;
|
||||
case FAB$C_VFC:
|
||||
reclen += rab->rab$l_fab->fab$b_fsz;
|
||||
break;
|
||||
case FAB$C_FIX:
|
||||
if (reclen != rab->rab$l_fab->fab$w_mrs) return RMS$_RSZ;
|
||||
break;
|
||||
}
|
||||
|
||||
block = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_efblk);
|
||||
offset = VMSWORD(fcb->head->fh2$w_recattr.fat$w_ffbyte);
|
||||
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
|
||||
if (rfm == FAB$C_VAR || rfm == FAB$C_VFC) {
|
||||
unsigned short *lenptr = (unsigned short *) (buffer + offset);
|
||||
reclen = *lenptr;
|
||||
vmsword *lenptr = (vmsword *) (buffer + offset);
|
||||
*lenptr = VMSWORD(reclen);
|
||||
offset += 2;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("Block %d Offset %d Reclen %d Eofblk %d\n",block,offset,reclen,eofblk);
|
||||
#endif
|
||||
|
||||
if (reclen > rab->rab$w_usz) {
|
||||
sts = deaccesschunk(vioc,0,0);
|
||||
return RMS$_RTB;
|
||||
}
|
||||
endflg = 0;
|
||||
if (block + reclen / 512 >= eofblk) {
|
||||
unsigned remaining = (eofblk - block) * 512 - offset +
|
||||
fcb->head->fh2$w_recattr.fat$w_ffbyte;
|
||||
if (remaining < reclen) {
|
||||
reclen = remaining;
|
||||
endflg = 1;
|
||||
}
|
||||
}
|
||||
cpylen = 0;
|
||||
output = rab->rab$l_ubf;
|
||||
while (cpylen < reclen) {
|
||||
unsigned seglen = blocks * 512 - offset;
|
||||
while (1) {
|
||||
int seglen = blocks * 512 - offset;
|
||||
if (seglen > reclen - cpylen) seglen = reclen - cpylen;
|
||||
if (delim) {
|
||||
char *inptr = buffer + offset;
|
||||
if (delim != 1) {
|
||||
while (seglen-- > 0) {
|
||||
char ch = *inptr++;
|
||||
if (ch == delim) {
|
||||
reclen = cpylen;
|
||||
break;
|
||||
}
|
||||
if (cpylen++ < reclen) {
|
||||
*output++ = ch;
|
||||
} else {
|
||||
sts = RMS$_RTB;
|
||||
reclen = cpylen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rfm == FAB$C_VFC && cpylen < rab->rab$l_fab->fab$b_fsz) {
|
||||
unsigned fsz = rab->rab$l_fab->fab$b_fsz - cpylen;
|
||||
if (fsz > seglen) fsz = seglen;
|
||||
if (rab->rab$l_rhb) {
|
||||
memcpy(buffer + offset,rab->rab$l_rhb + cpylen,fsz);
|
||||
} else {
|
||||
while (seglen-- > 0) {
|
||||
char ch = *inptr++;
|
||||
if (ch != 0 || cpylen > 0) {
|
||||
if (ch == '\f' || ch == '\v' || ch == '\n' || ch == '\r') {
|
||||
reclen = cpylen;
|
||||
} else {
|
||||
if (cpylen++ < reclen) {
|
||||
*output++ = ch;
|
||||
} else {
|
||||
sts = RMS$_RTB;
|
||||
reclen = cpylen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cpylen == reclen && endflg) break;
|
||||
} else {
|
||||
if (rfm == FAB$C_VFC) {
|
||||
unsigned fsz = rab->rab$l_fab->fab$b_fsz;
|
||||
if (fsz > seglen) fsz = seglen;
|
||||
if (cpylen < fsz) {
|
||||
fsz = fsz - cpylen;
|
||||
if (rab->rab$l_rhb) memcpy(rab->rab$l_rhb + cpylen,buffer + offset,fsz);
|
||||
cpylen += fsz;
|
||||
offset += fsz;
|
||||
seglen -= fsz;
|
||||
}
|
||||
}
|
||||
memcpy(output,buffer + offset,seglen);
|
||||
output += seglen;
|
||||
cpylen += seglen;
|
||||
memset(buffer + offset,0,fsz);
|
||||
}
|
||||
cpylen += fsz;
|
||||
offset += fsz;
|
||||
seglen -= fsz;
|
||||
}
|
||||
if (cpylen < reclen) {
|
||||
sts = deaccesschunk(vioc,0,0);
|
||||
block += blocks;
|
||||
if (block > eofblk) return RMS$_EOF;
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,0,NULL);
|
||||
if (seglen) {
|
||||
memcpy(buffer + offset,recbuff,seglen);
|
||||
recbuff += seglen;
|
||||
cpylen += seglen;
|
||||
offset += seglen;
|
||||
}
|
||||
if (delim && offset < blocks * 512) {
|
||||
offset++;
|
||||
switch (delim) {
|
||||
case 1:
|
||||
*buffer = '\n';
|
||||
delim = 0;
|
||||
break;
|
||||
case 2:
|
||||
*buffer = '\r';
|
||||
delim = 0;
|
||||
break;
|
||||
case 3:
|
||||
*buffer = '\r';
|
||||
if (offset < blocks * 512) {
|
||||
offset++;
|
||||
*buffer = '\n';
|
||||
delim = 0;
|
||||
} else {
|
||||
delim = 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
sts = deaccesschunk(vioc,block,blocks,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
block += blocks;
|
||||
if (cpylen >= reclen && delim == 0) {
|
||||
break;
|
||||
} else {
|
||||
sts = accesschunk(fcb,block,&vioc,&buffer,&blocks,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
if (rfm == FAB$C_VFC) {
|
||||
rab->rab$w_rsz = cpylen - rab->rab$l_fab->fab$b_fsz;;
|
||||
} else {
|
||||
rab->rab$w_rsz = cpylen;
|
||||
}
|
||||
deaccesschunk(vioc,0,1);
|
||||
if ((offset & 1) && (rfm == FAB$C_VAR || rfm == FAB$C_VFC)) offset++;
|
||||
block += offset / 512;
|
||||
offset %= 512;
|
||||
fcb->head->fh2$w_recattr.fat$l_efblk = VMSSWAP(block);
|
||||
fcb->head->fh2$w_recattr.fat$w_ffbyte = VMSWORD(offset);
|
||||
rab->rab$w_rfa[0] = block & 0xffff;
|
||||
rab->rab$w_rfa[1] = block >> 16;
|
||||
rab->rab$w_rfa[2] = offset;
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/* display to fill fab & xabs with info from the file header... */
|
||||
|
||||
unsigned sys_display(struct FAB *fab)
|
||||
@@ -882,45 +1006,45 @@ unsigned sys_display(struct FAB *fab)
|
||||
struct IDENT *id = (struct IDENT *) (pp + head->fh2$b_idoffset);
|
||||
int ifi_no = fab->fab$w_ifi;
|
||||
if (ifi_no == 0 || ifi_no >= IFI_MAX) return RMS$_IFI;
|
||||
fab->fab$l_alq = swapw(head->fh2$w_recattr.fat$l_hiblk);
|
||||
fab->fab$l_alq = VMSSWAP(head->fh2$w_recattr.fat$l_hiblk);
|
||||
fab->fab$b_bks = head->fh2$w_recattr.fat$b_bktsize;
|
||||
fab->fab$w_deq = head->fh2$w_recattr.fat$w_defext;
|
||||
fab->fab$w_deq = VMSWORD(head->fh2$w_recattr.fat$w_defext);
|
||||
fab->fab$b_fsz = head->fh2$w_recattr.fat$b_vfcsize;
|
||||
fab->fab$w_gbc = head->fh2$w_recattr.fat$w_gbc;
|
||||
fab->fab$w_mrs = head->fh2$w_recattr.fat$w_maxrec;
|
||||
fab->fab$w_gbc = VMSWORD(head->fh2$w_recattr.fat$w_gbc);
|
||||
fab->fab$w_mrs = VMSWORD(head->fh2$w_recattr.fat$w_maxrec);
|
||||
fab->fab$b_org = head->fh2$w_recattr.fat$b_rtype & 0xf0;
|
||||
fab->fab$b_rfm = head->fh2$w_recattr.fat$b_rtype & 0x0f;
|
||||
fab->fab$b_rat = head->fh2$w_recattr.fat$b_rattrib;
|
||||
while (xab != NULL) {
|
||||
switch (xab->xab$b_cod) {
|
||||
case XAB$C_DAT:
|
||||
memcpy(&xab->xab$q_bdt,&id->fi2$q_bakdate,sizeof(struct TIME));
|
||||
memcpy(&xab->xab$q_cdt,&id->fi2$q_credate,sizeof(struct TIME));
|
||||
memcpy(&xab->xab$q_edt,&id->fi2$q_expdate,sizeof(struct TIME));
|
||||
memcpy(&xab->xab$q_rdt,&id->fi2$q_revdate,sizeof(struct TIME));
|
||||
memcpy(&xab->xab$q_bdt,id->fi2$q_bakdate,sizeof(id->fi2$q_bakdate));
|
||||
memcpy(&xab->xab$q_cdt,id->fi2$q_credate,sizeof(id->fi2$q_credate));
|
||||
memcpy(&xab->xab$q_edt,id->fi2$q_expdate,sizeof(id->fi2$q_expdate));
|
||||
memcpy(&xab->xab$q_rdt,id->fi2$q_revdate,sizeof(id->fi2$q_revdate));
|
||||
xab->xab$w_rvn = id->fi2$w_revision;
|
||||
break;
|
||||
case XAB$C_FHC:{
|
||||
struct XABFHC *fhc = (struct XABFHC *) xab;
|
||||
fhc->xab$b_atr = head->fh2$w_recattr.fat$b_rattrib;
|
||||
fhc->xab$b_bkz = head->fh2$w_recattr.fat$b_bktsize;
|
||||
fhc->xab$w_dxq = head->fh2$w_recattr.fat$w_defext;
|
||||
fhc->xab$l_ebk = swapw(head->fh2$w_recattr.fat$l_efblk);
|
||||
fhc->xab$w_ffb = head->fh2$w_recattr.fat$w_ffbyte;
|
||||
fhc->xab$w_dxq = VMSWORD(head->fh2$w_recattr.fat$w_defext);
|
||||
fhc->xab$l_ebk = VMSSWAP(head->fh2$w_recattr.fat$l_efblk);
|
||||
fhc->xab$w_ffb = VMSWORD(head->fh2$w_recattr.fat$w_ffbyte);
|
||||
if (fhc->xab$l_ebk == 0) {
|
||||
fhc->xab$l_ebk = fab->fab$l_alq;
|
||||
if (fhc->xab$w_ffb == 0) fhc->xab$l_ebk++;
|
||||
}
|
||||
fhc->xab$w_gbc = head->fh2$w_recattr.fat$w_gbc;
|
||||
fhc->xab$l_hbk = swapw(head->fh2$w_recattr.fat$l_hiblk);
|
||||
fhc->xab$w_gbc = VMSWORD(head->fh2$w_recattr.fat$w_gbc);
|
||||
fhc->xab$l_hbk = VMSSWAP(head->fh2$w_recattr.fat$l_hiblk);
|
||||
fhc->xab$b_hsz = head->fh2$w_recattr.fat$b_vfcsize;
|
||||
fhc->xab$w_lrl = head->fh2$w_recattr.fat$w_maxrec;
|
||||
fhc->xab$w_verlimit = head->fh2$w_recattr.fat$w_versions;
|
||||
fhc->xab$w_lrl = VMSWORD(head->fh2$w_recattr.fat$w_maxrec);
|
||||
fhc->xab$w_verlimit = VMSWORD(head->fh2$w_recattr.fat$w_versions);
|
||||
}
|
||||
break;
|
||||
case XAB$C_PRO:{
|
||||
struct XABPRO *pro = (struct XABPRO *) xab;
|
||||
pro->xab$w_pro = head->fh2$w_fileprot;
|
||||
pro->xab$w_pro = VMSWORD(head->fh2$w_fileprot);
|
||||
memcpy(&pro->xab$l_uic,&head->fh2$l_fileowner,4);
|
||||
}
|
||||
}
|
||||
@@ -981,10 +1105,13 @@ unsigned sys_open(struct FAB *fab)
|
||||
} else {
|
||||
sts = 1;
|
||||
}
|
||||
if (sts & 1) sts = accessfile(wccfile->wcf_vcb,&wccfile->wcf_fid,&wccfile->wcf_fcb,0);
|
||||
if (sts & 1) sts = accessfile(wccfile->wcf_vcb,&wccfile->wcf_fid,&wccfile->wcf_fcb,
|
||||
fab->fab$b_fac & (FAB$M_PUT | FAB$M_UPD));
|
||||
if (sts & 1) {
|
||||
struct HEAD *head = wccfile->wcf_fcb->head;
|
||||
ifi_table[ifi_no] = wccfile;
|
||||
fab->fab$w_ifi = ifi_no;
|
||||
if (head->fh2$w_recattr.fat$b_rtype == 0) head->fh2$w_recattr.fat$b_rtype = FAB$C_STMLF;
|
||||
sys_display(fab);
|
||||
}
|
||||
if (wcc_flag && ((sts & 1) == 0)) {
|
||||
@@ -1025,11 +1152,11 @@ unsigned sys_erase(struct FAB *fab)
|
||||
}
|
||||
if (sts & 1) {
|
||||
struct fibdef fibblk;
|
||||
struct dsc$descriptor fibdsc,serdsc;
|
||||
fibdsc.dsc$w_length = sizeof(struct fibdef);
|
||||
fibdsc.dsc$a_pointer = (char *) &fibblk;
|
||||
serdsc.dsc$w_length = wccfile->wcf_wcd.wcd_reslen;
|
||||
serdsc.dsc$a_pointer = wccfile->wcf_result + wccfile->wcf_wcd.wcd_prelen;
|
||||
struct dsc_descriptor fibdsc,serdsc;
|
||||
fibdsc.dsc_w_length = sizeof(struct fibdef);
|
||||
fibdsc.dsc_a_pointer = (char *) &fibblk;
|
||||
serdsc.dsc_w_length = wccfile->wcf_wcd.wcd_reslen;
|
||||
serdsc.dsc_a_pointer = wccfile->wcf_result + wccfile->wcf_wcd.wcd_prelen;
|
||||
memcpy(&fibblk.fib$w_did_num,&wccfile->wcf_wcd.wcd_dirid,sizeof(struct fiddef));
|
||||
fibblk.fib$w_nmctl = 0;
|
||||
fibblk.fib$l_acctl = 0;
|
||||
@@ -1039,7 +1166,11 @@ unsigned sys_erase(struct FAB *fab)
|
||||
fibblk.fib$b_fid_nmx = 0;
|
||||
fibblk.fib$l_wcc = 0;
|
||||
sts = direct(wccfile->wcf_vcb,&fibdsc,&serdsc,NULL,NULL,1);
|
||||
if (sts & 1) sts = accesserase(wccfile->wcf_vcb,&wccfile->wcf_fid);
|
||||
if (sts & 1) {
|
||||
sts = accesserase(wccfile->wcf_vcb,&wccfile->wcf_fid);
|
||||
} else {
|
||||
printf("Direct status is %d\n",sts);
|
||||
}
|
||||
}
|
||||
if (wcc_flag) {
|
||||
cleanup_wcf(wccfile);
|
||||
@@ -1047,3 +1178,72 @@ unsigned sys_erase(struct FAB *fab)
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
unsigned sys_create(struct FAB *fab)
|
||||
{
|
||||
unsigned sts;
|
||||
int ifi_no = 1;
|
||||
int wcc_flag = 0;
|
||||
struct WCCFILE *wccfile = NULL;
|
||||
struct NAM *nam = fab->fab$l_nam;
|
||||
if (fab->fab$w_ifi != 0) return RMS$_IFI;
|
||||
while (ifi_table[ifi_no] != NULL && ifi_no < IFI_MAX) ifi_no++;
|
||||
if (ifi_no >= IFI_MAX) return RMS$_IFI;
|
||||
if (nam != NULL) {
|
||||
wccfile = (struct WCCFILE *) fab->fab$l_nam->nam$l_wcc;
|
||||
}
|
||||
if (wccfile == NULL) {
|
||||
sts = do_parse(fab,&wccfile);
|
||||
if (sts & 1) {
|
||||
wcc_flag = 1;
|
||||
if (wccfile->wcf_status & STATUS_WILDCARD) {
|
||||
sts = RMS$_WLD;
|
||||
} else {
|
||||
sts = do_search(fab,wccfile);
|
||||
if (sts == RMS$_FNF) sts = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sts = 1;
|
||||
}
|
||||
if (sts & 1) {
|
||||
struct fibdef fibblk;
|
||||
struct dsc_descriptor fibdsc,serdsc;
|
||||
fibdsc.dsc_w_length = sizeof(struct fibdef);
|
||||
fibdsc.dsc_a_pointer = (char *) &fibblk;
|
||||
serdsc.dsc_w_length = wccfile->wcf_wcd.wcd_reslen;
|
||||
serdsc.dsc_a_pointer = wccfile->wcf_result + wccfile->wcf_wcd.wcd_prelen;
|
||||
memcpy(&fibblk.fib$w_did_num,&wccfile->wcf_wcd.wcd_dirid,sizeof(struct fiddef));
|
||||
fibblk.fib$w_nmctl = 0;
|
||||
fibblk.fib$l_acctl = 0;
|
||||
fibblk.fib$w_did_num = 11;
|
||||
fibblk.fib$w_did_seq = 1;
|
||||
fibblk.fib$b_did_rvn = 0;
|
||||
fibblk.fib$b_did_nmx = 0;
|
||||
fibblk.fib$l_wcc = 0;
|
||||
sts = update_create(wccfile->wcf_vcb,(struct fiddef *)&fibblk.fib$w_did_num,
|
||||
"TEST.FILE;1",(struct fiddef *)&fibblk.fib$w_fid_num,&wccfile->wcf_fcb);
|
||||
if (sts & 1)
|
||||
sts = direct(wccfile->wcf_vcb,&fibdsc,
|
||||
&wccfile->wcf_wcd.wcd_serdsc,NULL,NULL,2);
|
||||
if (sts & 1) {
|
||||
sts = update_extend(wccfile->wcf_fcb,100,0);
|
||||
ifi_table[ifi_no] = wccfile;
|
||||
fab->fab$w_ifi = ifi_no;
|
||||
}
|
||||
}
|
||||
cleanup_wcf(wccfile);
|
||||
if (nam != NULL) nam->nam$l_wcc = 0;
|
||||
return sts;
|
||||
}
|
||||
|
||||
unsigned sys_extend(struct FAB *fab)
|
||||
{
|
||||
int sts;
|
||||
int ifi_no = fab->fab$w_ifi;
|
||||
if (ifi_no < 1 || ifi_no >= IFI_MAX) return RMS$_IFI;
|
||||
sts = update_extend(ifi_table[ifi_no]->wcf_fcb,
|
||||
fab->fab$l_alq - ifi_table[ifi_no]->wcf_fcb->hiblock,0);
|
||||
return sts;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* RMS.H v1.2 RMS routine definitions */
|
||||
/* RMS.h v1.3 RMS routine definitions */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -10,14 +10,7 @@
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
/* If not using GNU C on VMS use real RMS structures :-)...
|
||||
otherwise define minimum subset to meet our requirements */
|
||||
|
||||
#if defined(VMS) && !defined(__GNUC__)
|
||||
|
||||
#include <rms.h>
|
||||
|
||||
#else
|
||||
#ifndef RMS$_RTB
|
||||
|
||||
#include "vmstime.h"
|
||||
|
||||
@@ -33,6 +26,7 @@
|
||||
#define RMS$_IFI 99684
|
||||
#define RMS$_NAM 99804
|
||||
#define RMS$_RSS 99988
|
||||
#define RMS$_RSZ 100004
|
||||
#define RMS$_WLD 100164
|
||||
#define RMS$_DNF 114762
|
||||
|
||||
@@ -44,20 +38,21 @@
|
||||
#define XAB$C_FHC 29
|
||||
#define XAB$C_PRO 19
|
||||
|
||||
|
||||
struct XABDAT {
|
||||
void *xab$l_nxt;
|
||||
int xab$b_cod;
|
||||
int xab$w_rvn;
|
||||
struct TIME xab$q_bdt;
|
||||
struct TIME xab$q_cdt;
|
||||
struct TIME xab$q_edt;
|
||||
struct TIME xab$q_rdt;
|
||||
VMSTIME xab$q_bdt;
|
||||
VMSTIME xab$q_cdt;
|
||||
VMSTIME xab$q_edt;
|
||||
VMSTIME xab$q_rdt;
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct XABDAT cc$rms_xabdat = {NULL,XAB$C_DAT,0,
|
||||
{{0,0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0,0}},
|
||||
{{0,0,0,0,0,0,0,0}}, {{0,0,0,0,0,0,0,0}}};
|
||||
VMSTIME_ZERO, VMSTIME_ZERO,
|
||||
VMSTIME_ZERO, VMSTIME_ZERO};
|
||||
#else
|
||||
extern struct XABDAT cc$rms_xabdat;
|
||||
#endif
|
||||
@@ -79,7 +74,7 @@ struct XABFHC {
|
||||
int xab$w_verlimit;
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct XABFHC cc$rms_xabfhc = {NULL,XAB$C_FHC,0,0,0,0,0,0,0,0,0,0};
|
||||
#else
|
||||
extern struct XABFHC cc$rms_xabfhc;
|
||||
@@ -94,12 +89,14 @@ struct XABPRO {
|
||||
int xab$l_uic;
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct XABPRO cc$rms_xabpro = {NULL,XAB$C_PRO,0,0};
|
||||
#else
|
||||
extern struct XABPRO cc$rms_xabpro;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NAM$M_WILDCARD 0x100
|
||||
|
||||
struct NAM {
|
||||
@@ -127,17 +124,18 @@ struct NAM {
|
||||
char *nam$l_type;
|
||||
int nam$b_ver;
|
||||
char *nam$l_ver;
|
||||
int nam$l_wcc;
|
||||
void *nam$l_wcc;
|
||||
int nam$b_nop;
|
||||
int nam$l_fnb;
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct NAM cc$rms_nam = {0,0,0,0,0,0,0,0,0,0,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,NULL,0,0,0};
|
||||
#else
|
||||
extern struct NAM cc$rms_nam;
|
||||
#endif
|
||||
|
||||
|
||||
#define RAB$C_SEQ 0
|
||||
#define RAB$C_RFA 2
|
||||
|
||||
@@ -145,19 +143,21 @@ struct RAB {
|
||||
struct FAB *rab$l_fab;
|
||||
char *rab$l_ubf;
|
||||
char *rab$l_rhb;
|
||||
char *rab$l_rbf;
|
||||
unsigned rab$w_usz;
|
||||
unsigned rab$w_rsz;
|
||||
int rab$b_rac;
|
||||
unsigned short rab$w_rfa[3];
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
struct RAB cc$rms_rab = {NULL,NULL,NULL,0,0,0,{0,0,0}};
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct RAB cc$rms_rab = {NULL,NULL,NULL,NULL,0,0,0,{0,0,0}};
|
||||
#else
|
||||
extern struct RAB cc$rms_rab;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define FAB$C_SEQ 0
|
||||
#define FAB$C_REL 16
|
||||
#define FAB$C_IDX 32
|
||||
@@ -168,6 +168,15 @@ extern struct RAB cc$rms_rab;
|
||||
#define FAB$M_PRN 4
|
||||
#define FAB$M_BLK 8
|
||||
|
||||
#define FAB$M_PUT 0x1
|
||||
#define FAB$M_GET 0x2
|
||||
#define FAB$M_DEL 0x4
|
||||
#define FAB$M_UPD 0x8
|
||||
#define FAB$M_TRN 0x10
|
||||
#define FAB$M_BIO 0x20
|
||||
#define FAB$M_BRO 0x40
|
||||
#define FAB$M_EXE 0x80
|
||||
|
||||
#define FAB$C_UDF 0
|
||||
#define FAB$C_FIX 1
|
||||
#define FAB$C_VAR 2
|
||||
@@ -193,17 +202,18 @@ struct FAB {
|
||||
int fab$b_org;
|
||||
int fab$b_rat;
|
||||
int fab$b_rfm;
|
||||
int fab$b_fac;
|
||||
void *fab$l_xab;
|
||||
};
|
||||
|
||||
#ifdef RMS_INITIALIZE
|
||||
struct FAB cc$rms_fab = {NULL,0,NULL,NULL,0,0,0,0,0,0,0,0,0,0,0,0,NULL};
|
||||
#ifdef RMS$INITIALIZE
|
||||
struct FAB cc$rms_fab = {NULL,0,NULL,NULL,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL};
|
||||
#else
|
||||
extern struct FAB cc$rms_fab;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_DOLLAR
|
||||
#define sys$search sys_search
|
||||
#define sys$parse sys_parse
|
||||
#define sys$setddir sys_setddir
|
||||
@@ -213,17 +223,22 @@ extern struct FAB cc$rms_fab;
|
||||
#define sys$display sys_display
|
||||
#define sys$close sys_close
|
||||
#define sys$open sys_open
|
||||
#define sys$create sys_create
|
||||
#define sys$erase sys_erase
|
||||
|
||||
#endif
|
||||
|
||||
unsigned sys_search(struct FAB *fab);
|
||||
unsigned sys_parse(struct FAB *fab);
|
||||
unsigned sys_connect(struct RAB *rab);
|
||||
unsigned sys_disconnect(struct RAB *rab);
|
||||
unsigned sys_get(struct RAB *rab);
|
||||
unsigned sys_put(struct RAB *rab);
|
||||
unsigned sys_display(struct FAB *fab);
|
||||
unsigned sys_close(struct FAB *fab);
|
||||
unsigned sys_open(struct FAB *fab);
|
||||
unsigned sys_create(struct FAB *fab);
|
||||
unsigned sys_erase(struct FAB *fab);
|
||||
unsigned sys_setddir(struct dsc$descriptor *newdir,unsigned short *oldlen,
|
||||
struct dsc$descriptor *olddir);
|
||||
unsigned sys_extend(struct FAB *fab);
|
||||
unsigned sys_setddir(struct dsc_descriptor *newdir,unsigned short *oldlen,
|
||||
struct dsc_descriptor *olddir);
|
||||
#endif
|
||||
|
||||
271
extracters/ods2/scsidefs.h
Normal file
271
extracters/ods2/scsidefs.h
Normal file
@@ -0,0 +1,271 @@
|
||||
//***************************************************************************
|
||||
//
|
||||
// Name: SCSIDEFS.H
|
||||
//
|
||||
// Description: SCSI definitions ('C' Language)
|
||||
//
|
||||
//***************************************************************************
|
||||
|
||||
//***************************************************************************
|
||||
// %%% TARGET STATUS VALUES %%%
|
||||
//***************************************************************************
|
||||
#define STATUS_GOOD 0x00 // Status Good
|
||||
#define STATUS_CHKCOND 0x02 // Check Condition
|
||||
#define STATUS_CONDMET 0x04 // Condition Met
|
||||
#define STATUS_BUSY 0x08 // Busy
|
||||
#define STATUS_INTERM 0x10 // Intermediate
|
||||
#define STATUS_INTCDMET 0x14 // Intermediate-condition met
|
||||
#define STATUS_RESCONF 0x18 // Reservation conflict
|
||||
#define STATUS_COMTERM 0x22 // Command Terminated
|
||||
#define STATUS_QFULL 0x28 // Queue full
|
||||
|
||||
//***************************************************************************
|
||||
// %%% SCSI MISCELLANEOUS EQUATES %%%
|
||||
//***************************************************************************
|
||||
#define MAXLUN 7 // Maximum Logical Unit Id
|
||||
#define MAXTARG 7 // Maximum Target Id
|
||||
#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs
|
||||
#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// %%% SCSI COMMAND OPCODES %%%
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//***************************************************************************
|
||||
// %%% Commands for all Device Types %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional)
|
||||
#define SCSI_COMPARE 0x39 // Compare (O)
|
||||
#define SCSI_COPY 0x18 // Copy (O)
|
||||
#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O)
|
||||
#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY)
|
||||
#define SCSI_LOG_SELECT 0x4C // Log Select (O)
|
||||
#define SCSI_LOG_SENSE 0x4D // Log Sense (O)
|
||||
#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific)
|
||||
#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific)
|
||||
#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific)
|
||||
#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific)
|
||||
#define SCSI_READ_BUFF 0x3C // Read Buffer (O)
|
||||
#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY)
|
||||
#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O)
|
||||
#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY)
|
||||
#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Direct Access Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_COMPARE 0x39 // Compare (O)
|
||||
#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY)
|
||||
#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O)
|
||||
#define SCSI_PREFETCH 0x34 // Prefetch (O)
|
||||
#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O)
|
||||
#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY)
|
||||
#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY)
|
||||
#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY)
|
||||
#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O)
|
||||
#define SCSI_READ_LONG 0x3E // Read Long (O)
|
||||
#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O)
|
||||
#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O)
|
||||
#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY)
|
||||
#define SCSI_REZERO 0x01 // Rezero Unit (O)
|
||||
#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O)
|
||||
#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O)
|
||||
#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O)
|
||||
#define SCSI_SEEK6 0x0B // Seek 6-Byte (O)
|
||||
#define SCSI_SEEK10 0x2B // Seek 10-Byte (O)
|
||||
#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY)
|
||||
#define SCSI_SET_LIMIT 0x33 // Set Limits (O)
|
||||
#define SCSI_START_STP 0x1B // Start/Stop Unit (O)
|
||||
#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O)
|
||||
#define SCSI_VERIFY 0x2F // Verify (O)
|
||||
#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY)
|
||||
#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY)
|
||||
#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O)
|
||||
#define SCSI_WRITE_LONG 0x3F // Write Long (O)
|
||||
#define SCSI_WRITE_SAME 0x41 // Write Same (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Sequential Access Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_ERASE 0x19 // Erase (MANDATORY)
|
||||
#define SCSI_LOAD_UN 0x1b // Load/Unload (O)
|
||||
#define SCSI_LOCATE 0x2B // Locate (O)
|
||||
#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY)
|
||||
#define SCSI_READ_POS 0x34 // Read Position (O)
|
||||
#define SCSI_READ_REV 0x0F // Read Reverse (O)
|
||||
#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O)
|
||||
#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY)
|
||||
#define SCSI_REWIND 0x01 // Rewind (MANDATORY)
|
||||
#define SCSI_SPACE 0x11 // Space (MANDATORY)
|
||||
#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O)
|
||||
#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Printer Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_PRINT 0x0A // Print (MANDATORY)
|
||||
#define SCSI_SLEW_PNT 0x0B // Slew and Print (O)
|
||||
#define SCSI_STOP_PNT 0x1B // Stop Print (O)
|
||||
#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Processor Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_RECEIVE 0x08 // Receive (O)
|
||||
#define SCSI_SEND 0x0A // Send (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Write-Once Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O)
|
||||
#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O)
|
||||
#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O)
|
||||
#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O)
|
||||
#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O)
|
||||
#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O)
|
||||
#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O)
|
||||
#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O)
|
||||
#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O)
|
||||
#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O)
|
||||
#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O)
|
||||
#define SCSI_WRITE12 0xAA // Write 12-Byte (O)
|
||||
#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O)
|
||||
#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to CD-ROM Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O)
|
||||
#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O)
|
||||
#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O)
|
||||
#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O)
|
||||
#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O)
|
||||
#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O)
|
||||
#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY)
|
||||
#define SCSI_READHEADER 0x44 // Read Header (O)
|
||||
#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O)
|
||||
#define SCSI_READ_TOC 0x43 // Read TOC (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Scanner Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O)
|
||||
#define SCSI_GETWINDOW 0x25 // Get Window (O)
|
||||
#define SCSI_OBJECTPOS 0x31 // Object Postion (O)
|
||||
#define SCSI_SCAN 0x1B // Scan (O)
|
||||
#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Optical Memory Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_UpdateBlk 0x3D // Update Block (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Medium Changer Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O)
|
||||
#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O)
|
||||
#define SCSI_POSTOELEM 0x2B // Position to Element (O)
|
||||
#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O)
|
||||
#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O)
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Commands Unique to Communication Devices %%%
|
||||
//***************************************************************************
|
||||
#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY)
|
||||
#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O)
|
||||
#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O)
|
||||
#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY)
|
||||
#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O)
|
||||
#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// %%% END OF SCSI COMMAND OPCODES %%%
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//***************************************************************************
|
||||
// %%% Request Sense Data Format %%%
|
||||
//***************************************************************************
|
||||
typedef struct {
|
||||
BYTE ErrorCode; // Error Code (70H or 71H)
|
||||
BYTE SegmentNum; // Number of current segment descriptor
|
||||
BYTE SenseKey; // Sense Key(See bit definitions too)
|
||||
BYTE InfoByte0; // Information MSB
|
||||
BYTE InfoByte1; // Information MID
|
||||
BYTE InfoByte2; // Information MID
|
||||
BYTE InfoByte3; // Information LSB
|
||||
BYTE AddSenLen; // Additional Sense Length
|
||||
BYTE ComSpecInf0; // Command Specific Information MSB
|
||||
BYTE ComSpecInf1; // Command Specific Information MID
|
||||
BYTE ComSpecInf2; // Command Specific Information MID
|
||||
BYTE ComSpecInf3; // Command Specific Information LSB
|
||||
BYTE AddSenseCode; // Additional Sense Code
|
||||
BYTE AddSenQual; // Additional Sense Code Qualifier
|
||||
BYTE FieldRepUCode; // Field Replaceable Unit Code
|
||||
BYTE SenKeySpec15; // Sense Key Specific 15th byte
|
||||
BYTE SenKeySpec16; // Sense Key Specific 16th byte
|
||||
BYTE SenKeySpec17; // Sense Key Specific 17th byte
|
||||
BYTE AddSenseBytes; // Additional Sense Bytes
|
||||
} SENSE_DATA_FMT;
|
||||
|
||||
//***************************************************************************
|
||||
// %%% REQUEST SENSE ERROR CODE %%%
|
||||
//***************************************************************************
|
||||
#define SERROR_CURRENT 0x70 // Current Errors
|
||||
#define SERROR_DEFERED 0x71 // Deferred Errors
|
||||
|
||||
//***************************************************************************
|
||||
// %%% REQUEST SENSE BIT DEFINITIONS %%%
|
||||
//***************************************************************************
|
||||
#define SENSE_VALID 0x80 // Byte 0 Bit 7
|
||||
#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7
|
||||
#define SENSE_EOM 0x40 // Byte 2 Bit 6
|
||||
#define SENSE_ILI 0x20 // Byte 2 Bit 5
|
||||
|
||||
//***************************************************************************
|
||||
// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%%
|
||||
//***************************************************************************
|
||||
#define KEY_NOSENSE 0x00 // No Sense
|
||||
#define KEY_RECERROR 0x01 // Recovered Error
|
||||
#define KEY_NOTREADY 0x02 // Not Ready
|
||||
#define KEY_MEDIUMERR 0x03 // Medium Error
|
||||
#define KEY_HARDERROR 0x04 // Hardware Error
|
||||
#define KEY_ILLGLREQ 0x05 // Illegal Request
|
||||
#define KEY_UNITATT 0x06 // Unit Attention
|
||||
#define KEY_DATAPROT 0x07 // Data Protect
|
||||
#define KEY_BLANKCHK 0x08 // Blank Check
|
||||
#define KEY_VENDSPEC 0x09 // Vendor Specific
|
||||
#define KEY_COPYABORT 0x0A // Copy Abort
|
||||
#define KEY_EQUAL 0x0C // Equal (Search)
|
||||
#define KEY_VOLOVRFLW 0x0D // Volume Overflow
|
||||
#define KEY_MISCOMP 0x0E // Miscompare (Search)
|
||||
#define KEY_RESERVED 0x0F // Reserved
|
||||
|
||||
//***************************************************************************
|
||||
// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%%
|
||||
//***************************************************************************
|
||||
#define DTYPE_DASD 0x00 // Disk Device
|
||||
#define DTYPE_SEQD 0x01 // Tape Device
|
||||
#define DTYPE_PRNT 0x02 // Printer
|
||||
#define DTYPE_PROC 0x03 // Processor
|
||||
#define DTYPE_WORM 0x04 // Write-once read-multiple
|
||||
#define DTYPE_CROM 0x05 // CD-ROM device
|
||||
#define DTYPE_SCAN 0x06 // Scanner device
|
||||
#define DTYPE_OPTI 0x07 // Optical memory device
|
||||
#define DTYPE_JUKE 0x08 // Medium Changer device
|
||||
#define DTYPE_COMM 0x09 // Communications device
|
||||
#define DTYPE_RESL 0x0A // Reserved (low)
|
||||
#define DTYPE_RESH 0x1E // Reserved (high)
|
||||
#define DTYPE_UNKNOWN 0x1F // Unknown or no device type
|
||||
|
||||
//***************************************************************************
|
||||
// %%% ANSI APPROVED VERSION DEFINITIONS %%%
|
||||
//***************************************************************************
|
||||
#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand
|
||||
#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1)
|
||||
#define ANSI_SCSI2 0x2 // Device complies to SCSI-2
|
||||
#define ANSI_RESLO 0x3 // Reserved (low)
|
||||
#define ANSI_RESHI 0x7 // Reserved (high)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* Ssdef.h v1.2 System status definitions */
|
||||
/* Ssdef.h v1.3 System status definitions */
|
||||
|
||||
/*
|
||||
This is part of ODS2 written by Paul Nankervis,
|
||||
@@ -10,17 +10,13 @@
|
||||
the contibution of the original author.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef VMS
|
||||
|
||||
#include <ssdef.h>
|
||||
|
||||
#else
|
||||
#ifndef SS$_NORMAL
|
||||
|
||||
#define SS$_NORMAL 1
|
||||
#define SS$_WASCLR 1
|
||||
#define SS$_WASSET 9
|
||||
#define SS$_ABORT 44
|
||||
#define SS$_DEVMOUNT 108
|
||||
#define SS$_DEVNOTMOUNT 124
|
||||
#define SS$_ILLEFC 236
|
||||
#define SS$_INSFMEM 292
|
||||
@@ -29,11 +25,15 @@
|
||||
#define SS$_DUPLICATE 148
|
||||
#define SS$_BADPARAM 20
|
||||
#define SS$_IVCHAN 316
|
||||
#define SS$_IVDEVNAM 324
|
||||
#define SS$_NOIOCHAN 436
|
||||
#define SS$_PARITY 500
|
||||
#define SS$_WRITLCK 604
|
||||
#define SS$_BADIRECTORY 2088
|
||||
#define SS$_DEVICEFULL 2128
|
||||
#define SS$_DEVNOTALLOC 2136
|
||||
#define SS$_DUPFILENAME 2152
|
||||
#define SS$_FILESEQCHK 2232
|
||||
#define SS$_NOSUCHDEV 2312
|
||||
#define SS$_NOSUCHFILE 2320
|
||||
#define SS$_BADFILENAME 2072
|
||||
@@ -41,8 +41,10 @@
|
||||
#define SS$_ENDOFFILE 2160
|
||||
#define SS$_FILELOCKED 2216
|
||||
#define SS$_NOMOREFILES 2352
|
||||
#define SS$_ITEMNOTFOUND 2640
|
||||
#define SS$_NOSUCHVOL 3882
|
||||
#define SS$_NOTINSTALL 8212
|
||||
#define SS$_DEVNOTDISM 8628
|
||||
#define SS$_UNSUPVOLSET 9908
|
||||
|
||||
#endif
|
||||
|
||||
677
extracters/ods2/update.c
Normal file
677
extracters/ods2/update.c
Normal file
@@ -0,0 +1,677 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include "ssdef.h"
|
||||
#include "access.h"
|
||||
|
||||
unsigned deaccesshead(struct VIOC *vioc,struct HEAD *head,unsigned idxblk);
|
||||
unsigned accesshead(struct VCB *vcb,struct fiddef *fid,unsigned seg_num,
|
||||
struct VIOC **vioc,struct HEAD **headbuff,
|
||||
unsigned *retidxblk,unsigned wrtflg);
|
||||
unsigned getwindow(struct FCB * fcb,unsigned vbn,struct VCBDEV **devptr,
|
||||
unsigned *phyblk,unsigned *phylen,struct fiddef *hdrfid,
|
||||
unsigned *hdrseq);
|
||||
struct VCBDEV *rvn_to_dev(struct VCB *vcb,unsigned rvn);
|
||||
|
||||
|
||||
|
||||
/* Bitmaps get accesses in 'WORK_UNITs' which can be an integer
|
||||
on a little endian machine but must be a byte on a big endian system */
|
||||
|
||||
#ifdef BIG_ENDIAN
|
||||
#define WORK_UNIT unsigned char
|
||||
#define WORK_MASK 0xff
|
||||
#else
|
||||
#define WORK_UNIT unsigned int
|
||||
#define WORK_MASK 0xffffffff
|
||||
#endif
|
||||
#define WORK_BITS (sizeof(WORK_UNIT) * 8)
|
||||
|
||||
/* update_freecount() to read the device cluster bitmap and compute
|
||||
the number of un-used clusters */
|
||||
|
||||
unsigned update_freecount(struct VCBDEV *vcbdev,unsigned *retcount)
|
||||
{
|
||||
register unsigned sts;
|
||||
register unsigned free_clusters = 0;
|
||||
register unsigned map_block, map_end = (vcbdev->max_cluster + 4095) / 4096 + 2;
|
||||
for (map_block = 2; map_block < map_end; ) {
|
||||
struct VIOC *vioc;
|
||||
unsigned blkcount;
|
||||
WORK_UNIT *bitmap,*work_ptr;
|
||||
register unsigned work_count;
|
||||
sts = accesschunk(vcbdev->mapfcb,map_block, &vioc,(char **) &bitmap,&blkcount,0);
|
||||
if (!(sts & 1)) return sts;
|
||||
if (blkcount > map_end - map_block) blkcount = map_end - map_block + 1;
|
||||
work_ptr = bitmap;
|
||||
work_count = blkcount * 512 / sizeof(WORK_UNIT);
|
||||
do {
|
||||
register WORK_UNIT work_val = *work_ptr++;
|
||||
if (work_val == WORK_MASK) {
|
||||
free_clusters += WORK_BITS;
|
||||
} else {
|
||||
while (work_val != 0) {
|
||||
if (work_val & 1) free_clusters++;
|
||||
work_val = work_val >> 1;
|
||||
}
|
||||
}
|
||||
} while (--work_count > 0);
|
||||
sts = deaccesschunk(vioc,0,0,1);
|
||||
if (!(sts & 1)) return sts;
|
||||
map_block += blkcount;
|
||||
}
|
||||
*retcount = free_clusters;
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* bitmap_modify() will either set or release a block of bits in the
|
||||
device cluster bitmap */
|
||||
|
||||
unsigned bitmap_modify(struct VCBDEV *vcbdev,unsigned cluster,unsigned count,
|
||||
unsigned release_flag)
|
||||
{
|
||||
register unsigned sts;
|
||||
register unsigned clust_count = count;
|
||||
register unsigned map_block = cluster / 4096 + 2;
|
||||
register unsigned block_offset = cluster % 4096;
|
||||
if (clust_count < 1) return SS$_BADPARAM;
|
||||
if (cluster + clust_count > vcbdev->max_cluster + 1) return SS$_BADPARAM;
|
||||
do {
|
||||
struct VIOC *vioc;
|
||||
unsigned blkcount;
|
||||
WORK_UNIT *bitmap;
|
||||
register WORK_UNIT *work_ptr;
|
||||
register unsigned work_count;
|
||||
sts = accesschunk(vcbdev->mapfcb,map_block,&vioc,(char **) &bitmap,&blkcount,1);
|
||||
if (!(sts & 1)) return sts;
|
||||
work_ptr = bitmap + block_offset / WORK_BITS;
|
||||
if (block_offset % WORK_BITS) {
|
||||
register unsigned bit_no = block_offset % WORK_BITS;
|
||||
register WORK_UNIT bit_mask = WORK_MASK;
|
||||
if (bit_no + clust_count < WORK_BITS) {
|
||||
bit_mask = bit_mask >> (WORK_BITS - clust_count);
|
||||
clust_count = 0;
|
||||
} else {
|
||||
clust_count -= WORK_BITS - bit_no;
|
||||
}
|
||||
bit_mask = bit_mask << bit_no;
|
||||
if (release_flag) {
|
||||
*work_ptr++ |= bit_mask;
|
||||
} else {
|
||||
*work_ptr++ &= ~bit_mask;
|
||||
}
|
||||
block_offset += WORK_BITS - bit_no;
|
||||
}
|
||||
work_count = (blkcount * 4096 - block_offset) / WORK_BITS;
|
||||
if (work_count > clust_count / WORK_BITS) {
|
||||
work_count = clust_count / WORK_BITS;
|
||||
block_offset = 1;
|
||||
} else {
|
||||
block_offset = 0;
|
||||
}
|
||||
clust_count -= work_count * WORK_BITS;
|
||||
if (release_flag) {
|
||||
while (clust_count-- > 0) {
|
||||
*work_ptr++ = WORK_MASK;
|
||||
}
|
||||
} else {
|
||||
while (work_count-- > 0) {
|
||||
*work_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
if (clust_count != 0 && block_offset) {
|
||||
register WORK_UNIT bit_mask = WORK_MASK >> (WORK_BITS - clust_count);
|
||||
if (release_flag) {
|
||||
*work_ptr++ |= bit_mask;
|
||||
} else {
|
||||
*work_ptr++ &= ~bit_mask;
|
||||
}
|
||||
clust_count = 0;
|
||||
}
|
||||
sts = deaccesschunk(vioc,map_block,blkcount,1);
|
||||
if (!(sts & 1)) return sts;
|
||||
map_block += blkcount;
|
||||
block_offset = 0;
|
||||
} while (clust_count != 0);
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* bitmap_search() is a routine to find a pool of free clusters in the
|
||||
device cluster bitmap */
|
||||
|
||||
unsigned bitmap_search(struct VCBDEV *vcbdev,unsigned *position,unsigned *count)
|
||||
{
|
||||
register unsigned sts;
|
||||
register unsigned map_block,block_offset;
|
||||
register unsigned search_words,needed;
|
||||
register unsigned run = 0,cluster;
|
||||
register unsigned best_run = 0,best_cluster = 0;
|
||||
needed = *count;
|
||||
if (needed < 1 || needed > vcbdev->max_cluster + 1) return SS$_BADPARAM;
|
||||
cluster = *position;
|
||||
if (cluster + *count > vcbdev->max_cluster + 1) cluster = 0;
|
||||
map_block = cluster / 4096 + 2;
|
||||
block_offset = cluster % 4096;
|
||||
cluster = cluster - (cluster % WORK_BITS);
|
||||
search_words = vcbdev->max_cluster / WORK_BITS;
|
||||
do {
|
||||
struct VIOC *vioc;
|
||||
unsigned blkcount;
|
||||
WORK_UNIT *bitmap;
|
||||
register WORK_UNIT *work_ptr, work_val;
|
||||
register unsigned work_count;
|
||||
sts = accesschunk(vcbdev->mapfcb,map_block,&vioc,(char **) &bitmap,&blkcount,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
work_ptr = bitmap + block_offset / WORK_BITS;
|
||||
work_val = *work_ptr++;
|
||||
if (block_offset % WORK_BITS) {
|
||||
work_val = work_val && (WORK_MASK << block_offset % WORK_BITS);
|
||||
}
|
||||
work_count = (blkcount * 4096 - block_offset) / WORK_BITS;
|
||||
if (work_count > search_words) work_count = search_words;
|
||||
search_words -= work_count;
|
||||
do {
|
||||
if (work_val == WORK_MASK) {
|
||||
run += WORK_BITS;
|
||||
} else {
|
||||
register unsigned bit_no = 0;
|
||||
while (work_val != 0) {
|
||||
if (work_val & 1) {
|
||||
run++;
|
||||
} else {
|
||||
if (run > best_run) {
|
||||
best_run = run;
|
||||
best_cluster = cluster + bit_no;
|
||||
}
|
||||
run = 0;
|
||||
}
|
||||
work_val = work_val >> 1;
|
||||
bit_no++;
|
||||
}
|
||||
if (bit_no < WORK_BITS) {
|
||||
if (run > best_run) {
|
||||
best_run = run;
|
||||
best_cluster = cluster + bit_no;
|
||||
}
|
||||
run = 0;
|
||||
}
|
||||
}
|
||||
cluster += WORK_BITS;
|
||||
if (work_count-- > 0) {
|
||||
work_val = *work_ptr++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (best_run < needed);
|
||||
deaccesschunk(vioc,map_block,0,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
map_block += blkcount;
|
||||
block_offset = 0;
|
||||
} while (best_run < needed && search_words != 0);
|
||||
if (best_run > needed) best_run = needed;
|
||||
*count = best_run;
|
||||
*position = best_cluster;
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* headmap_clear() will release a header from the indexf.sys file header
|
||||
bitmap */
|
||||
|
||||
unsigned headmap_clear(struct VCBDEV *vcbdev,unsigned head_no)
|
||||
{
|
||||
WORK_UNIT *bitmap;
|
||||
struct VIOC *vioc;
|
||||
register unsigned sts;
|
||||
register unsigned map_block = head_no / 4096 + vcbdev->home.hm2$w_cluster * 4 + 1;
|
||||
if (head_no < 10) return 0;
|
||||
sts = accesschunk(vcbdev->idxfcb,map_block,&vioc,(char **) &bitmap,NULL,1);
|
||||
if (sts & 1) {
|
||||
bitmap[(head_no % 4096) / WORK_BITS] &= ~(1 << (head_no % WORK_BITS));
|
||||
sts = deaccesschunk(vioc,map_block,1,1);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* update_findhead() will locate a free header from indexf.sys */
|
||||
|
||||
unsigned update_findhead(struct VCBDEV *vcbdev,unsigned *rethead_no,
|
||||
struct VIOC **retvioc,struct HEAD **headbuff,
|
||||
unsigned *retidxblk)
|
||||
{
|
||||
unsigned head_no = 0;
|
||||
register unsigned sts;
|
||||
do {
|
||||
struct VIOC *vioc;
|
||||
int modify_flag = 0;
|
||||
unsigned blkcount;
|
||||
WORK_UNIT *bitmap,*work_ptr;
|
||||
register unsigned map_block,work_count;
|
||||
map_block = head_no / 4096 + vcbdev->home.hm2$w_cluster * 4 + 1;
|
||||
sts = accesschunk(vcbdev->idxfcb,map_block,
|
||||
&vioc,(char **) &bitmap,&blkcount,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
work_count = (head_no % 4096) / WORK_BITS;
|
||||
work_ptr = bitmap + work_count;
|
||||
work_count = blkcount * 512 / WORK_BITS - work_count;
|
||||
do {
|
||||
register WORK_UNIT work_val = *work_ptr;
|
||||
if (work_val == WORK_MASK) {
|
||||
head_no += WORK_BITS;
|
||||
} else {
|
||||
register unsigned bit_no = 0;
|
||||
for (bit_no = 0; bit_no < WORK_BITS; bit_no++) {
|
||||
if ((work_val & (1 << bit_no)) == 0) {
|
||||
register unsigned idxblk = head_no +
|
||||
VMSWORD(vcbdev->home.hm2$w_ibmapvbn) +
|
||||
VMSWORD(vcbdev->home.hm2$w_ibmapsize);
|
||||
sts = accesschunk(vcbdev->idxfcb,idxblk,retvioc,(char **) headbuff,NULL,1);
|
||||
if (sts & 1) {
|
||||
*work_ptr |= 1 << bit_no;
|
||||
modify_flag = 1;
|
||||
if ((*headbuff)->fh2$w_checksum != 0 || (*headbuff)->fh2$w_fid.fid$w_num != 0 ||
|
||||
VMSLONG((*headbuff)->fh2$l_filechar) & FH2$M_MARKDEL == 0) {
|
||||
sts = deaccesschunk(*retvioc,0,0,0);
|
||||
} else {
|
||||
*rethead_no = head_no + 1;
|
||||
*retidxblk = idxblk;
|
||||
deaccesschunk(vioc,map_block,blkcount,modify_flag);
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
head_no++;
|
||||
}
|
||||
}
|
||||
work_ptr++;
|
||||
} while (--work_count != 0);
|
||||
deaccesschunk(vioc,map_block,blkcount,modify_flag);
|
||||
if ((sts & 1) == 0) break;
|
||||
} while (head_no < VMSLONG(vcbdev->home.hm2$l_maxfiles));
|
||||
return sts;
|
||||
}
|
||||
|
||||
unsigned update_addhead(struct VCB *vcb,char *filename,struct fiddef *back,
|
||||
unsigned seg_num,struct fiddef *fid,
|
||||
struct VIOC **vioc,struct HEAD **rethead,
|
||||
unsigned *idxblk)
|
||||
{
|
||||
register unsigned free_space = 0;
|
||||
register unsigned device,rvn,sts;
|
||||
unsigned head_no;
|
||||
struct IDENT *id;
|
||||
struct HEAD *head;
|
||||
struct VCBDEV *vcbdev = NULL;
|
||||
for (device = 0; device < vcb->devices; device++) {
|
||||
if (vcb->vcbdev[device].dev != NULL) {
|
||||
if (vcb->vcbdev[device].free_clusters > free_space) {
|
||||
free_space = vcb->vcbdev[device].free_clusters;
|
||||
vcbdev = &vcb->vcbdev[device];
|
||||
rvn = device;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vcbdev == NULL) return SS$_DEVICEFULL;
|
||||
|
||||
sts = update_findhead(vcbdev,&head_no,vioc,&head,idxblk);
|
||||
if (!(sts & 1)) return sts;
|
||||
printf("Header %d index %d rvn %d\n",head_no,idxblk,rvn);
|
||||
fid->fid$w_num = head_no;
|
||||
fid->fid$w_seq = ++head->fh2$w_fid.fid$w_seq;
|
||||
if (fid->fid$w_seq == 0) fid->fid$w_seq = 1;
|
||||
if (rvn > 0) {
|
||||
fid->fid$b_rvn = rvn + 1;
|
||||
} else {
|
||||
fid->fid$b_rvn = 0;
|
||||
}
|
||||
fid->fid$b_nmx = head_no >> 16;
|
||||
memset(head,0,512);
|
||||
head->fh2$b_idoffset = 40;
|
||||
head->fh2$b_mpoffset = 100;
|
||||
head->fh2$b_acoffset = 255;
|
||||
head->fh2$b_rsoffset = 255;
|
||||
head->fh2$w_seg_num = seg_num;
|
||||
head->fh2$w_struclev = 513;
|
||||
head->fh2$l_fileowner.uic$w_mem = 4;
|
||||
head->fh2$l_fileowner.uic$w_grp = 1;
|
||||
fid_copy(&head->fh2$w_fid,fid,0);
|
||||
if (back != NULL) fid_copy(&head->fh2$w_backlink,back,0);
|
||||
id = (struct IDENT *) ((unsigned short *) head + 40);
|
||||
memset(id->fi2$t_filenamext,' ',66);
|
||||
if (strlen(filename) < 20) {
|
||||
memset(id->fi2$t_filename,' ',20);
|
||||
memcpy(id->fi2$t_filename,filename,strlen(filename));
|
||||
} else {
|
||||
memcpy(id->fi2$t_filename,filename,20);
|
||||
memcpy(id->fi2$t_filenamext,filename+20,strlen(filename+20));
|
||||
}
|
||||
id->fi2$w_revision = 1;
|
||||
sys_gettim(id->fi2$q_credate);
|
||||
memcpy(id->fi2$q_revdate,id->fi2$q_credate,sizeof(id->fi2$q_credate));
|
||||
memcpy(id->fi2$q_expdate,id->fi2$q_credate,sizeof(id->fi2$q_credate));
|
||||
head->fh2$w_recattr.fat$l_efblk = VMSSWAP(1);
|
||||
{
|
||||
unsigned short check = checksum((vmsword *) head);
|
||||
head->fh2$w_checksum = VMSWORD(check);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* update_create() will create a new file... */
|
||||
|
||||
unsigned update_create(struct VCB *vcb,struct fiddef *did,char *filename,
|
||||
struct fiddef *fid,struct FCB **fcb)
|
||||
{
|
||||
struct VIOC *vioc;
|
||||
struct HEAD *head;
|
||||
unsigned idxblk;
|
||||
register unsigned sts;
|
||||
sts = update_addhead(vcb,filename,did,0,fid,&vioc,&head,&idxblk);
|
||||
if (!(sts & 1)) return sts;
|
||||
sts = deaccesshead(vioc,head,idxblk);
|
||||
if (sts & 1 && fcb != NULL) {
|
||||
sts = accessfile(vcb,fid,fcb,1);
|
||||
}
|
||||
printf("(%d,%d,%d) %d\n",fid->fid$w_num,fid->fid$w_seq,fid->fid$b_rvn,sts);
|
||||
return sts;
|
||||
}
|
||||
|
||||
unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig)
|
||||
{
|
||||
register unsigned sts;
|
||||
struct VCBDEV *vcbdev;
|
||||
struct VIOC *vioc;
|
||||
struct HEAD *head;
|
||||
unsigned headvbn;
|
||||
struct fiddef hdrfid;
|
||||
unsigned hdrseq;
|
||||
unsigned start_pos = 0;
|
||||
unsigned block_count = blocks;
|
||||
if (block_count < 1) return 0;
|
||||
if ((fcb->status & FCB_WRITE) == 0) return SS$_WRITLCK;
|
||||
if (fcb->hiblock > 0) {
|
||||
unsigned mapblk,maplen;
|
||||
sts = getwindow(fcb,fcb->hiblock,&vcbdev,&mapblk,&maplen,&hdrfid,&hdrseq);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
start_pos = mapblk + 1;
|
||||
if (hdrseq != 0) {
|
||||
sts = accesshead(fcb->vcb,&hdrfid,hdrseq,&vioc,&head,&headvbn,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
} else {
|
||||
head = fcb->head;
|
||||
vioc = NULL;
|
||||
}
|
||||
} else {
|
||||
head = fcb->head;
|
||||
vioc = NULL;
|
||||
start_pos = 0; /* filenum * 3 /indexfsize * volumesize; */
|
||||
}
|
||||
if (vioc == NULL) vcbdev = rvn_to_dev(fcb->vcb,fcb->rvn);
|
||||
if (vcbdev->free_clusters == 0 || head->fh2$b_map_inuse + 4 >=
|
||||
head->fh2$b_acoffset - head->fh2$b_mpoffset) {
|
||||
struct VIOC *nvioc;
|
||||
struct HEAD *nhead;
|
||||
unsigned nidxblk;
|
||||
sts = update_addhead(fcb->vcb,"",&head->fh2$w_fid,head->fh2$w_seg_num+1,
|
||||
&head->fh2$w_ext_fid,&nvioc,&nhead,&nidxblk);
|
||||
if (!(sts & 1)) return sts;
|
||||
if (vioc != NULL) deaccesshead(vioc,head,headvbn);
|
||||
vioc = nvioc;
|
||||
head = nhead;
|
||||
headvbn = nidxblk;
|
||||
vcbdev = rvn_to_dev(fcb->vcb,head->fh2$w_fid.fid$b_rvn);
|
||||
}
|
||||
sts = bitmap_search(vcbdev,&start_pos,&block_count);
|
||||
printf("Update_extend %d %d\n",start_pos,block_count);
|
||||
if (sts & 1) {
|
||||
if (block_count < 1 || contig && block_count * vcbdev->clustersize < blocks) {
|
||||
sts = SS$_DEVICEFULL;
|
||||
} else {
|
||||
register unsigned short *mp;
|
||||
mp = (unsigned short *) head + head->fh2$b_mpoffset + head->fh2$b_map_inuse;
|
||||
*mp++ = (3 << 14) | ((block_count *vcbdev->clustersize - 1) >> 16);
|
||||
*mp++ = (block_count * vcbdev->clustersize - 1) & 0xffff;
|
||||
*mp++ = (start_pos * vcbdev->clustersize) & 0xffff;
|
||||
*mp++ = (start_pos * vcbdev->clustersize) >> 16;
|
||||
head->fh2$b_map_inuse += 4;
|
||||
fcb->hiblock += block_count * vcbdev->clustersize;
|
||||
fcb->head->fh2$w_recattr.fat$l_hiblk = VMSSWAP(fcb->hiblock * vcbdev->clustersize);
|
||||
sts = bitmap_modify(vcbdev,start_pos,block_count,0);
|
||||
}
|
||||
}
|
||||
if (vioc != NULL) deaccesshead(vioc,head,headvbn);
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* This routine has bugs and does NOT work properly yet!!!!
|
||||
It may be something simple but I haven't had time to look...
|
||||
So DON'T use mount/write!!! */
|
||||
|
||||
unsigned deallocfile(struct FCB *fcb)
|
||||
{
|
||||
register unsigned sts = 1;
|
||||
/*
|
||||
First mark all file clusters as free in BITMAP.SYS
|
||||
*/
|
||||
register unsigned vbn = 1;
|
||||
while (vbn <= fcb->hiblock) {
|
||||
register unsigned sts;
|
||||
unsigned phyblk,phylen;
|
||||
struct VCBDEV *vcbdev;
|
||||
sts = getwindow(fcb,vbn,&vcbdev,&phyblk,&phylen,NULL,NULL);
|
||||
if ((sts & 1) == 0) break;
|
||||
|
||||
sts = bitmap_modify(vcbdev,phyblk,phylen,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
}
|
||||
/*
|
||||
Now reset file header bit map in INDEXF.SYS and
|
||||
update each of the file headers...
|
||||
*/
|
||||
{
|
||||
unsigned rvn = fcb->rvn;
|
||||
unsigned headvbn = fcb->headvbn;
|
||||
struct HEAD *head = fcb->head;
|
||||
struct VIOC *headvioc = fcb->headvioc;
|
||||
do {
|
||||
unsigned ext_seg_num = 0;
|
||||
struct fiddef extfid;
|
||||
register struct VCBDEV *vcbdev;
|
||||
unsigned *bitmap;
|
||||
struct VIOC *vioc;
|
||||
register unsigned filenum = (head->fh2$w_fid.fid$b_nmx << 16) +
|
||||
head->fh2$w_fid.fid$w_num - 1;
|
||||
register unsigned idxblk;
|
||||
vcbdev = rvn_to_dev(fcb->vcb,rvn);
|
||||
if (vcbdev == NULL) break;
|
||||
idxblk = filenum / 4096 +
|
||||
vcbdev->home.hm2$w_cluster * 4 + 1;
|
||||
sts = accesschunk(vcbdev->idxfcb,idxblk,&vioc,
|
||||
(char **) &bitmap,NULL,1);
|
||||
if (sts & 1) {
|
||||
bitmap[(filenum % 4096) / WORK_BITS] &=
|
||||
~(1 << (filenum % WORK_BITS));
|
||||
sts = deaccesschunk(vioc,idxblk,1,1);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
head->fh2$w_fid.fid$w_num = 0;
|
||||
head->fh2$w_fid.fid$b_rvn = 0;
|
||||
head->fh2$w_fid.fid$b_nmx = 0;
|
||||
head->fh2$w_checksum = 0;
|
||||
ext_seg_num++;
|
||||
memcpy(&extfid,&fcb->head->fh2$w_ext_fid,sizeof(struct fiddef));
|
||||
sts = deaccesshead(headvioc,NULL,headvbn);
|
||||
if ((sts & 1) == 0) break;
|
||||
if (extfid.fid$b_rvn == 0) {
|
||||
extfid.fid$b_rvn = rvn;
|
||||
} else {
|
||||
rvn = extfid.fid$b_rvn;
|
||||
}
|
||||
if (extfid.fid$w_num != 0 || extfid.fid$b_nmx != 0) {
|
||||
sts = accesshead(fcb->vcb,&extfid,ext_seg_num,&headvioc,&head,&headvbn,1);
|
||||
if ((sts & 1) == 0) break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
if (sts & 1) {
|
||||
fcb->headvioc = NULL;
|
||||
cache_untouch(&fcb->cache,0);
|
||||
cache_delete(&fcb->cache);
|
||||
}
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* accesserase: delete a file... */
|
||||
|
||||
unsigned accesserase(struct VCB * vcb,struct fiddef * fid)
|
||||
{
|
||||
struct FCB *fcb;
|
||||
register int sts;
|
||||
sts = accessfile(vcb,fid,&fcb,1);
|
||||
if (sts & 1) {
|
||||
fcb->head->fh2$l_filechar |= FH2$M_MARKDEL;
|
||||
printf("Accesserase ... \n");
|
||||
sts = deaccessfile(fcb);
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef EXTEND
|
||||
unsigned extend(struct FCB *fcb,unsigned blocks)
|
||||
{
|
||||
register unsigned sts;
|
||||
struct VCBDEV *vcbdev;
|
||||
unsigned clusterno;
|
||||
unsigned extended = 0;
|
||||
if ((fcb->status & FCB_WRITE) == 0) return SS$_WRITLCK;
|
||||
if (fcb->hiblock > 0) {
|
||||
unsigned phyblk,phylen;
|
||||
sts = getwindow(fcb,fcb->hiblock,&vcbdev,&phyblk,&phylen,NULL,NULL);
|
||||
clusterno = (phyblk + 1) / vcbdev->home.hm2$w_cluster;
|
||||
if ((sts & 1) == 0) return sts;
|
||||
} else {
|
||||
vcbdev = fcb->vcb->vcbdev;
|
||||
clusterno = 0; /* filenum * 3 /indexfsize * volumesize; */
|
||||
}
|
||||
while (extended < blocks) {
|
||||
unsigned *bitmap,blkcount;
|
||||
struct VIOC *vioc;
|
||||
register unsigned clustalq = 0;
|
||||
register unsigned clustersz = vcbdev->home.hm2$w_cluster;
|
||||
sts = accesschunk(vcbdev->mapfcb,clusterno / 4096 + 2,
|
||||
&vioc,(char **) &bitmap,&blkcount,1);
|
||||
if ((sts & 1) == 0) return sts;
|
||||
do {
|
||||
register unsigned wordno = (clusterno % 4096) / WORK_BITS;
|
||||
register unsigned wordval = bitmap[wordno];
|
||||
if (wordval == 0xffff) {
|
||||
if (clustalq) break;
|
||||
clusterno = (clusterno % WORK_BITS) *
|
||||
WORK_BITS + 1;
|
||||
} else {
|
||||
register unsigned bitno = clusterno % WORK_BITS;
|
||||
do {
|
||||
if (wordval & (1 << bitno)) {
|
||||
if (clustalq) break;
|
||||
} else {
|
||||
clustalq++;
|
||||
wordval |= 1 << bitno;
|
||||
}
|
||||
clusterno++;
|
||||
if (clustalq >= (extended - blocks)) break;
|
||||
} while (++bitno < WORK_BITS);
|
||||
if (clustalq) {
|
||||
bitmap[wordno] = wordval;
|
||||
if (bitno < WORK_BITS) break;
|
||||
}
|
||||
}
|
||||
} while (++wordno < blkcount * 512 / sizeof(unsigned));
|
||||
mp = (unsigned word *) fcb->head + fcb->head->fh2$b_mpoffset;
|
||||
*mp++ = (3 << 14) | (clustalq >> 16);
|
||||
*mp++ = clustalq & 0xff;
|
||||
*mp++ = clustno & 0xff;
|
||||
*clusertize
|
||||
* mp++ = clustno << 16;
|
||||
fcb->head->fh2$b_map_inuse + 4;
|
||||
fcb->hiblock += clustalq;
|
||||
fcb->head.fh2$w_recattr.fat$l_hiblk[0] = fcb->hiblock >> 16;
|
||||
fcb->head.fh2$w_recattr.fat$l_hiblk[1] = fcb->hiblock & 0xff;
|
||||
sts = deaccesschunk(vioc,clusterno / 4096 + 2,blkcount,1);
|
||||
/* code to append clusterno:clustalq to map */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef EXTEND
|
||||
|
||||
unsigned access_create(struct VCB * vcb,struct FCB ** fcbadd,unsigned blocks) {
|
||||
register struct FCB *fcb;
|
||||
struct fiddef fid;
|
||||
unsigned create = sizeof(struct FCB);
|
||||
if (wrtflg && ((vcb->status & VCB_WRITE) == 0)) return SS$_WRITLCK;
|
||||
|
||||
sts = headmap_search(struct VCBDEV * vcbdev,struct fiddef * fid,
|
||||
struct VIOC ** vioc,struct HEAD ** headbuff,unsigned *retidxblk,) {
|
||||
fcb = cachesearch((void *) &vcb->fcb,filenum,0,NULL,NULL,&create);
|
||||
if (fcb == NULL) return SS$_INSFMEM;
|
||||
/* If not found make one... */
|
||||
if (create == 0) {
|
||||
fcb->cache.objtype = CACHETYPE_DEV;
|
||||
fcb->rvn = fid->fid_b_rvn;
|
||||
if (fcb->rvn == 0 && vcb->devices > 1) fcb->rvn = 1;
|
||||
fcb->vcb = vcb;
|
||||
fcb->wcb = NULL;
|
||||
fcb->headvbn = 0;
|
||||
fcb->vioc = NULL;
|
||||
fcb->headvioc = NULL;
|
||||
fcb->cache.objmanager = fcbmanager;
|
||||
}
|
||||
if (wrtflg) {
|
||||
if (fcb->headvioc != NULL && (fcb->cache.status & CACHE_WRITE) == 0) {
|
||||
deaccesshead(fcb->headvioc,NULL,0);
|
||||
fcb->headvioc = NULL;
|
||||
}
|
||||
fcb->cache.status |= CACHE_WRITE;
|
||||
}
|
||||
if (fcb->headvioc == NULL) {
|
||||
register unsigned sts;
|
||||
if (vcb->idxboot != NULL) {
|
||||
*fcbadd = fcb;
|
||||
fcb->hiblock = 32767; /* guess at indexf.sys file size */
|
||||
fcb->highwater = 0;
|
||||
fcb->head = vcb->idxboot; /* Load bootup header */
|
||||
}
|
||||
sts = accesshead(vcb,fid,0,&fcb->headvioc,&fcb->head,&fcb->headvbn,wrtflg);
|
||||
if (sts & 1) {
|
||||
fcb->hiblock = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_hiblk);
|
||||
if (fcb->head->fh2$b_idoffset > 39) {
|
||||
fcb->highwater = fcb->head->fh2$l_highwater;
|
||||
} else {
|
||||
fcb->highwater = 0;
|
||||
}
|
||||
} else {
|
||||
printf("Accessfile status %d\n",sts);
|
||||
fcb->cache.objmanager = NULL;
|
||||
cacheuntouch(&fcb->cache,0,0);
|
||||
cachefree(&fcb->cache);
|
||||
return sts;
|
||||
}
|
||||
}
|
||||
*fcbadd = fcb;
|
||||
return SS$_NORMAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,16 @@
|
||||
/*
|
||||
|
||||
VMSTIME.H v1.1
|
||||
Vmstime.h v1.6A
|
||||
|
||||
Author: Paul Nankervis
|
||||
|
||||
Please send bug reports to PaulNank@au1.ibm.com
|
||||
Please send bug reports to Paulnank@au1.ibm.com
|
||||
|
||||
1.4A Changed default DOLLAR handling to include DOLLAR
|
||||
identifers unless NO_DOLLAR is defined
|
||||
(ie #ifdef DOLLAR to #ifndef NO_DOLLAR)
|
||||
1.5 Moved more header info here and added cvt_internal support
|
||||
1.6A Fixed endian problems in addx/subx
|
||||
|
||||
*/
|
||||
|
||||
@@ -14,39 +20,155 @@
|
||||
|
||||
#include "descrip.h"
|
||||
|
||||
#ifdef __ALPHA
|
||||
#define VMSTIME_64BIT __int64
|
||||
#endif
|
||||
|
||||
struct TIME {
|
||||
unsigned char time[8]; /* Structure of time */
|
||||
}; /* Look out Einstein!! :-) */
|
||||
/* Define quadword time type and test for delta times... */
|
||||
|
||||
#ifdef VMSTIME_64BIT
|
||||
typedef VMSTIME_64BIT VMSTIME[1];
|
||||
typedef VMSTIME_64BIT *pVMSTIME;
|
||||
#define ISDELTA(x) (*x < 0)
|
||||
#define VMSTIME_ZERO {0}
|
||||
#else
|
||||
typedef unsigned char VMSTIME[8];
|
||||
typedef unsigned char *pVMSTIME;
|
||||
#define ISDELTA(x) (x[7] & 0x80)
|
||||
#define VMSTIME_ZERO {0,0,0,0,0,0,0,0}
|
||||
#endif
|
||||
|
||||
/* Define status codes we require... note that if the real code values
|
||||
are being included (SSDEF.H) then they should be included first!!! */
|
||||
|
||||
#ifndef SS__NORMAL
|
||||
#define SS__NORMAL 1
|
||||
#define SS__IVTIME 388
|
||||
#define LIB__NORMAL 1409025
|
||||
#define LIB__IVTIME 1410012
|
||||
#define LIB__ONEDELTIM 1410020
|
||||
#define LIB__ABSTIMREQ 1410044
|
||||
#define LIB__DELTIMREQ 1410052
|
||||
#define LIB__INVOPER 1410060
|
||||
|
||||
#ifndef NO_DOLLAR
|
||||
#ifndef SS$_NORMAL
|
||||
#define SS$_NORMAL SS__NORMAL
|
||||
#define SS$_IVTIME SS__IVTIME
|
||||
#define LIB$_NORMAL LIB__NORMAL
|
||||
#define LIB$_IVTIME LIB__IVTIME
|
||||
#define LIB$_ONEDELTIM LIB__ONEDELTIM
|
||||
#define LIB$_ABSTIMREQ LIB__ABSTIMREQ
|
||||
#define LIB$_DELTIMREQ LIB__DELTIMREQ
|
||||
#define LIB$_INVOPER LIB__INVOPER
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Constants for lib$cvt_ routines */
|
||||
|
||||
#define LIB_K_MONTH_OF_YEAR 1
|
||||
#define LIB_K_DAY_OF_YEAR 2
|
||||
#define LIB_K_HOUR_OF_YEAR 3
|
||||
#define LIB_K_MINUTE_OF_YEAR 4
|
||||
#define LIB_K_SECOND_OF_YEAR 5
|
||||
#define LIB_K_DAY_OF_MONTH 6
|
||||
#define LIB_K_HOUR_OF_MONTH 7
|
||||
#define LIB_K_MINUTE_OF_MONTH 8
|
||||
#define LIB_K_SECOND_OF_MONTH 9
|
||||
#define LIB_K_DAY_OF_WEEK 10
|
||||
#define LIB_K_HOUR_OF_WEEK 11
|
||||
#define LIB_K_MINUTE_OF_WEEK 12
|
||||
#define LIB_K_SECOND_OF_WEEK 13
|
||||
#define LIB_K_HOUR_OF_DAY 14
|
||||
#define LIB_K_MINUTE_OF_DAY 15
|
||||
#define LIB_K_SECOND_OF_DAY 16
|
||||
#define LIB_K_MINUTE_OF_HOUR 17
|
||||
#define LIB_K_SECOND_OF_HOUR 18
|
||||
#define LIB_K_SECOND_OF_MINUTE 19
|
||||
#define LIB_K_JULIAN_DATE 20
|
||||
#define LIB_K_DELTA_WEEKS 21
|
||||
#define LIB_K_DELTA_DAYS 22
|
||||
#define LIB_K_DELTA_HOURS 23
|
||||
#define LIB_K_DELTA_MINUTES 24
|
||||
#define LIB_K_DELTA_SECONDS 25
|
||||
#define LIB_K_DELTA_WEEKS_F 26
|
||||
#define LIB_K_DELTA_DAYS_F 27
|
||||
#define LIB_K_DELTA_HOURS_F 28
|
||||
#define LIB_K_DELTA_MINUTES_F 29
|
||||
#define LIB_K_DELTA_SECONDS_F 30
|
||||
#define LIB_K_MAX_OPERATION 31
|
||||
|
||||
/* For system which can use a dollar symbol...*/
|
||||
|
||||
#ifndef NO_DOLLAR
|
||||
#define sys$asctim sys_asctim
|
||||
#define sys$bintim sys_bintim
|
||||
#define sys$gettim sys_gettim
|
||||
#define sys$numtim sys_numtim
|
||||
#define lib$add_times lib_add_times
|
||||
#define lib$addx lib_addx
|
||||
#define lib$cvt_from_internal_time lib_cvt_from_internal_time
|
||||
#define lib$cvt_to_internal_time lib_cvt_to_internal_time
|
||||
#define lib$cvt_vectim lib_cvt_vectim
|
||||
#define lib$day lib_day
|
||||
#define lib$day_of_week lib_day_of_week
|
||||
#define lib$mult_delta_time lib_mult_delta_time
|
||||
#define lib$sub_times lib_sub_times
|
||||
#define lib$subx lib_subx
|
||||
#define sys$asctim sys_asctim
|
||||
#define sys$bintim sys_bintim
|
||||
#define sys$gettim sys_gettim
|
||||
#define sys$numtim sys_numtim
|
||||
|
||||
|
||||
unsigned sys_gettim(struct TIME *timadr);
|
||||
unsigned lib_cvt_vectim(unsigned short timbuf[7],struct TIME *timadr);
|
||||
unsigned lib_day(int *days,struct TIME *timadr,int *day_time);
|
||||
unsigned sys_numtim(unsigned short timbuf[7],struct TIME *timadr);
|
||||
unsigned sys_bintim(struct dsc$descriptor *timbuf,struct TIME *timadr);
|
||||
unsigned sys_asctim(unsigned short *timlen,struct dsc$descriptor *timbuf,
|
||||
struct TIME *timadr,unsigned cvtflg);
|
||||
unsigned lib_day_of_week(struct TIME *timadr,unsigned *weekday);
|
||||
unsigned lib_addx(void *addant,void *addee,void *result,int *lenadd);
|
||||
unsigned lib_subx(void *subant,void *subee,void *result,int *lenadd);
|
||||
unsigned lib_add_times(struct TIME *time1,struct TIME *time2,
|
||||
struct TIME *result);
|
||||
unsigned lib_sub_times(struct TIME *time1,struct TIME *time2,
|
||||
struct TIME *result);
|
||||
unsigned lib_mult_delta_time(int *multiple,struct TIME *timadr);
|
||||
|
||||
#define LIB$K_MONTH_OF_YEAR LIB_K_MONTH_OF_YEAR
|
||||
#define LIB$K_DAY_OF_YEAR LIB_K_DAY_OF_YEAR
|
||||
#define LIB$K_HOUR_OF_YEAR LIB_K_HOUR_OF_YEAR
|
||||
#define LIB$K_MINUTE_OF_YEAR LIB_K_MINUTE_OF_YEAR
|
||||
#define LIB$K_SECOND_OF_YEAR LIB_K_SECOND_OF_YEAR
|
||||
#define LIB$K_DAY_OF_MONTH LIB_K_DAY_OF_MONTH
|
||||
#define LIB$K_HOUR_OF_MONTH LIB_K_HOUR_OF_MONTH
|
||||
#define LIB$K_MINUTE_OF_MONTH LIB_K_MINUTE_OF_MONTH
|
||||
#define LIB$K_SECOND_OF_MONTH LIB_K_SECOND_OF_MONTH
|
||||
#define LIB$K_DAY_OF_WEEK LIB_K_DAY_OF_WEEK
|
||||
#define LIB$K_HOUR_OF_WEEK LIB_K_HOUR_OF_WEEK
|
||||
#define LIB$K_MINUTE_OF_WEEK LIB_K_MINUTE_OF_WEEK
|
||||
#define LIB$K_SECOND_OF_WEEK LIB_K_SECOND_OF_WEEK
|
||||
#define LIB$K_HOUR_OF_DAY LIB_K_HOUR_OF_DAY
|
||||
#define LIB$K_MINUTE_OF_DAY LIB_K_MINUTE_OF_DAY
|
||||
#define LIB$K_SECOND_OF_DAY LIB_K_SECOND_OF_DAY
|
||||
#define LIB$K_MINUTE_OF_HOUR LIB_K_MINUTE_OF_HOUR
|
||||
#define LIB$K_SECOND_OF_HOUR LIB_K_SECOND_OF_HOUR
|
||||
#define LIB$K_SECOND_OF_MINUTE LIB_K_SECOND_OF_MINUTE
|
||||
#define LIB$K_JULIAN_DATE LIB_K_JULIAN_DATE
|
||||
#define LIB$K_DELTA_WEEKS LIB_K_DELTA_WEEKS
|
||||
#define LIB$K_DELTA_DAYS LIB_K_DELTA_DAYS
|
||||
#define LIB$K_DELTA_HOURS LIB_K_DELTA_HOURS
|
||||
#define LIB$K_DELTA_MINUTES LIB_K_DELTA_MINUTES
|
||||
#define LIB$K_DELTA_SECONDS LIB_K_DELTA_SECONDS
|
||||
#define LIB$K_DELTA_WEEKS_F LIB_K_DELTA_WEEKS_F
|
||||
#define LIB$K_DELTA_DAYS_F LIB_K_DELTA_DAYS_F
|
||||
#define LIB$K_DELTA_HOURS_F LIB_K_DELTA_HOURS_F
|
||||
#define LIB$K_DELTA_MINUTES_F LIB_K_DELTA_MINUTES_F
|
||||
#define LIB$K_DELTA_SECONDS_F LIB_K_DELTA_SECONDS_F
|
||||
#define LIB$K_MAX_OPERATION LIB_K_MAX_OPERATION
|
||||
#endif
|
||||
|
||||
|
||||
unsigned sys_gettim(VMSTIME timadr);
|
||||
unsigned sys_numtim(unsigned short timvec[7],VMSTIME timadr);
|
||||
unsigned sys_bintim(struct dsc_descriptor *timbuf,VMSTIME timadr);
|
||||
unsigned sys_asctim(unsigned short *timlen,struct dsc_descriptor *timbuf,
|
||||
VMSTIME timadr,unsigned cvtflg);
|
||||
unsigned lib_add_times(VMSTIME time1,VMSTIME time2,VMSTIME result);
|
||||
unsigned lib_addx(void *addant,void *addee,void *result,int *lenadd);
|
||||
unsigned lib_cvt_from_internal_time(unsigned *operation,
|
||||
unsigned *result,VMSTIME input_time);
|
||||
unsigned lib_cvt_to_internal_time(unsigned *operation,int *input,
|
||||
VMSTIME result);
|
||||
unsigned lib_cvt_vectim(unsigned short timbuf[7],VMSTIME timadr);
|
||||
unsigned lib_day(int *days,VMSTIME timadr,int *day_time);
|
||||
unsigned lib_day_of_week(VMSTIME timadr,unsigned *weekday);
|
||||
unsigned lib_mult_delta_time(int *multiple,VMSTIME timadr);
|
||||
unsigned lib_subx(void *subant,void *subee,void *result,int *lenadd);
|
||||
unsigned lib_sub_times(VMSTIME time1,VMSTIME time2,VMSTIME result);
|
||||
unsigned vmstime_from_nt(VMSTIME nt_time,VMSTIME vms_time);
|
||||
unsigned vmstime_to_nt(VMSTIME vms_time,VMSTIME nt_time);
|
||||
int vmstime_compare(VMSTIME time1,VMSTIME time2);
|
||||
#endif
|
||||
|
||||
6
extracters/ods2/wnaspi32.def
Normal file
6
extracters/ods2/wnaspi32.def
Normal file
@@ -0,0 +1,6 @@
|
||||
LIBRARY WNASPI32
|
||||
EXPORTS
|
||||
GetASPI32SupportInfo @1
|
||||
SendASPI32Command @2
|
||||
; Make library with
|
||||
; LIB /DEF:WNASPI32.DEF /MACHINE:IX86
|
||||
BIN
extracters/ods2/wnaspi32.exp
Normal file
BIN
extracters/ods2/wnaspi32.exp
Normal file
Binary file not shown.
376
extracters/ods2/wnaspi32.h
Normal file
376
extracters/ods2/wnaspi32.h
Normal file
@@ -0,0 +1,376 @@
|
||||
//
|
||||
|
||||
// Name: WNASPI32.H
|
||||
|
||||
//
|
||||
|
||||
// Description: ASPI for Win32 definitions ('C' Language)
|
||||
|
||||
//
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C" {
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef void *LPSRB;
|
||||
|
||||
typedef void (*PFNPOST)();
|
||||
|
||||
|
||||
|
||||
DWORD SendASPI32Command (LPSRB);
|
||||
|
||||
DWORD GetASPI32SupportInfo (VOID);
|
||||
|
||||
|
||||
|
||||
#define SENSE_LEN 14 // Default sense buffer length
|
||||
|
||||
#define SRB_DIR_IN 0x08 // Transfer from SCSI target to
|
||||
|
||||
// host
|
||||
|
||||
#define SRB_DIR_OUT 0x10 // Transfer from host to SCSI
|
||||
|
||||
// target
|
||||
|
||||
#define SRB_POSTING 0x01 // Enable ASPI posting
|
||||
|
||||
#define SRB_EVENT_NOTIFY 0x40 // Enable ASPI event notification
|
||||
|
||||
#define SRB_ENABLE_RESIDUAL_COUNT 0x04 // Enable residual byte count
|
||||
|
||||
// reporting
|
||||
|
||||
#define SRB_DATA_SG_LIST 0x02 // Data buffer points to
|
||||
|
||||
// scatter-gather list
|
||||
|
||||
#define WM_ASPIPOST 0x4D42 // ASPI Post message
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% ASPI Command Definitions %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
#define SC_HA_INQUIRY 0x00 // Host adapter inquiry
|
||||
|
||||
#define SC_GET_DEV_TYPE 0x01 // Get device type
|
||||
|
||||
#define SC_EXEC_SCSI_CMD 0x02 // Execute SCSI command
|
||||
|
||||
#define SC_ABORT_SRB 0x03 // Abort an SRB
|
||||
|
||||
#define SC_RESET_DEV 0x04 // SCSI bus device reset
|
||||
|
||||
#define SC_GET_DISK_INFO 0x06 // Get Disk information
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB Status %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
#define SS_PENDING 0x00 // SRB being processed
|
||||
|
||||
#define SS_COMP 0x01 // SRB completed without error
|
||||
|
||||
#define SS_ABORTED 0x02 // SRB aborted
|
||||
|
||||
#define SS_ABORT_FAIL 0x03 // Unable to abort SRB
|
||||
|
||||
#define SS_ERR 0x04 // SRB completed with error
|
||||
|
||||
|
||||
|
||||
#define SS_INVALID_CMD 0x80 // Invalid ASPI command
|
||||
|
||||
#define SS_INVALID_HA 0x81 // Invalid host adapter number
|
||||
|
||||
#define SS_NO_DEVICE 0x82 // SCSI device not installed
|
||||
|
||||
#define SS_INVALID_SRB 0xE0 // Invalid parameter set in SRB
|
||||
|
||||
#define SS_BUFFER_ALIGN 0xE1 // Buffer alignment problem
|
||||
|
||||
#define SS_SECURITY_VIOLATION 0xE2 // Device access security violation
|
||||
|
||||
#define SS_FAILED_INIT 0xE4 // ASPI for windows failed init
|
||||
|
||||
#define SS_BUFFER_TO_BIG 0xE6 // Buffer size too big to handle!
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% Host Adapter Status %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
#define HASTAT_OK 0x00 // Host adapter did not detect an
|
||||
|
||||
// error
|
||||
|
||||
#define HASTAT_SEL_TO 0x11 // Selection Timeout
|
||||
|
||||
#define HASTAT_DO_DU 0x12 // Data overrun data underrun
|
||||
|
||||
#define HASTAT_BUS_FREE 0x13 // Unexpected bus free
|
||||
|
||||
#define HASTAT_PHASE_ERR 0x14 // Target bus phase sequence
|
||||
|
||||
// failure
|
||||
|
||||
#define HASTAT_TIMEOUT 0x09 // Timed out while SRB was
|
||||
|
||||
// waiting to beprocessed.
|
||||
|
||||
#define HASTAT_COMMAND_TIMEOUT 0x0B // While processing the SRB, the
|
||||
|
||||
// adapter timed out.
|
||||
|
||||
#define HASTAT_MESSAGE_REJECT 0x0D // While processing SRB, the
|
||||
|
||||
// adapter received a MESSAGE
|
||||
|
||||
// REJECT.
|
||||
|
||||
#define HASTAT_BUS_RESET 0x0E // A bus reset was detected.
|
||||
|
||||
#define HASTAT_PARITY_ERROR 0x0F // A parity error was detected.
|
||||
|
||||
#define HASTAT_REQUEST_SENSE_FAILED 0x10 // The adapter failed in issuing
|
||||
|
||||
// REQUEST SENSE.
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - HOST ADAPTER INQUIRY - SC_HA_INQUIRY %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_HA_INQUIRY
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // ASPI request flags
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved, MUST = 0
|
||||
|
||||
BYTE HA_Count; // Number of host adapters present
|
||||
|
||||
BYTE HA_SCSI_ID; // SCSI ID of host adapter
|
||||
|
||||
BYTE HA_ManagerId[16]; // String describing the manager
|
||||
|
||||
BYTE HA_Identifier[16]; // String describing the host adapter
|
||||
|
||||
BYTE HA_Unique[16]; // Host Adapter Unique parameters
|
||||
|
||||
WORD HA_Rsvd1;
|
||||
|
||||
} SRB_HAInquiry, *PSRB_HAInquiry;
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_GET_DEV_TYPE
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // Reserved
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved
|
||||
|
||||
BYTE SRB_Target; // Target's SCSI ID
|
||||
|
||||
BYTE SRB_Lun; // Target's LUN number
|
||||
|
||||
BYTE SRB_DeviceType; // Target's peripheral device type
|
||||
|
||||
BYTE SRB_Rsvd1;
|
||||
|
||||
} SRB_GDEVBlock, *PSRB_GDEVBlock;
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // ASPI request flags
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved
|
||||
|
||||
BYTE SRB_Target; // Target's SCSI ID
|
||||
|
||||
BYTE SRB_Lun; // Target's LUN number
|
||||
|
||||
WORD SRB_Rsvd1; // Reserved for Alignment
|
||||
|
||||
DWORD SRB_BufLen; // Data Allocation Length
|
||||
|
||||
BYTE *SRB_BufPointer; // Data Buffer Pointer
|
||||
|
||||
BYTE SRB_SenseLen; // Sense Allocation Length
|
||||
|
||||
BYTE SRB_CDBLen; // CDB Length
|
||||
|
||||
BYTE SRB_HaStat; // Host Adapter Status
|
||||
|
||||
BYTE SRB_TargStat; // Target Status
|
||||
|
||||
void (*SRB_PostProc)(); // Post routine
|
||||
|
||||
void *SRB_Rsvd2; // Reserved
|
||||
|
||||
BYTE SRB_Rsvd3[16]; // Reserved for alignment
|
||||
|
||||
BYTE CDBByte[16]; // SCSI CDB
|
||||
|
||||
BYTE SenseArea[SENSE_LEN+2]; // Request Sense buffer
|
||||
|
||||
} SRB_ExecSCSICmd, *PSRB_ExecSCSICmd;
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - ABORT AN SRB - SC_ABORT_SRB %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // Reserved
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved
|
||||
|
||||
void *SRB_ToAbort; // Pointer to SRB to abort
|
||||
|
||||
} SRB_Abort, *PSRB_Abort;
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - BUS DEVICE RESET - SC_RESET_DEV %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // Reserved
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved
|
||||
|
||||
BYTE SRB_Target; // Target's SCSI ID
|
||||
|
||||
BYTE SRB_Lun; // Target's LUN number
|
||||
|
||||
BYTE SRB_Rsvd1[12]; // Reserved for Alignment
|
||||
|
||||
BYTE SRB_HaStat; // Host Adapter Status
|
||||
|
||||
BYTE SRB_TargStat; // Target Status
|
||||
|
||||
void (*SRB_PostProc)(); // Post routine
|
||||
|
||||
void *SRB_Rsvd2; // Reserved
|
||||
|
||||
BYTE SRB_Rsvd3[32]; // Reserved
|
||||
|
||||
} SRB_BusDeviceReset, *PSRB_BusDeviceReset;
|
||||
|
||||
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
// %%% SRB - GET DISK INFORMATION - SC_GET_DISK_INFO %%%
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
typedef struct {
|
||||
|
||||
BYTE SRB_Cmd; // ASPI command code = SC_EXEC_SCSI_CMD
|
||||
|
||||
BYTE SRB_Status; // ASPI command status byte
|
||||
|
||||
BYTE SRB_HaId; // ASPI host adapter number
|
||||
|
||||
BYTE SRB_Flags; // Reserved
|
||||
|
||||
DWORD SRB_Hdr_Rsvd; // Reserved
|
||||
|
||||
BYTE SRB_Target; // Target's SCSI ID
|
||||
|
||||
BYTE SRB_Lun; // Target's LUN number
|
||||
|
||||
BYTE SRB_DriveFlags; // Driver flags
|
||||
|
||||
BYTE SRB_Int13HDriveInfo; // Host Adapter Status
|
||||
|
||||
BYTE SRB_Heads; // Preferred number of heads translation
|
||||
|
||||
BYTE SRB_Sectors; // Preferred number of sectors translation
|
||||
|
||||
BYTE SRB_Rsvd1[10]; // Reserved
|
||||
|
||||
} SRB_GetDiskInfo, *PSRB_GetDiskInfo;
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user