Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

652 lines
18 KiB

Documentation for DH system libraries.
Thu Jul 6 11:52:33 PDT 1989
*******************
***** DOCLIB *****
*******************
/*** doclib.c - standard DH library routines
*
* This file contains the functions that implement folders
* and documents as abstract data types. While this implementation
* is intended to be portable, it is not definitive.
*
* This implementation supports a canonical folder format;
* the canonical folder format specifies the ordering of bytes
* within a short and long; shorts are assumed to be two bytes
* and longs are assumed to be four bytes. This canonical format
* makes it possible to read folders created on one architecture
* on another architecture; this is particularly important in
* a file-sharing network where the host cpus have different
* natural byte order.
*
* Functions exported from this file:
* getfolder - prepare a DH folder for manipulation
* putfolder - close a folder
* getname - get a DH name for a folder
* getfldlen - get an upper bound on highest docid in folder
* getdoc - get a document
* scanfolder - scan the existing documents
* putdoc - close a document
* deldoc - make a document go away
* getflags - return the attribute flags for a document
* putflags - set the attribute flags for a document
* gettext - write document to stream
* gethdr - get header block
* getbdy - write the body of the document to the passed file handle
* puttext - replace contents of a document
* putbdy - replace the body of a document
* puthdr - set new header block
* getid - get the name of a document
* gethdrlen - get length of a document header
* getbdylen - get length of a document body
* readbdy - read data from body into user buffer
* seekbdy - set address readbdy will read from
*/
/*** Memory Allocation Hooks */
char *(*dh_alloc)(int) = malloc;
void (*dh_free)(char *) = free;
#define memalloc(size) (*dh_alloc)(size)
#define memfree(object) (*dh_free)(object)
/*** getfolder - prepare a DH folder for manipulation
*
* folderhand = getfolder(foldername, function, oper)
*
* get a folder handle for the folder foldername
* function can take one of the following values:
* FLD_CREATE create a new folder
* FLD_SPEC open existing folder
* oper can be either
* FLD_READONLY open for read, deny-write
* FLD_READWRITE open for read-write, deny_all
*/
Fhandle getfolder(char *name, short func, int oper)
/*** putfolder - close a folder
*
* putfolder indicates that this folder is no longer going
* to be manipulated. Thus, we can now deallocate any resources
* associated with that folder, after commiting all buffered data
* to the disk file.
*
* NOTE: This version always blows away handles and the like,
* but it will at least REPORT errors. Need more work
* here to allow recovery from them.
*
* Entry: fh = Fhandle of folder to close
* Return: ERROR or OK
*
*/
short putfolder(Fhandle fh)
/*** getname - get a DH name for a folder
*
* Getname gets the name of an open folder. The name of a folder
* is the canonical pathname of the file that represents the folder.
*
* Entry: fh = handle to relevant folder
* Return: pointer to memalloc'ed string containing name.
*
*/
char *getname(Fhandle fh)
/*** getdoc - get a document
*
* get a document handle for the document indicated by flags [and docid].
* flags can take one of the following values:
* DOC_SPEC document specified by 'docid' in 'folder'
* DOC_CREATE create new document in 'folder'
*
* Entry: fh = Fhandle to parent folder of document
* func = desired action
* docid = document id, if needed
* Return: ERROR if failed, Dhandle to document if successful
*/
Dhandle getdoc(Fhandle fh, short func, Docid docid)
/*** scanfolder - scan the existing documents
*
* return the document id for the specified document
* flags can take one of the following values:
* DOC_SET prepare for scan, return first doc in scan
* DOC_NEXT return next document in scan
*
* Entry: fh = Fhandle to parent folder of document
* func = desired action
* docid = document id
* Return: ERROR if failed, docid of document if successful
*/
Docid scanfolder(Fhandle fh, short func, Docid id)
/*** getfldlen - return upper bound on last docid currently in folder
*
* Entry: fh = handle to folder of interest
* Return: Highest docid currently possible in folder, or ERROR.
*/
Docid getfldlen(Fhandle fh)
/*** putdoc - close a document
*
* Put_doc indicates that the document is no longer going to
* be manipulated. Thus, we can free all the resources that
* are allocated for that document.
*
* Entry: dh = Dhandle to document to close
* Return: none unless there's an error, in which case ERROR
*/
short putdoc(Dhandle dh)
/*** deldoc - make a document go away
*
* deldoc simply calls getdoc and putflags to set DAF_DELETED.
* deldoc will go away.
*
* BUGBUG - deleting an open document will result in chaos
*/
short deldoc(Fhandle fh, Docid docid)
/*** getflags - return the attribute flags for a document
*
* Getflags returns the flag set for a document.
* Only flag bits which are defined for use by applications can
* be returned. The mask argument selects which flags to report
* on. Using a mask of -1L will report on all user manipulable
* flags. Using a mask of DAT_DELETED, for example, will indicate
* whether the given document is deleted. Applications are advised
* to set mask to only report those bits they understand, since new
* bits may be defined in the future.
*
*
* Note: It is NOT an error to request the status of undefined
* flags, it simply isn't allowed. No warning is given.
*
* Entry: dh = handle to document of interest
* mask = one bits select which flags will be reported
* flags = word to fill in with flags
*
* Exit: flags = relevent part of flags word for document
*
* Return: OK or ERROR
*/
short getflags(Dhandle dh, Docflag mask, Docflag *flags)
/*** putflags - set the attribute flags for a document
*
* Putflags sets the flag set for a document.
* Only flag bits which are defined for use by applications can
* be set. The mask argument selects which flags to set.
* Using a mask of -1L will cause all user manipulable flags to
* to be set. Using a mask of DAT_DELETE, for example, will set
* or clear the document's deleted bit. Applications are warned
* to set mask to only those bits they understand, since new
* bits may be defined in the future, and setting such bits will
* usually have unexpected results.
*
* Note: It is NOT an error to request the status of undefined
* flags, it simply isn't allowed. No warning is given.
*
* Note: New flag settings don't take effect until a putdoc is done.
*
* Entry: dh = handle to document of interest
* mask = one bits select which flags will be reported
* flags = values to set flags to
*
* Return: OK or ERROR
*/
short putflags(Dhandle dh, Docflag mask, Docflag flags)
/*** gettext - write document to stream
*
* The entire document, header and all, is written to the
* passed stream in presentation format.
*
* Entry: dh = handle of document to write to stream
* stream = stream to write document onto
*
* Return: ERROR or OK
*/
short gettext(Dhandle dh, short file)
/*** gethdr - get header block
*
* We return a pointer to on allocated piece of memory that
* contains the header for the document. The memory is allocated
* from the heap. Because the memory pointer is returned to the
* user, we must assume that we transfer ownership to the caller.
* Thus, he is responsible for freeing the memory when he no longer
* needs it.
*
* Entry: dh = handle of relevant document
*
* Return: pointer to block of memory if successful
* ERROR if unsuccessful
*/
char *gethdr(Dhandle dh)
/*** getbdy - write the body of the document to the passed file handle
*
* The body of the relevant document is written onto the passed
* file handle.
*
* Entry: dh = handle of document
* file = file handle to write body onto
*
* Return: OK or ERROR
*/
short getbdy(Dhandle dh, short file)
/*** puttext - replace contents of a document
*
* The entire document is replaced by the document read from
* the stream, assumed to be a document is presentation format
*
* Entry: dh = handle of document to replace
* file = file handle to read new document content from
*
* Return: ERROR or OK
*/
short puttext(Dhandle dh, short file)
/*** putbdy - replace the body of a document
*
* The body of the specified document is replaced with the
* body read from the specified file descriptor.
*
* Note - this code is arranged so that if we punt due to a write
* failure, the old version of the document will be left
* intact. Further, we will resize the file to it's previous
* size, and thus avoid filling the disk with trash.
*
* ENTRY dh = handle of document to replace
* ifd = file handle to read body from
*
* RETURN ERROR if some difficulty arises, OK if it worked.
*
*/
short putbdy(Dhandle dh, short ifd)
/*** puthdr - set new header block
*
* The document specified by dh gets a new header,
* which is specified by the memory block that bp points to.
* The header block is NULL terminated byte string.
*
* If new header is <= old header, write it back in place
* to avoid wasting lots of space with redundent header copies.
* Don't update in-memory structures until after write works,
* so that if it fails, things will be as correct as possible.
*
* ENTRY dh = handle of document which will recieve the new header
* bp = pointer to new header block
*
* RETURN ERROR if some problem, else OK.
*
* #ERROR# Should we restore old header if write fails?
* Mark entry corrupt?
*/
short puthdr(Dhandle dh, char *bp)
/*** getid - get the name of a document
*
* The name of the document is its 'document id', really
* just a number. This number is computed based on information
* in the doclist and returned. (ie Convert a document handle -> doc id)
*
* ENTRY dh = handle of document in question
*
* RETURN id of document, or error
*/
Docid getid(Dhandle dh)
/*** gethdrlen - get the length of a document's header
*
* The length of the header is retrieved from the
* index, and returned.
*
* ENTRY dh = handle of document in question
*
* RETURN length of document's header, or ERROR
*/
long gethdrlen(Dhandle dh)
/*** getbdylen - get the length of a document's body
*
* The length of the body is retrieved from the
* index, and returned.
*
* ENTRY dh = handle of document in question
*
* RETURN length of document's body, or ERROR
*/
long getbdylen(Dhandle dh)
/*** readbdy - read data from body into user buffer
*
* readbdy does a "read" on the body of document. (Use gethdr to get
* the header of a document.)
*
* ENTRY dh - document handle for document of interest
* bp - buffer pointer, points to where data should go
* want - how many bytes to read
*
* EXIT got - how many bytes actually read, 0 -> EOF
*
* RETURN OK if things worked (got == 0 for EOF),
* ERROR if some error arose
*/
short readbdy(Dhandle dh, char *bp, unsigned short want, unsigned short *got)
/*** seekbdy - set address readbdy will read from
*
* seekbdy sets the position within the document's body that the next
* readbdy call on that document will start reading from. First byte
* is number 0, implict seekbdy(dh, 0L) is done at getdoc() time.
*
* seekbdy will also return the current read position. If fun = 1, it
* does nothing else.
*
* Seeking beyond the end of a body produces an error. Use getbdylen to
* learn the length of a document's body.
*
* ENTRY dh - document handle for document of interest
* fun - function 0 -> set position, 1 -> return current position
* rpos - new position to set if fun = 0
*
* EXIT oldrpos - previous position
*
* RETURN ERROR or OK
*/
short seekbdy(Dhandle dh, short fun, long rpos, long *oldrpos)
*******************
***** TMPNAME *****
*******************
/*** mktmpnam - make mktemp behave in a reasonable way
*
* mktmpnam duplicates the pattern string, passed the duplicate into
* mktemp (thus preserving the pattern string), and returns the address
* of the new name string. Use free to dispose of the new string.
*
* mktmpnam will examine the contents of the environment variable
* "TMPENV" (TMP on Xenix or Dos systems) to learn what directory
* the temp file should go in. If no such environment variable exists
* or it is NULL, mktmpnam will use a system dependent default, specified
* by the defined variable TMPDEF.
*
* RETURN address of file name string, NULL if failure
*
*/
char *mktmpnam()
*******************
***** DOCLIST *****
*******************
/*** dlist.c - code to handle creation of DH style doclists
*
*/
/*** adddl - add an entry to the output document list
*
* adddl adds an entry to the output doclist, which is eventually
* written to standard output.
*
* Entry: fh = handle to relevant folder
* did = document id of relevant document in folder
*/
void adddl(Fhandle fh, Docid did)
/*** putdl - ???
void putdl()
*******************
***** MAP *****
*******************
/*** map - apply functions to lists of documents
*
* This file contains the code required to apply functions
* to lists of documents.
*
* A 'Document list' is a sequence of entries; each entry
* specifies a folder and some documents in that folder.
* The grammar for an entry is:
* <entry> ::= <foldername> |
* <list> |
* <foldername> ':' <list>
*
* The first production for <entry> specifies all of the
* documents in the folder.
*
* The second production for <entry> specifies the <list>
* of documents in the current folder.
*
* The third production for <entry> specified the <list>
* of documents in <foldername>.
* The foldername is the DH pathname of the folder.
*
* The <list> is composed as follows:
* <list> ::= <list> ',' <element> |
* <element> |
* <element> ::= <num> |
* <num> '-' <num> |
* <num> '-' |
* '-' <num>
*
* A list specifies all of the documents specified by its
* component elements.
*
* The first production for <element> specifies a single document.
*
* The second production specifies all of the documents whose
* docid is greater than or equal to the first num, and less
* than or equal to the second num.
*
* The third production specifies all the documents whose
* docid is greater than or equal to the given number.
*
* The fourth production specifies all the documents whose
* docid is less than or equal to the given number.
*/
/*** map - map a function over a document list
*
* Function is called once for each document listed
* by the document list passed as name. Basically, we
* break off the folder name, open the folder, and
* pass the buck to mapdoc. One special case
* is that we handle the special document list '-'
* here, reading the real document list from
* stdin, and calling map recursively. Note that
* document lists read from stdin cannot use the
* '-' list.
*
* Entry: first = ptr to function to call when folder is opened.
* func = function to be called for each document
* last = ptr to function to call before folder is closed.
* doclist = string of documents to work on
* oper = how to open folder (FLD_READONLY or FLD_READWRITE)
* Exit: none
*
*/
void map(int (*first)(), int (*func)(), int (*last)(),
char *doclist, int oper)
/*** null - do nothing function to satisfy 'map()'
*
* Map expects to get a function to call when each folder
* is first gotten, and another to call just before it is
* put back. This function is made available for programs
* that wish to do nothing at those points.
*
* Entry: fh = handle of folder
* Return: nothing
*/
void null(Fhandle fh)
*******************
***** HEADER ******
*******************
/*** dh.h - standard header file for DH programs
*/
/*
* Environment names
*/
#define EDITENV "EDITOR" /* name of default editor */
#define PATHENV "DHPATH" /* path string to search for folder */
#define TMPENV "TMP" /* path of directory to hold temporary files */
/*
* Defaults
*/
#define EDITDEF "vi" /* default editor, if not in enviroment */
/* TMPDEF defines the default temporary directory to use if one can't be
found in the environment. (This varies from system to system.) */
#ifdef XENIX
#define TMPDEF "/tmp"
#endif
#ifdef MSDOS
#define TMPDEF "\\"
#endif
/* TMPPATT is the last component of the path name passed to mktemp */
#ifdef XENIX
#define TMPPATT "/dhXXXXXX"
#endif
#ifdef MSDOS
#define TMPPATT "\\dhXXXXXX"
#endif
/*
* Fundmental characters
*/
#ifdef XENIX
#define PATHSEP '/' /* separator char in pathnames */
#define PATHBRK ':' /* separator char in search path */
#endif
#ifdef MSDOS
#define PATHSEP '\\' /* separator char in pathnames */
#define PATHBRK ';' /* separator char in search path */
#endif
/*
* System specific constants
*/
#ifdef XENIX
#define MAXPATH 128
#endif
#ifdef MSDOS
#define MAXPATH 128
#endif
/* Folder object declarations */
#define FLD_SPEC 1
#define FLD_CREATE 2
typedef short Fhandle;
/* Folder operation decls - legal values for "oper" arg to getfolder */
#define FLD_READONLY 0 // Readonly, deny_write
#define FLD_READWRITE 1 // Read-write, exclusive
/* Document object declarations */
#define DOC_SET 1
#define DOC_NEXT 2
#define DOC_SPEC 3
#define DOC_CREATE 4
typedef short Dhandle;
typedef short Docid;
typedef unsigned long Docflag;
#define ERROR -1
#define OK 0
#define MINDOCID 1
/* Document attribute flags */
#define DAF_DELETED 2L /* Set if deleted */
/* Bits app can set or clear */
#define DAF_NOTRESERVED DAF_DELETED
/* Declarations for functions */
/* Folder functions */
Fhandle getfolder(char *name, short func, int oper);
short putfolder(Fhandle);
char *getname(Fhandle);
Docid getfldlen(Fhandle);
/* Document access functions */
Dhandle getdoc(Fhandle, short, Docid);
short putdoc(Dhandle);
Docid getid(Dhandle);
Docid scanfolder(Fhandle, short, Docid);
short deldoc(Fhandle, Docid);
/* Document manipulation functions */
short gettext(Dhandle, short);
short puttext(Dhandle, short);
short getflags(Dhandle, Docflag, Docflag *);
short putflags(Dhandle, Docflag, Docflag);
char *gethdr(Dhandle);
short puthdr(Dhandle, char *);
short getbdy(Dhandle, short);
short putbdy(Dhandle, short); /* Should use this one. */
short readbdy(Dhandle, char *, unsigned short, unsigned short *);
short seekbdy(Dhandle, short, long, long *);
long gethdrlen(Dhandle);
long getbdylen(Dhandle);
/* interface to 'map' */
void map(int (*first)(), int (*func)(), int (*last)(),
char *doclist, int oper);
void null();
/* interface to doclist construction routines */
void adddl();
void putdl();
/* interface to mktmpnam */
char *mktmpnam();