home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / oxcc1433.zip / DOC / CFF.TXT < prev    next >
Text File  |  1995-11-05  |  67KB  |  1,957 lines

  1.  
  2.                      Culvers Fabulous Filesystem
  3.                             Version 5.5
  4.                            Gamma Release
  5.                            June 15, 1995
  6.  
  7.               Copyright 1991, 1992, 1993, 1994, 1995 Norman D. Culver
  8.                           All Rights Reserved
  9.  
  10.  
  11.                     Send bug reports and suggestions to:
  12.                             ndc@gcomm.com
  13.                                  or
  14.                             Oxbow Software
  15.                        1323 S.E. 17th Street #662
  16.                         Ft. Lauderdale, FL 33316
  17.                          (305) 527-1663 Phone
  18.                          (305) 760-7584 Fax
  19.  
  20.  
  21.         This software package is distributed as a preliminary version for
  22.                 TESTING PURPOSES ONLY, WITHOUT ANY WARRANTY;
  23.                    without even the implied warranty of
  24.             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  25.  
  26.              This product includes software developed by the
  27.              University of California, Berkeley and its contributors.
  28.  
  29.  
  30. GENERAL DESCRIPTION
  31.  
  32. This distribution contains a single threaded 32 bit portable library
  33. compiled with gcc for the Intel 386 cpu. The library contains external
  34. references to functions in 'cfport.c' which is supplied as source code.
  35. The user can modify cfport.c to accommodate a non-unix like OS.
  36.  
  37. The user API for the library is declared in the file 'cff.h' and described
  38. in this document. CFF is a filesystem/database engine which handles
  39. allocation of memory, extended memory and disk. It supports incrementally
  40. hashed and B+ tree storage maps in an identical fashion for memory and
  41. disk. The standard flavors of malloc are included. NEW for the first time,
  42. to my knowledge, is the ability to malloc by category and the ability
  43. to malloc PERMANENTLY.
  44.  
  45. Data is stored in and accessed through 'objects' which are referenced
  46. in the classical filesystem manner. e.g. MEMORY/myobject/subobject/...
  47. Objects are opened and closed in the time honored unix fashion. But there
  48. is a big difference between CFF objects and normal filesystem objects.
  49. Each object has the properties of a directory, stack, file, dictionary and
  50. repository. Objects can be created as F_SORTED, in which case they are
  51. B+ trees, and/or with their own local 'bitmaps' for locality of reference,
  52. or, if hashed, with PREALLOCATED DATA AND ENTRIES for ultra fast inserts.
  53. The objects expand and shrink automatically as entries are added or deleted.
  54. The in-core index for hashed objects is never saved to disk because it can be
  55. rebuilt when the object is loaded. Data can be accessed directly in the
  56. localizer buffers or copied to/from user space.
  57.  
  58.  
  59. COPY OBJECTS
  60.  
  61. The 'cfcopy' command will move an object and all subobjects within and
  62. between filesystems. A filesystem on disk is denoted with the extension
  63. '.cff'.     The filesystems for memory and extended memory
  64. (if it exists) are predefined as MEMORY and EXTDMEM. The copy command
  65. will create a filesystem on disk if an object is copied to a '.cff' object.
  66.  
  67. The command: 
  68.  
  69.     cfcopy("newsys.cff", "MEMORY/object/subobject/target");
  70.  
  71. copies the object named 'target' to the disk file newsys.cff and thus
  72. 'target' becomes a filesystem. Conversely, filesystems can become objects, etc.
  73.  
  74.  
  75. PATHNAME TRANSLATION
  76.  
  77. A pathname translation facility permits brevity.
  78. Translation dictionaries are maintained for process, application and system.
  79.  
  80. Example:
  81.  
  82. void *h1, *h2;
  83.  
  84.      cfdef("phone book", "myfile.cff/users/applications/faxmodem/phones");
  85.      h1 = cfopen("phone book", F_RDWR, NULL);
  86. or
  87.      h2 = cfcopy("MEMORY/tempobj", "phone book");
  88.      
  89. or
  90.      h2 = cfcopy("MEMORY/tempobj", h1);
  91.  
  92. And when finished you can get a fully garbage collected and shrunk disk object 
  93. with the command:
  94.  
  95.  
  96.     cfcopy(h1, h2);
  97. or
  98.     cfcopy("phone book", h2);
  99. or
  100.     cfcopy("phone book", "MEMORY/tempobj");
  101.  
  102.  
  103. EXTERNAL FILES
  104.  
  105. It is possible to access normal OS files and directories. If a path doesn't
  106. reference a .cff filesystem then it is assumed to be external. Copy to/from an
  107. external file only exercises the file property of an object, so it is
  108. trivial to import/export external data.
  109.  
  110.  
  111. FANCY MALLOCS
  112.  
  113. The CFF library supplies standard versions of malloc, calloc, realloc etc.
  114. which MUST superceed the standard compiler versions. Don't worry, these
  115. implementations are fast and debugged. This BETA version of the library
  116. does not include debugging support for when you corrupt the heap, it will be
  117. in the commercial version when it is released.
  118.  
  119. The enhancements to malloc are simple to use but rather complicated to
  120. implement. They permit the programmer to malloc, calloc, free etc. by
  121. CATEGORY and they are FAST. Category 0 is reserved for normal malloc, and
  122. is somewhat segregated in the address space because it calls 'sbrk()'
  123. directly. All other categories call cfmalloc() which does it's own calls
  124. to sbrk (actually PORTSBRK in cfport.c). NOTE: Normal malloc, etc. will work
  125. even if cfinit() is not issued. This is nice.
  126.  
  127. Examples:
  128.  
  129. void *ptr;
  130.  
  131.     ptr = mallocC (5, 1024);  // malloc 1K bytes for category 5
  132.     freeC (5, ptr);           // free the pointer in category 5
  133.     freecat (5);              // free all memory allocated to category 5
  134.  
  135. Permanent categories have negative numbers.
  136.  
  137.     ptr = malloc (-20, 1024);  // malloc 1K bytes for permanent category -20
  138.     freeC (-20, ptr);          // free the pointer in category -20
  139.     freecat (-20);             // free all memory allocated to category -20
  140.  
  141.  
  142. Permanent categories are enabled only if the programmer has named a
  143. filesystem when 'cfinit' is called.
  144.  
  145. main()
  146. {
  147. cfinit("app1", 512, "myfile.cff"); // enables permanent categories in myfile.cff
  148. or
  149. cfinit("app1", 512, NULL);         // permanent categories are disabled;
  150.  
  151. ...
  152.  
  153. cfexit(); // saves active permanent categories and closes objects
  154.           // cfinit calls atexit with this function, you do not
  155.           // have to include it in the program, but it is harmless to do
  156.           // so.
  157. }
  158.  
  159. Data in active permanent categories is reloaded to exactly the same memory
  160. addresses at program startup and saved in the named filesystem at program exit.
  161. Creep in the data segment as program development proceeds is accommodated
  162. by setting the variable 'heapstart' in cfport.c. The programmer should
  163. pick a number large enough to accommodate the environment in which development
  164. is taking place. If C++ is used, static constructors can gobble a lot of
  165. space before cfinit() is called. The command cfcreep() returns the amount
  166. of space in the safety zone. WARNING: you can't change heapstart after
  167. permanent categories have been saved in a file.
  168.  
  169. The named filesystem can hold permanent categories for multiple applications
  170. providing the applications are uniquely identified by the first argument
  171. to cfinit().
  172.  
  173. In a clean design, a programmer would save a small number of pointers (one??)
  174. to a complex memory structure which will come and go automatically as the
  175. application is run. The purpose here is to speed up the process of loading
  176. permanent objects. Some CAD programs take 30 minutes to start; with CFF
  177. startup can be reduced to seconds on similarly endianed machines.
  178.  
  179. for example:
  180.  
  181. main()
  182. {
  183. struct masterstruct *masterptr;
  184.     
  185.     cfinit("myapp", 256,"myfile.cff");  // PERMINFO is now defined
  186.     if(!cfisnew(PERMINFO))
  187.     {/* The file is not new, load the saved copy of masterptr */
  188.         cfget(PERMINFO, "masterptr", 9, &masterptr, sizeof(void *));
  189.     }
  190.     else
  191.     {/* The file is new, build the basic structures */
  192.         masterptr = mallocC(-1, sizeof(masterstruct)); // or whatever
  193.  
  194.         ...  // build memory structures based on masterptr
  195.              // and various negative categories
  196.     }
  197.  
  198.     ...  // use and modify the permanent structures
  199.          // always use negative categories
  200.  
  201.     /* Save the master pointer before exit */
  202.     cfreput(PERMINFO, "masterptr", 9, &masterptr, sizeof(void *));
  203.     cfexit();
  204. }
  205.  
  206. PREDEFINED PATHNAMES (use as the leading element of a path)
  207.  
  208.     MEMORY    the memory filesystem
  209.     EXTDMEM   the extended memory filesystem
  210.  
  211. PREDEFINED PATHNAMES or HANDLES (use as the leading element or as a handle)
  212.  
  213.     PERMFILE  the filesystem which was mentioned in cfinit()
  214.     PERMCAT   an object in PERMFILE containing the app's permanent categories
  215.     PERMINFO  an object in PERMFILE into which the user can store app info
  216.  
  217.  
  218. PREDEFINED HANDLE (use only as a handle)
  219.  
  220.     MEMTEMP    a memory object which can be used by the programmer
  221.  
  222. ALIGNMENT
  223.  
  224. The granularity of the BETA release is 16 bytes for malloc and 32 bytes
  225. for filesystem allocations. I am considering allowing each bitmap to 
  226. carry a different alignment, if all programmers used gcc then I could
  227. use long long arguments in the user API.
  228.  
  229. NODE SIZES
  230.  
  231. Node (bucket) sizes can range from 512 bytes to 8192 bytes. When an
  232. object is created, the default size is 2048 bytes. The programmer can
  233. modify this size by setting a flag in the mode bits for cfopen. The
  234. root directory of a filesystem is defaulted to 1024 bytes per node.
  235.  
  236.         F_FILEONLY      512 bytes
  237.         F_BIGDIR        4096 bytes
  238.         F_HUGEDIR       8192 bytes
  239.         
  240.  
  241. KEYS, ITEMS and DATA
  242.  
  243. Keys are the names of things in the filesystem. When used as part of a 
  244. path the key must contain only characters in the range 0x40 to 0x7f 
  245. (space to tilde) or it will be rejected by the name translation mechanism.
  246. In all other cases a key may contain anything. When using hashed objects
  247. the programmer should make a distinction between long and short keys.
  248. Short keys are 8 bytes or less and are stored directly in the hash buckets
  249. along with Items. Long keys are stored in a special KEYCACHE area and
  250. require the overhead of the hash bucket entry which is 20 bytes plus
  251. the overhead of the KEYCACHE which is 13 bytes + the size of the key.
  252. Note: the minimum KEYCACHE allocation is 32 bytes. When a long key is
  253. stored in a hash bucket the 8 byte key region is converted to an alternative
  254. hash value for the key, this ensures that only one key comparison
  255. is ever done. B+ tree objects store the keys and items together in the
  256. tree nodes. The programmer should ensure that at least 2 keys will fit
  257. into a B+ tree node, 1 key per node results in a B tree.
  258.  
  259. The key comparison routine can be set for each object with the command
  260. cfkeycmp(handle, funcaddr);
  261.  
  262. Items are the basic insertable/retrievable elements in a node. They are
  263. 64 bits in size with the high 4 bits reserved for tags. B+ trees can support
  264. untagged items if created with F_UNTAGGED set.
  265.  
  266. The programmer will find that 64 bit items are a bit of a pain, especially
  267. if his compiler does not support the long long type. They are worth the
  268. extra effort, believe me.
  269.  
  270. When the system stores a tagged item it checks the high 4 bits, if they
  271. are non-zero it assumes that a tag is already present, otherwise the
  272. item is tagged as a STO_VALUE. Be SURE that your program generated items
  273. have the high 4 bits set to zero.
  274.  
  275. Due to the tagged nature of most items, the system can automatically allocate
  276. and deallocate storage if the item happens to describe a chunk of data.
  277. Currently the maximum size of a single contiguous chunk is 16 Megabytes -1.
  278. This can change if I implement adjustable alignment per bitmap.
  279. See the file cff.h for tag values.
  280.  
  281. The item comparison routine can be set for each object with the command
  282. cfitemcmp(handle, funcaddr);
  283.  
  284. A copy of the default keycmp and itemcmp functions are located in the
  285. module cfport.c so that the programmer can see what needs to be done for
  286. alternative functions.
  287.  
  288.  
  289. HASHED vs SORTED
  290.  
  291. The default method for an object is hashed. The root directory of a
  292. filesystem is forced to be hashed even if created as F_SORTED. Thus
  293. a SORTED object cannot become a filesystem with the cfcopy command.
  294. I may change this but it complicates opening a filesystem.
  295.  
  296. SORTED pros
  297. 1. Sequential access of a sorted object produces sorted output.
  298. 2. Sorted objects can support untagged items, no subobjects are allowed.
  299. 3. Normal mode duplicate entries have the overhead of only one key per node.
  300. 4. An unlimited number of normal mode duplicate entries is supported.
  301. 5. There is no in-core index for the nodes. This could be important for
  302.    an object with 100 million items.
  303. 6. Inserts and deletes to sorted objects do not invalidate the mark.
  304.  
  305. SORTED cons
  306. 1. Access and update of sorted objects is MUCH slower than hashed.
  307. 2. Key length is limited by the node size.
  308.  
  309. HASHED pros
  310. 1. Hashed objects are fast to update and access, and VERY fast with short keys.
  311. 2. Key length is unlimited (16 Megabytes).
  312. 3. Hashed objects can be created with PREALLOCATED entries and data. This
  313.    produces complete locality of reference and great speed when creating
  314.    a database.
  315.  
  316. HASHED cons
  317. 1. The in-core index for each object takes up space (4 bytes per bucket).
  318.    This is a consideration when the object contains a lot of items. The
  319.    maximum bucket of 8192 bytes contains 406 items.
  320. 2. Normal mode duplicate entries is limited to 406 dups.
  321. 3. Under pathological conditions the hashed object may fill up, i.e. a
  322.    bucket may contain a mix of keys which cannot be split.
  323. 4. Sequential access to a hashed object produces unsorted output.
  324.  
  325.  
  326.  
  327. DUPLICATE ENTRIES
  328.  
  329. Keys with duplicate entries are supported in two ways: the normal
  330. 'dupnum' way and the 'dupname' way. Dupnames are 48 bit unique names + a 12 bit
  331. unique id. Each object can support and control 4093 dupname sets.
  332. Dupnames can be used as keys or items. Normal dups must be accessed by
  333. a key-item combination or sequentially; the items for each normal 
  334. dup should be different.
  335. DO NOT MIX NORMAL AND DUPNAME DUPLICATES.
  336.  
  337.  
  338. OBJECTS AS FILES
  339.  
  340. Any object is a file, just read and write to it. If you read
  341. before writing, read will return ERROR. When an object is closed
  342. space allocated to the file property is truncated to within 128 bytes
  343. of the filesize, filesize is limited to 2G bytes.
  344.  
  345.  
  346. OBJECTS AS STACKS
  347.  
  348. Any object is a stack, just push and pop items or data. Stacks retain
  349. their data when an object is closed and/or copied, stack depth is unlimited.
  350.  
  351. OBJECTS AS DIRECTORIES
  352.  
  353. Any object is a directory, just create a subobject (subdirectory) with
  354. the cfopen or cfsubopen commands. The directory property can be accessed
  355. with cfopendir, cfreaddir, cfrewinddir, cftelldir, cfseekdir and cfclosedir.
  356.  
  357.  
  358. OBJECTS AS DICTIONARIES
  359.  
  360. Any object is an dictionary, just insert, find and delete keyed items.
  361. To find out what is in an object, issue the command cfprintentries(something).
  362.  
  363. OBJECTS AS REPOSITORIES
  364.  
  365. Any object is a repository, just put and get keyed data chunks 
  366. (max 16Meg per chunk, min 32 bytes per chunk).
  367.  
  368.  
  369. INTERNAL BUFFERING
  370.  
  371. This BETA version supports 512 buffer headers and unlimited data
  372. buffering. The cfinit command includes an argument for the number of 1K blocks
  373. of data buffering allowed. cfinit("app",700,NULL) designates that 700K of 
  374. memory be allocated to buffering.
  375.  
  376. Data chunks can be accessed directly in the buffer region with the command
  377. cflocalize(). The localizer will allow up to half of the defined
  378. data region to be allocated to a single localization request, excess
  379. buffers are flushed. The size of the data region may be increased/decreased
  380. dynamically with the cfmodbufs() command.
  381.  
  382. This localizer does not localize blocks; it localizes chunks which may
  383. be large or small. Most of the time the localizer is working with nodes
  384. and keys so the memory reqirements are not large internally. The file
  385. property is read/written in 8K chunks. If the user creates a huge chunk
  386. then it is up to the user to deal with it.
  387.  
  388. Huge data chunks can be accessed with the command cfopen_chunk() followed
  389. by reads and writes to the returned handle.
  390.  
  391.  
  392. LAZY WRITING
  393.  
  394. The writethrough properties of an object can be set with the commands
  395. cfsetlazy(handle) and cfsetverylazy(handle). The command cfclrlazy(handle)
  396. causes the object and all underlying buffers, including the OS, to be flushed.
  397. The default writethrough property of an object causes it to be up to date
  398. at the user API level. By this I mean that the CFF buffers are written to
  399. the OS buffers. In order to ensure that the OS buffers are flushed, the
  400. programmer should issue cfflush(handle) and cfsync() commands when appropriate.
  401.  
  402.  
  403. BITMAPS
  404.  
  405. The term 'bitmaps' is misleading. CFF uses extent maps which are 512 bytes
  406. in size and contain 49 sorted entries per map. Each bitmap set has an
  407. in-core sorted index. The root directory of each filesystem has a bitmap
  408. set by default. Individual objects can be created with a bitmap which
  409. will control space allocation for the object and it's subobjects. If an
  410. object has a bitmap it can be deleted very quickly, the system merely returns
  411. all the space defined by the maps to the parent maps. Without a bitmap the
  412. deletion of a complex object can take a while. Nevertheless, DO NOT USE
  413. BITMAPS unless you know what you are doing. This is because they lead to
  414. fragmentation in any environment that involves active insertions and deletions.
  415. Preferably you would pre-allocate all the anticipated space to the bitmap
  416. when you create the object, but this usually means that you allocate a lot
  417. more than is really needed. To find out more about bitmaps, issue the command
  418. cfprintbitmaps(something). Hashed objects which have preallocated data and
  419. entries do not return space to the controlling bitmaps when something
  420. is deleted, this is good. To shrink a sparsely populated preallocated hashed 
  421. object, copy it.
  422.  
  423. CFF maintains two caches for each set of bitmaps, the KEYCACHE is used
  424. for storage of hashed keys and tends to segregate long keys from the data,
  425. this is good; the CACHE is used to dispense space for data, and nodes.
  426. Bitmaps are stored in the space that they map; often as the first 512
  427. bytes.
  428.  
  429.  
  430. GARBAGE COLLECTION
  431.  
  432. The system actively returns space to the underlying bitmaps and
  433. also coalesces the bitmaps in a timely manner. The system currently does not
  434. compress an object or filesystem in place, i.e. rearrange the placement
  435. of things so that the end of a bitmap contains a nice chunk of space that
  436. can be returned to it's parent. cfcopy() is the rich man's substitute.
  437.  
  438.  
  439. ERROR REPORTING
  440.  
  441. Version 5.4 has very uninformative error reporting.
  442.  
  443.  
  444. ACCESS CONTROL and SECURITY
  445.  
  446. Version 5.4 has no access control or security.
  447.  
  448.  
  449. FILE AND RECORD LOCKING
  450.  
  451. Version 5.4 has no locks.
  452.  
  453.  
  454. DATA COMPRESSION
  455.  
  456. An adaptation of gzip is used to achieve automatic data compression of
  457. permanent categories. Two calls, cfzip() and cfunzip() are provided
  458. for the programmer.
  459.  
  460.  
  461. STDIO STYLE I/O
  462.  
  463. A set of 'stream' calls is included. These calls work with objects, data 
  464. chunks, values, external files and raw devices. There are several additional
  465. opening modes: unique,temp,string,stat,text,binary.
  466.  
  467.  
  468. INFORMATIONAL PRINTING
  469.  
  470. The programmer can set the system print function with the command
  471. cfsetprintfunc(int (*funcptr)(int));
  472.  
  473. The print function prints one character at a time and returns 1 if OK
  474. and -1 if a device error.
  475.  
  476. The default print function calls PORTPRINT in cfport.c which writes
  477. one character to file descriptor 1. Unbuffered printing gets you all
  478. there is to see even when the system aborts.
  479.  
  480. CFF contains a built in printf 'cfprintf' which is reentrant and
  481. prints one character at a time.
  482.  
  483.  
  484. cfprintbitmaps(void *something);
  485. Prints the bitmaps of something (a path or handle) and it's parents.
  486.  
  487.  
  488. cfprintentries(void *something);
  489. Prints the contents of the storage maps of something (a path or handle).
  490.  
  491.  
  492. cfpflags(char *label, void *handle)
  493. Prints the flags for an open object and its parents, 
  494. adds a programmer supplied label string.
  495.  
  496.  
  497.  
  498. THE COMMAND SET
  499.  
  500. NOTATION:
  501. void *something     Denotes a path or handle (use either one). 
  502.                     If a path, the object need not be open.
  503. void *handle        Denotes a handle for an open object or data chunk.
  504.  
  505.  
  506.  
  507. INITIALIZATION AND EXIT
  508.  
  509. void cfinit(
  510.               char *appname,    // the name of the application
  511.               int bufferspace,  // size of buffer area in KB
  512.               char *permfile    // path of file containing permanent objs
  513.            )
  514. Initialize, load permanent malloc categories from permfile,
  515. load application and system string definitions from permfile,
  516. define PERMFILE, PERMCAT and PERMINFO to refer to the appropriate
  517. objects in permfile, add 'cfexit()' to the atexit list.
  518.  
  519.  
  520. void cfexit(
  521.             void
  522.            )
  523. Save permanent malloc categories, save current application and system string
  524. definitions, close all open objects.
  525.  
  526.  
  527. OPEN CLOSE READ WRITE etc.
  528.  
  529. typedef struct opninfo {
  530.     long initial_entries;  // if hashed object, preallocates buckets
  531.     unsigned long bitmap_prealloc;  // if object has bitmap, initial space
  532.     long data_prealloc;    // if hashed object, data space per initial entry
  533. } OPNINFO;
  534.  
  535. /* OPEN MODE BITS */
  536.  
  537. #define F_RDONLY    0x0001     // The object is readonly, the parents are rdwr
  538. #define F_WRONLY    0x0002     // I don't think this works
  539. #define F_RDWR      0x0003
  540. #define F_CREAT     0x0004     // create if non-existant
  541. #define F_TEMP      0x0008     // delete on close
  542. #define F_UNIQ      0x0010     // create a unique name and append to path
  543. #define F_EXCL      0x0020     // non shared open
  544. #define F_BITMAP    0x0040     // attach a bitmap
  545. #define F_TRUNC     0x0080     // truncate on open
  546. #define F_APPEND    0x0100     // only append when writing to file
  547. #define F_FILEONLY  0x0400     // 512 byte nodes
  548. #define F_BIGDIR    0x0800     // 4096 byte nodes
  549. #define F_HUGEDIR   0x1000     // 8192 byte nodes
  550. #define F_SORTED    0x8000     // B+ tree
  551. #define F_UNTAGGED  0x10000    // items are untagged if B+ tree
  552. #define F_STAT      0x20000    // The object and parents are readonly
  553.  
  554. void *cfopen(
  555.                 char *path,        // pathname of object
  556.                 long mode,        // open mode bits
  557.                 void *info        // pointer to OPNINFO struct or NULL
  558.             )
  559. Returns an opaque handle or NULL, check errno.
  560. Will also open a chunk or value for reading 
  561. (the key must contain only legal chars).
  562.  
  563. void *cfsubopen(
  564.                 void *handle,    // handle of open object
  565.                 void *name,        // name of subobject
  566.                 long mode,        // open mode bits
  567.                 void *info        // pointer to OPNINFO struct or NULL
  568.                )                
  569. Pastes the path, this is a convenience for the programmer.
  570. Returns an opaque handle or NULL, check errno.
  571. Will also open a chunk or value for reading 
  572. (the key must contain only legal chars).
  573.  
  574. void *cfopen_chunk(
  575.                    void *handle,    // handle of open object
  576.                    void *item        // pointer to an Item describing a chunk
  577.                   )
  578. Permits read/write access to a fixed length chunk of data.  
  579. Use cfclose() when finished.
  580. Returns an opaque handle or NULL, check errno.
  581.  
  582. void cfclose(
  583.              void *handle
  584.              )
  585. Closes and flushes whatever is referenced by the handle.
  586. If an object or file has been created with F_TEMP, it is deleted on close.
  587.  
  588. void cfflush(
  589.              void *handle
  590.              )
  591. Ensures that all information pertaining
  592. to the object or external file is written out.
  593.  
  594. void cfsync()
  595. Ensures that all information pertaining
  596. to all open objects and external files is written out.
  597.  
  598. long cfread(
  599.             void *handle,
  600.             void *userbuffer,
  601.             long amount
  602.             )
  603. Reads from a file or a chunk.
  604. Returns amount read or ERROR, check errno.
  605.  
  606. long cfwrite(
  607.              void *handle,
  608.              void *userbuffer,
  609.              long amount
  610.             )
  611. Writes to a file or a chunk.
  612. Returns amount written or ERROR, check errno.
  613.  
  614. long cfseek(
  615.             void *handle,
  616.             unsigned long amount,
  617.             int mode
  618.            )
  619. Seeks within a file or a chunk.
  620. It is legal to seek past the end of a file.
  621. CFF Version 5.4 files do not have holes.
  622. Returns position or ERROR
  623.  
  624. /* Seek modes */
  625. #define S_SET 0
  626. #define S_CUR 1
  627. #define S_END 2
  628.  
  629. int cftruncate(
  630.                void *something,
  631.                unsigned long size
  632.               )
  633. Truncates the file property to 'size', returns OK or ERROR
  634.  
  635.  
  636.  
  637. SEQUENTIAL DIRECTORY ACCESS -- JUST LIKE POSIX almost
  638.  
  639. typedef struct cfdirent {
  640.     int d_namlen;
  641.     char *d_name;
  642.     unsigned long d_bytesalloc;
  643.     unsigned long d_bytesused;
  644.     unsigned long d_mode;
  645.     unsigned long d_entrycnt;
  646.     void *d_fpt;
  647. } CFDIRENT;
  648.  
  649. void *cfopendir(
  650.                 void *something,   // path or handle
  651.                )
  652. Opens the directory and dictionary aspects of a path or handle.
  653. Works for external files.
  654. Returns opaque handle, or NULL, check errno.
  655.  
  656.  
  657. void cfclosedir(
  658.                 void *openhandle
  659.                )
  660. Close using the handle produced by cfopendir.
  661.  
  662.  
  663. CFDIRENT *cfreaddir(
  664.                     void *openhandle
  665.                    )
  666. Returns a pointer to a CFDIRENT struct, or NULL if EOD.
  667. The nodes (sub-directories) are returned.
  668.  
  669. CFDIRENT *cfreadfulldir(
  670.                     void *openhandle
  671.                    )
  672. Returns a pointer to a CFDIRENT struct, or NULL if EOD.
  673. Nodes, values and chunks are returned.
  674.  
  675. void cfrewinddir(
  676.                  void *openhandle
  677.                 )
  678. Reset to beginning of directory.
  679.  
  680.  
  681. void cftelldir(
  682.                void *openhandle,
  683.                STOR *curentry
  684.               )
  685. Returns a pointer to the current directory entry.
  686.  
  687.  
  688. void cfseekdir(
  689.                void *openhandle,
  690.                STOR *curentry
  691.               )
  692. Sets the directory search to the spot returned by cftelldir.
  693.  
  694.  
  695. SEQUENTIAL INDEX ACCESS
  696.  
  697. long cfhead(
  698.             void *handle,
  699.             Item *itemptr
  700.            )
  701. Goto beginning of entries, get current item.
  702. Returns OK or ERROR, 
  703.  
  704. long cfhead_dupnum(
  705.                    void *handle
  706.                    void *keyptr,
  707.                    int   keylen,
  708.                    void *itemptr
  709.                   )
  710. Goto beginning of normal duplicate entries for the key, get current item.
  711. Returns OK or ERROR
  712.  
  713. long cfhead_dupname(
  714.                    void *handle
  715.                    void *keyptr,
  716.                    int   keylen,
  717.                    void *itemptr
  718.                   )
  719. Goto beginning of DupName duplicate entries for the key, get current item.
  720. Returns OK or ERROR
  721.  
  722. long cftail(
  723.             void *handle,
  724.             Item *itemptr
  725.            )
  726. Goto end of entries, get current item.
  727. Returns OK or ERROR, 
  728.  
  729. long cftail_dupnum(
  730.                    void *handle
  731.                    void *keyptr,
  732.                    int   keylen,
  733.                    void *itemptr
  734.                   )
  735. Goto end of normal duplicate entries for the key, get current item.
  736. Returns OK or ERROR
  737.  
  738. long cftail_dupname(
  739.                    void *handle
  740.                    void *keyptr,
  741.                    int   keylen,
  742.                    void *itemptr
  743.                   )
  744. Goto end of DupName duplicate entries for the key, get current item.
  745. Returns OK or ERROR
  746.  
  747. long cfnext(
  748.             void *handle,
  749.             Item *itemptr
  750.            )
  751. Goto next sequential entry, get current item.
  752. Returns OK, EOI or ERROR, 
  753.  
  754. long cfnext_dupnum(
  755.                    void *handle
  756.                    void *keyptr,
  757.                    int   keylen,
  758.                    void *itemptr
  759.                   )
  760. Goto next normal duplicate entry for the key, get current item.
  761. Returns OK, EOI or ERROR
  762.  
  763. long cfnext_dupname(
  764.                    void *handle
  765.                    void *keyptr,
  766.                    int   keylen,
  767.                    void *itemptr
  768.                   )
  769. Goto next DupName duplicate entry for the key, get current item.
  770. Returns OK, EOI or ERROR
  771.  
  772. long cfprev(
  773.             void *handle,
  774.             Item *itemptr
  775.            )
  776. Goto previous sequential entry, get current item.
  777. Returns OK, BOI or ERROR, 
  778.  
  779. long cfprev_dupnum(
  780.                    void *handle
  781.                    void *keyptr,
  782.                    int   keylen,
  783.                    void *itemptr
  784.                   )
  785. Goto previous normal duplicate entry for the key, get current item.
  786. Returns OK, BOI or ERROR
  787.  
  788. long cfprev_dupname(
  789.                    void *handle
  790.                    void *keyptr,
  791.                    int   keylen,
  792.                    void *itemptr
  793.                   )
  794. Goto previous DupName duplicate entry for the key, get current item.
  795. Returns OK, BOI or ERROR
  796.  
  797. long cfkey(
  798.            void *handle,
  799.            void *keybufptr,
  800.            int keybuflen
  801.           )
  802. Returns OK, BOI, EOI or ERROR.
  803. If OK, fills the buffer denoted by 'keybufptr' with no more than
  804. 'keybuflen' bytes of the current key.
  805.  
  806. long cfitem(
  807.             void *handle,
  808.             Item *itemptr
  809.            )
  810. Get item from current position.
  811. Returns OK, BOI, EOI or ERROR.
  812.  
  813. long cfdata(
  814.            void *handle,
  815.            void *databufptr,
  816.            int databuflen
  817.           )
  818. Returns OK, BOI, EOI or ERROR if invalid handle or no data available.
  819. If OK, fills the buffer denoted by 'databufptr' with no more than
  820. 'databuflen' bytes of the current key's data area, if it exists.
  821.  
  822.  
  823. long cfkeylen(
  824.               void *handle,
  825.               int *len
  826.              )
  827. returns OK if a current key exists, len is set to the length of the key
  828. NOTE: Short hashed keys always return a length of 8, even if they
  829. were originally shorter.
  830.  
  831.  
  832. long cfdatalen(
  833.                void *handle,
  834.                int *len
  835.               )
  836. returns OK if a current key exists, len is set to data size or 0 if no data
  837.  
  838.  
  839. long cfmark(
  840.             void *handle
  841.            )
  842. Saves the current position. (see cffind_mark()).
  843. Returns OK or ERROR.
  844.  
  845.  
  846. INSERT ITEMS
  847.  
  848. int cfinsert(
  849.               void *handle,
  850.               void *keyptr,
  851.               int   keylen,
  852.               void *itemptr
  853.              )
  854. Returns OK or ERROR, duplicate entries are not allowed
  855.  
  856. int cfreinsert(
  857.               void *handle,
  858.               void *keyptr,
  859.               int   keylen,
  860.               void *itemptr
  861.              )
  862. Returns OK or ERROR, the key must exist, duplicate entries are not allowed.
  863. If the existing item references data, the data space is deleted.
  864.  
  865. int cfinsert_dupnum(
  866.                      void *handle,
  867.                      void *keyptr,
  868.                      int   keylen,
  869.                      void *itemptr,
  870.                      long *dupcnt    // returns the current dupcnt, 1 based
  871.                     )
  872. Returns OK or ERROR, 'normal' duplicates are allowed.
  873.  
  874. int cfreinsert_dupnum(
  875.                      void *handle,
  876.                      void *keyptr,
  877.                      int   keylen,
  878.                      void *itemptr,
  879.                      long *dupnum    // points to the desired dupnum, 0 based
  880.                     )
  881. Returns OK or ERROR, the key and dupnumn'th duplicate must exist.
  882. If the existing item references data, the data space is deleted.
  883.  
  884. NOTE: Items entered as normal duplicates do not remain in the order
  885.       in which they are entered, B+ trees sort the keys and items,
  886.       hashed directories get rearranged when split. Therefore, reinserting
  887.       to a specific dupnum is a chancy business and should be done only
  888.       when the programmer is certain of the algorithm.
  889.  
  890.  
  891. int cfinsert_dupname(
  892.                      void *handle,
  893.                      void *keyptr,
  894.                      int   keylen,
  895.                      void *itemptr,
  896.                      DupName *dupname  // returns current dupname
  897.                      )
  898. Returns OK or ERROR, the value referenced by 'dupname' is filled with the
  899. current DupName.
  900.  
  901. NOTE: DupNames are constantly incremented and provide a completely unique
  902. way to identify a key-item pair. Each DupName contains a 48 bit counter
  903. that is decremented only under special circumstances (see cfdelete_lastdupname).
  904. If a program inserted 1000 dupnames per second, it would take more than 8000 
  905. years to overflow the counter.
  906.  
  907.  
  908.  
  909.  
  910.  
  911. int cfreinsert_dupname(
  912.                      void *handle,
  913.                      void *keyptr,
  914.                      int   keylen,
  915.                      void *itemptr,
  916.                      DupName *dupname    // points to the desired DupName
  917.                      )
  918. If the existing item references data, the data space is deleted.
  919. Returns OK or ERROR, the key and dupname'th duplicate must exist.
  920.  
  921.  
  922. INSERT DATA
  923.  
  924. NOTE: 1. Data may not be inserted in objects with untagged items.
  925.       2. reput acts like realloc, if the entry doesn't exist it is created.
  926.          If dupnums or DupNames are used with reput, then the desired entry
  927.          must exist or the operation fails.
  928.  
  929. void *cfput(
  930.             void *handle,
  931.             void *keyptr,
  932.             int   keylen,
  933.             void *databuffer,
  934.             long  databuflen,
  935.             void *itemptr    // if non NULL then the Item is filled in
  936.            )
  937. Returns 'itemptr' if successful, NULL if not.
  938. The Item referenced by 'itemptr' describes a data chunk.
  939. If itemptr is NULL, then the non-NULL value returned on success is not
  940. a valid itemptr in its own right.
  941.  
  942.  
  943. void *cfreput(
  944.             void *handle,
  945.             void *keyptr,
  946.             int   keylen,
  947.             void *databuffer,
  948.             long  databuflen,
  949.             void *itemptr     // if non NULL then the Item is filled in
  950.            )
  951. Overwrites old data, if no old data, a new entry is created.
  952. Returns 'itemptr' if successful, NULL if not.
  953. The Item referenced by 'itemptr' describes a data chunk.
  954. If itemptr is NULL, then the non-NULL value returned on success is not
  955. a valid itemptr in its own right.
  956.  
  957.  
  958. void *cfput_dupnum(
  959.                    void *handle,
  960.                    void *keyptr,
  961.                    int   keylen,
  962.                    void *databuffer,
  963.                    long  databuflen,
  964.                    void *itemptr,
  965.                    long *dupcnt      // returns the current dupcnt, 1 based
  966.                   )
  967. Returns 'itemptr' if successful, NULL if not.
  968. The Item referenced by 'itemptr' describes a data chunk.
  969. If itemptr is NULL, then the non-NULL value returned on success is not
  970. a valid itemptr in its own right.
  971.  
  972.  
  973. void *cfreput_dupnum(
  974.                    void *handle,
  975.                    void *keyptr,
  976.                    int   keylen,
  977.                    void *databuffer,
  978.                    long  databuflen,
  979.                    void *itemptr,    // if non NULL then the Item is filled in
  980.                    long *dupnum      // references the desired dupnum, 0 based
  981.                   )
  982. Overwrites old data, if no old data, the operation fails.
  983. Returns 'itemptr' if successful, NULL if not.
  984. The Item referenced by 'itemptr' describes a data chunk.
  985. If itemptr is NULL, then the non-NULL value returned on success is not
  986. a valid itemptr in its own right.
  987.  
  988.  
  989. void *cfput_dupname(
  990.                    void *handle,
  991.                    void *keyptr,
  992.                    int   keylen,
  993.                    void *databuffer,
  994.                    long  databuflen,
  995.                    void *itemptr,    // if non NULL then the Item is filled in
  996.                    DupName *dupname  // returns the current DupName
  997.                   )
  998. Returns 'itemptr' if successful, NULL if not.
  999. The Item referenced by 'itemptr' describes a data chunk.
  1000. If itemptr is NULL, then the non-NULL value returned on success is not
  1001. a valid itemptr in its own right.
  1002.  
  1003.  
  1004. void *cfreput_dupname(
  1005.                    void *handle,
  1006.                    void *keyptr,
  1007.                    int   keylen,
  1008.                    void *databuffer,
  1009.                    long  databuflen,
  1010.                    void *itemptr,      // if non NULL the Item is filled in
  1011.                    DupName *dupname    // references the desired DupName
  1012.                   )
  1013. Overwrites old data, if no old data, the operation fails.
  1014. Returns 'itemptr' if successful, NULL if not.
  1015. The Item referenced by 'itemptr' describes a data chunk.
  1016. If itemptr is NULL, then the non-NULL value returned on success is not
  1017. a valid itemptr in its own right.
  1018.  
  1019.  
  1020. RETRIEVE DATA
  1021.  
  1022. long cfget(
  1023.            void *handle,
  1024.            void *keyptr,
  1025.            void  keylen,
  1026.            void *databufptr,
  1027.            long  databuflen
  1028.           )
  1029. Read the data for the first item of the key into the buffer for no 
  1030. more than 'databuflen' bytes;
  1031. Returns FOUND, FOUND+1 if dups present, NOTFOUND, or ERROR
  1032. if >= FOUND sets up for sequential access.
  1033.  
  1034. int cfqget(
  1035.            void *handle,
  1036.            void *keyptr,
  1037.            int   keylen,
  1038.            void *databufptr,
  1039.            int    databuflen
  1040.           )
  1041. Read the data or item value of the key. If item value, buflen == 8.
  1042. i.e. if data is stored you get it; if the data is really a value you get
  1043. the 60 bit value + 4 bits of tag in the high 4 bits.
  1044. OPTIMIZED FOR SPEED, only works for memory based hash dictionaries.
  1045. Returns FOUND, NOTFOUND, or ERROR
  1046.  
  1047.  
  1048. long cfget_dupnum(
  1049.                   void *handle,
  1050.                   void *keyptr,
  1051.                   int   keylen,
  1052.                   void *databufptr,
  1053.                   long  databuflen,
  1054.                   long *dupnum      // references the desired dupnum, 0 based
  1055.                  )
  1056. Read the data for the dupnum'th item of the key into the buffer for no 
  1057. more than 'databuflen' bytes;
  1058. Returns FOUND, FOUND+1, NOTFOUND or ERROR. 
  1059. If >= FOUND, sets up for sequential access.
  1060.  
  1061.  
  1062. long cfget_dupname(
  1063.                   void *handle,
  1064.                   DupName *dupname,  // points to the desired DupName
  1065.                   void *databufptr,
  1066.                   long  databuflen
  1067.                  )
  1068. Read the data for the dupname into the buffer for no 
  1069. more than 'databuflen' bytes;
  1070. Returns FOUND, NOTFOUND or ERROR.
  1071. If FOUND, sets up for sequential access.
  1072.  
  1073.  
  1074. FIND ITEMS
  1075.  
  1076. int cffind(
  1077.            void *handle,
  1078.            void *keyptr,
  1079.            int   keylen,
  1080.            void *itemptr   // if FOUND the item is returned
  1081.           )
  1082. Locates the first item of a key, and sets up for sequential access.
  1083. Returns FOUND, FOUND+1 if dups present, NOTFOUND, or ERROR
  1084.  
  1085. int cfqfind(
  1086.            void *handle,
  1087.            void *keyptr,
  1088.            int   keylen,
  1089.            Item *keyi;    // or NULL
  1090.            Item *dati;    // or NULL
  1091.           )
  1092. Returns pointers to the key and data, and FOUND, NOTFOUND or ERROR;
  1093. OPTIMIZED FOR SPEED, only works for memory based hash dictionaries.
  1094.  
  1095. int cfqfinddat(
  1096.            void *handle,
  1097.            void *keyptr,
  1098.            int   keylen,
  1099.            Item *dati;
  1100.           )
  1101. Returns pointer to the data, and FOUND, NOTFOUND or ERROR;
  1102. dati.a1 points to data
  1103. data.a2.size is data size;
  1104. OPTIMIZED FOR SPEED, only works for memory based hash dictionaries.
  1105.  
  1106. int cfqfindkey(
  1107.            void *handle,
  1108.            void *keyptr,
  1109.            int   keylen,
  1110.            Item *keyi;
  1111.           )
  1112. Returns pointer to the key, and FOUND, NOTFOUND or ERROR;
  1113. keyi.a1 points to the key;
  1114. OPTIMIZED FOR SPEED, only works for memory based hash dictionaries.
  1115.  
  1116. int cffind_dupnum(
  1117.                   void *handle,
  1118.                   void *keyptr,
  1119.                   int   keylen,
  1120.                   void *itemptr,    // if FOUND the item is returned
  1121.                   long *dupnum      // points to the desired dupnum, 0 based
  1122.                  )
  1123. Returns FOUND, NOTFOUND or ERROR. 
  1124. If ==  FOUND, sets up for sequential access.
  1125.  
  1126.  
  1127. int cffind_dupname(
  1128.                   void *handle,
  1129.                   DupName *dupname  // points to the desired dupname
  1130.                   void *itemptr,    // if FOUND the item is returned
  1131.                  )
  1132. Returns FOUND, NOTFOUND or ERROR. If FOUND, sets up for sequential access.
  1133.  
  1134.  
  1135. int cffind_item(
  1136.                 void *handle,
  1137.                 void *keyptr,
  1138.                 int   keylen,
  1139.                 void *itemptr
  1140.                )
  1141. Locates a key-item pair.
  1142. Returns FOUND, NOTFOUND or ERROR. If FOUND, sets up for sequential access.
  1143.  
  1144.  
  1145. int cffind_mark(
  1146.                 void *handle,
  1147.                 void *itemptr
  1148.                )
  1149. Returns the item for the current mark if the mark is valid (see cfmark()).
  1150. The mark can be invalidated if items are inserted or deleted after the
  1151. mark is set. This phenomenon happens more often with hashed directories
  1152. than with B+ trees.
  1153.  
  1154. Returns FOUND, NOTFOUND or ERROR. If FOUND, sets up for sequential access.
  1155.  
  1156.  
  1157.  
  1158. DELETE ITEMS
  1159.  
  1160. int cfdelete(
  1161.               void *handle,
  1162.               void *keyptr,
  1163.               int   keylen
  1164.              )
  1165. The first item of the key is deleted along with any data.
  1166. Returns OK or ERRORNUM a negative number.
  1167.  
  1168.  
  1169. int cfdelete_item(
  1170.                   void *handle,
  1171.                   void *keyptr,
  1172.                   int   keylen,
  1173.                   void *itemptr
  1174.                  )
  1175. If the key-item pair exists it is deleted along with any data.
  1176. Returns OK or ERRORNUM a negative number.
  1177.  
  1178.  
  1179. int cfdelete_dupnum(
  1180.                     void *handle,
  1181.                     void *keyptr,
  1182.                     int   keylen,
  1183.                     long  dupnum      // 0 based
  1184.                    )
  1185. If the dupnum'th item for the key exists it is deleted along with any data.
  1186. Returns OK or ERRORNUM a negative number
  1187.  
  1188.  
  1189. int cfdelete_dupname(
  1190.                      void *handle,
  1191.                      void *keyptr,
  1192.                      int   keylen,
  1193.                      DupName *dupname
  1194.                     )
  1195. If the dupname exists, it is deleted along with any data.
  1196. If the dupname is deleted, the 'holes' counter is incremented by one.
  1197. Each DupName set contains a 48 bit holes counter. (see cfcountdups()).
  1198. returns OK or ERRORNUM a negative number.
  1199.  
  1200.  
  1201. int cfdelete_lastdupname(
  1202.                          void *handle,
  1203.                          void *keyptr,
  1204.                          int   keylen
  1205.                         )
  1206. If the last DupName for the key exists, it is deleted along with any data.
  1207. The DupName counter is decremented by one.
  1208. Returns OK or ERRORNUM a negative number.
  1209.  
  1210.  
  1211. int cfdelete_lastdupnum(
  1212.                          void *handle,
  1213.                          void *keyptr,
  1214.                          int   keylen
  1215.                         )
  1216. If the last dupnum for the key exists, it is deleted along with any data.
  1217. WARNING: The last dupnum is probably not the last dup entered. B+ trees
  1218. sort all input and hashed directories are reorganized when split/coalesced.
  1219. Returns OK or ERRORNUM a negative number.
  1220.  
  1221.  
  1222. int cfdelete_alldupnames(
  1223.                          void *handle,
  1224.                          void *keyptr,
  1225.                          int   keylen
  1226.                         )
  1227. All 'DupName' entries for the key are deleted along with any data.
  1228. Returns OK or ERROR
  1229.  
  1230.  
  1231. int cfdelete_alldupnums(
  1232.                          void *handle,
  1233.                          void *keyptr,
  1234.                          int   keylen
  1235.                         )
  1236. All 'dupnum' entries for the key are deleted along with any data.
  1237. Returns OK or ERROR
  1238.  
  1239. DELETE OBJECTS 
  1240.  
  1241. int cfunlink(
  1242.               void *something, // path or object handle
  1243.               ...              // optional 2'nd arg if arg 1 is a handle
  1244.             )
  1245.  
  1246. Deletes the object denoted by 'something' and an optional second argument.
  1247. If 'something' is a path, then the target of the path is deleted.
  1248. if 'something' is a handle, then if the second argument is NULL
  1249. the object denoted by the handle is deleted. A non-NULL second argument
  1250. must be a character string which names an entry in the object's index.
  1251. The second argument must not refer to a sub_object.
  1252.  
  1253. Returns OK or ERROR if multiply opened or sub_objects open or not found.
  1254.  
  1255. NOTE: When an object is unlinked all of it's sub-objects are unlinked
  1256. and all data is returned to parent bitmaps. External files can be unlinked.
  1257.  
  1258.  
  1259. STACK OPERATIONS
  1260.  
  1261. long cfpush_value(
  1262.                  void *handle,    // an open object
  1263.                  unsigned long *valptr
  1264.                 )
  1265. Push an unsigned long integer on the objects stack.
  1266. Returns current stack depth or ERROR.
  1267.  
  1268. long cfpush_item(
  1269.                  void *handle,    // an open object
  1270.                  void *itemptr
  1271.                 )
  1272. Push the item on the objects stack.
  1273. Returns current stack depth or ERROR.
  1274.  
  1275. long cfpush_data(
  1276.                  void *handle,  // an open object
  1277.                  void *datbufptr,
  1278.                  int   datbuflen
  1279.                 )
  1280. Pushes data onto the objects stack (max 16MB). 
  1281. Returns current stack depth or ERROR.
  1282.  
  1283.  
  1284. long cfpop_value(
  1285.                 void *handle,  // an open object
  1286.                 unsigned long *valptr
  1287.                )
  1288. Pops an unsigned long integer from the top of the objects stack.
  1289.  
  1290. long cfpop_item(
  1291.                 void *handle,  // an open object
  1292.                 void *itemptr
  1293.                )
  1294. Pops an item from the top of the objects stack.
  1295. IF THE ITEM DESCRIBES DATA, THE DATA HAS NOT BEEN DELETED (use cfretspace()).
  1296. I have chosen this dangerous method of dealing with the stack because
  1297. it can be very useful. i.e. One part of a program can push a lot of data
  1298. without regard for where it is going or assigning a key to it, another
  1299. part of a program can pop the items which describe the data and save the
  1300. items for later keyed retrieval, the data moves once. This method is doubly
  1301. dangerous: First, the programmer must ensure that the data can eventually
  1302. be deleted and Second, if a hashed object contains PREALLOCATED ENTRIES
  1303. then the data should NEVER be deleted because the preallocation mechanism
  1304. will want to reuse the space, and indeed will overwrite the data at some
  1305. time in the future.
  1306. Returns current stack depth or ERROR.
  1307.  
  1308.  
  1309. long cfpop_data(
  1310.                 void *handle,  // an open object
  1311.                 void *datbufptr,
  1312.                 int   datbuflen
  1313.                )
  1314. Pops data (if it exists) from the top of the stack.
  1315. If the top of the stack contains an item that does not describe data
  1316. the item is lost.
  1317. Returns current stack depth or ERROR.
  1318.  
  1319.  
  1320. long cfstackdepth(
  1321.                   void *handle  // an open object
  1322.                  )
  1323. Returns current stack depth or ERROR.
  1324.  
  1325.  
  1326.  
  1327. SPACE ALLOCATION
  1328.  
  1329. void *cfgetspace(
  1330.                   void *handle,  // an open object
  1331.                   long  amount,  // max 16MB
  1332.                   void *itemptr     // receives an Item which describes the space
  1333.                 )
  1334. Returns 'itemptr' if success or NULL.
  1335.  
  1336.  
  1337. int cfretspace(
  1338.                 void *handle,  // an open object
  1339.                 void *itemptr  // pointer to an Item which describes space
  1340.               )
  1341. Returns OK or ERROR
  1342. CFF Version 5.4 will abort if the Item does not describe valid space.
  1343. I think that this is better than returning an error.
  1344.  
  1345.  
  1346.     MEMORY FUNCTIONS
  1347.     void *malloc(size_t)
  1348.     void *calloc(unsigned, unsigned)
  1349.     void *realloc(void *, unsigned)
  1350.     void *valloc(unsigned)
  1351.     void *memalign(unsigned, unsigned)
  1352.     void free(void *)
  1353.     unsigned mallocsize(void *)
  1354.     void *cfmalloc(unsigned, Item *)
  1355.     void cffree(Item *)
  1356.  
  1357.     MEMORY BY CATEGORY FUNCTIONS
  1358.     void *mallocC(long, unsigned)
  1359.     void *callocC(long, unsigned, unsigned)
  1360.     void *reallocC(long, unsigned, unsigned)
  1361.     void *vallocC(long, unsigned)
  1362.     void *memalignC(long, unsigned, unsigned)
  1363.     void freeC(long, void *)
  1364.     void freecat(long)
  1365.  
  1366. CONTROL FUNCTIONS
  1367.  
  1368. long cfmodbufs(
  1369.                 long increment   // positive or negative increment in K bytes
  1370.               )
  1371. Changes the allowed buffering space by 'increment'.
  1372. Returns OK
  1373.  
  1374. long cfsetlazy(
  1375.                void *handle        // an open object
  1376.               )
  1377. Changes the writethrough characteristic of the object to LAZY.
  1378. Some bookeeping entries are forced out.
  1379. Returns OK or ERROR
  1380.  
  1381. long cfsetverylazy(
  1382.                    void *handle  // an open object
  1383.                   )
  1384. Changes the writethrough characteristic of the object to VERYLAZY.
  1385. No data is forced out.
  1386. Returns OK or ERROR
  1387.  
  1388. long cfclrlazy(
  1389.                void *handle   // an open object
  1390.               )
  1391. Sets the writethrough characteristic of the object to NORMAL.
  1392. Forces out everything.
  1393. Returns OK or ERROR
  1394.  
  1395. long cfsetkeycmp(
  1396.                  void *handle,                          // open object
  1397.                  int (*func)(void *, int, void *, int)  // function pointer
  1398.                 )
  1399. Changes the default key comparison routine for an object to a programmer
  1400. supplied version.
  1401. Returns OK or ERROR
  1402.  
  1403. long cfsetitemcmp(
  1404.                  void *handle,                // open object
  1405.                  int (*func)(void *, void *)  // function pointer
  1406.                 )
  1407. Changes the default item comparison routine for an object to a programmer
  1408. supplied version.
  1409. Returns OK or ERROR
  1410.  
  1411. long cfsetprintfunc(
  1412.                  int (*func)(int)  // function pointer
  1413.                 )
  1414. Changes the default system print function to a programmer supplied version.
  1415. The function must print one character at a time,
  1416. and return 1 for success, -1 for error.
  1417. Returns OK
  1418.  
  1419. void cfport_settestflags(
  1420.                          int flags
  1421.                         )
  1422. Set flags in the portability module 'cfport.c'. This command is issued
  1423. before cfinit(). The only defined flag is 1, which causes the extended
  1424. memory driver to enable a 4Meg local buffer for testing purposes.
  1425. If the 1 flag is not set, the system will map extended memory to
  1426. primary memory unless the programmer has included a 'real' extended
  1427. memory driver in cfport.c
  1428.  
  1429.  
  1430. COPY OBJECTS, FILESYSTEMS and FILES
  1431.  
  1432. void *cfcopy(
  1433.              void *something_dst,  // designates the destination
  1434.              void *something_src   // designates the source
  1435.             )
  1436.  
  1437. Copy the source to the destination.
  1438. The arguments can be paths or handles.
  1439. The source may be an object, a filesystem or an external file.
  1440. Ditto for the destination.
  1441. Sorted objects (created with F_SORTED) may not be copied to a filesystem.
  1442. If the source or destination is an external file, then the file property
  1443. of the object is copied.
  1444.  
  1445. Returns a handle to the OPENED destination or NULL.
  1446. NOTE: If the destination argument was an open handle, then the returned
  1447. handle SUPERCEEDS the original. i.e. the open object was deleted and
  1448. recreated.
  1449.  
  1450.  
  1451. DIRECT ACCESS TO DATA IN THE BUFFERS
  1452.  
  1453. void *cflocalize(
  1454.                  void *handle,   // an open object
  1455.                  void *item      // pointer to an Item which describes space
  1456.                 )
  1457. Returns a pointer to memory or NULL.
  1458. This command ties up one buffer header.
  1459. Be certain to release the buffer when finished.
  1460. The buffers are in the heap and thus are not memory protected.
  1461.  
  1462.  
  1463. void cfrelease(
  1464.                void *memptr,  // a pointer to memory returned by cflocalize()
  1465.                long  relmode  // R_CLEAN, R_DIRTY, R_FLUSH
  1466.               )
  1467. Release a buffer. 
  1468. If the release mode is R_CLEAN, then the buffer may never be written out.
  1469. If the release mode is R_DIRTY, then the buffer will eventually be written out.
  1470. If the release mode is R_FLUSH, then the buffer is written out immediately if
  1471. the object writethrough condition is not VERYLAZY. If the object may be in
  1472. VERYLAZY mode, be sure to use (R_DIRTY|R_FLUSH).
  1473.  
  1474.  
  1475. NAME TRANSLATION FUNCTIONS
  1476.  
  1477. int cfdef(
  1478.           char *keyptr,  // the key for the definition string
  1479.           char *defptr  // the definition string, entered in local dictionary
  1480.          )
  1481. Enters the definition string in the local dictionary, under the key.
  1482. Local definitions override application and system definitions.
  1483. Returns OK or ERROR
  1484.  
  1485.  
  1486. int cfundef(
  1487.             char *keyptr   // the key to a definition string
  1488.            )
  1489. Deletes a definition string from the local dictionary.
  1490. returns OK or ERROR
  1491.  
  1492.  
  1493. int cfsysdef(
  1494.               char *keyptr,  // the key for the definition string
  1495.               char *defptr  // the definition string, entered in PERMFILE
  1496.              )
  1497. Enters the definition string in the permanent system dictionary (if it exists).
  1498. PERMFILE is enabled if arg 3 of cfinit() mentions a valid '.cff' file.
  1499. Returns OK or ERROR
  1500.  
  1501.  
  1502. int cfsysundef(
  1503.                char *keyptr  // the key to a defined string
  1504.                )
  1505. Deletes a definition string from the permanent system dictionary.
  1506. Returns OK or ERROR
  1507.  
  1508. int cfappdef(
  1509.               char *keyptr,  // the key for the definition string
  1510.               char *defptr  // the definition string, entered in PERMINFO
  1511.              )
  1512. Enters the definition string in the permanent application dictionary.
  1513. Application definitions override system definitions.
  1514. PERMINFO is enabled if arg 3 of cfinit() mentions a valid '.cff' file.
  1515. Returns OK or ERROR
  1516.  
  1517.  
  1518. int cfappundef(
  1519.                char *keyptr  // the key to a defined string
  1520.                )
  1521. Deletes a definition string from the permanent application dictionary.
  1522. Returns OK or ERROR
  1523.  
  1524.  
  1525. int cftrn(
  1526.           char *input_string,
  1527.           char **output_string
  1528.          )
  1529. Translates the input string to the output string using the dictionaries.
  1530. The programmer must free the output string.
  1531. Returns OK or ERROR
  1532.  
  1533.  
  1534. int cfpathtrn(
  1535.               char *input_string,
  1536.               char **output_string
  1537.              )
  1538. Translates the input string to a fully qualified path, using the dictionaries
  1539. and the current working directory.
  1540. The programmer must free the output string.
  1541. Returns 0 if internal object, 1 if external file, 2 if filesys, 3 if rawdevice
  1542. Returns ERROR if trouble.
  1543.  
  1544.  
  1545. int cfchdir(
  1546.             char *newpath
  1547.            )
  1548. Change the current working directory.
  1549. Returns OK or ERROR
  1550.  
  1551.  
  1552. NOTE: to get the current working directory:
  1553. {
  1554. char *cwd;
  1555.     cfpathtrn(".", &cwd);
  1556.     
  1557.     ...
  1558.     
  1559.    free(cwd);
  1560. }
  1561. NOTE: CFF does not include disk drive prefixes in the cwd, the programmer
  1562.       may include them when opening a file or filesystem.
  1563.  
  1564. NOTE: The translator works mostly on the left hand side of a path;
  1565.       it first tries to translate the whole input string, then it expands
  1566.       the left hand side up to 10 times, then it tries to translate the
  1567.       whole result string. Would a macro facility be helpful?
  1568.  
  1569.  
  1570. STREAM I/O
  1571.  
  1572.       The standard flavors of opening stream files are supported.
  1573.       There are several new modes for opening and reopening files.
  1574.  
  1575.         Mode    Meaning
  1576.         "x"     Open a string, (put the string in place of the filename)
  1577.         "U"     Create a unique file, (supply a directory path as the filename)
  1578.         "T"     Open a temporary file, deleted on close.
  1579.         "M"     Open a file in memory.
  1580.         "s"        Open a file in 'stat' mode, i.e. parents are also readonly.
  1581.         "t"        Open file in 'text' mode, default is binary.
  1582.         "b"        Open file in binary mode, default (to be msdos compatible).
  1583.  
  1584.     As with cfopen, the stream handlers can open chunks and values for reading.
  1585.  
  1586. /* STDIO STUFF */
  1587. #define __BUFSIZ_  512
  1588.  
  1589. extern  struct  cf_iobuf {
  1590.     int      _cnt;
  1591.     char*    _ptr;
  1592.     char*    _base;
  1593.     int      _bufsiz;
  1594.     int      _flag;
  1595.     void *   _file;    // cff handle
  1596.     char     _sbuf;
  1597. } cf_iob[];
  1598.  
  1599. typedef struct cf_iobuf cfFILE;
  1600.  
  1601. #define cf_IOFBF    00000
  1602. #define cf_IOREAD   00001
  1603. #define cf_IOWRT    00002
  1604. #define cf_IONBF    00004
  1605. #define cf_IOMYBUF  00010
  1606. #define cf_IOEOF    00020
  1607. #define cf_IOERR    00040
  1608. #define cf_IOSTRG   00100
  1609. #define cf_IOLBF    00200
  1610. #define cf_IORW     00400
  1611. #define cf_IOAPPEND 01000
  1612. #define cf_IOTEXT   02000  /* for MSDOS cr/lf style files */
  1613.  
  1614. #define cfstdin     (&cf_iob[0])
  1615. #define cfstdout    (&cf_iob[1])
  1616. #define cfstderr    (&cf_iob[2])
  1617. #define cfstdaux    (&cf_iob[3])
  1618. #define cfstdprn    (&cf_iob[4])
  1619.  
  1620. #define cfgetc(p) (--(p)->_cnt>=0 ? \
  1621. (int)(*(unsigned char*)(p)->_ptr++) : \
  1622. cf_filbuf(p))
  1623. #define cfputc(x,p) (--(p)->_cnt>=0? \
  1624. ((int)((unsigned char)((*(p)->_ptr++=(unsigned)(x))))): \
  1625. cf_flsbuf((unsigned)(x),p))
  1626.  
  1627. #define cfclearerr(p) ((p)->_flag &= ~(cf_IOERR|cf_IOEOF))
  1628. #define cfgetchar()   cfgetc(cfstdin)
  1629. #define cfputchar(x)  cfputc(x,cfstdout)
  1630. #define cffeof(p)     (((p)->_flag&cf_IOEOF)!=0)
  1631. #define cfferror(p)   (((p)->_flag&cf_IOERR)!=0)
  1632. #define cffileno(p)   (cf_filelist[(p)->_file])
  1633.  
  1634. cfFILE*  cffopen(char *something, char *mode);
  1635. cfFILE*  cffreopen(char *something, char *mode, cfFILE *iop);
  1636. cfFILE*  cffdopen(void *handle, char *mode);
  1637. int      cf_filbuf(cfFILE*);
  1638. int      cf_flsbuf(unsigned, cfFILE*);
  1639. int      cffclose(cfFILE*);
  1640. int      cffflush(cfFILE*);
  1641. int      cffgetc(cfFILE*);
  1642. char*    cffgets(char*, int, cfFILE *);
  1643. int      cffputc(int, cfFILE*);
  1644. int      cffputs(char*, cfFILE*);
  1645. int      cffread(void*, int, int, cfFILE*);
  1646. int      cffseek(cfFILE*, long, int);
  1647. long     cfftell(cfFILE *);
  1648. int      cfsetpos(cfFILE *, long *);
  1649. int      cfgetpos(cfFILE *, long *);
  1650. cfFILE   *cftmpfile(void);
  1651. char     *cftmpnam(char *buf);
  1652. char     *cftempnam(char *dir, char *pref);
  1653. int      cffwrite(void*, int, int, cfFILE*);
  1654. char*    cfgets(char*);
  1655. int      cfgetw(cfFILE*);
  1656. int      cfputs(char*);
  1657. int      cfputw(int, cfFILE*);
  1658. void     cfrewind(cfFILE*);
  1659. int      cfsetbuf(cfFILE*, char*);
  1660. int      cfsetbuffer(cfFILE*, char*, int);
  1661. int      cfsetlinebuf(cfFILE*);
  1662. int      cfsetvbuf(cfFILE*, char*, int, int);
  1663. int      cfungetc(int, cfFILE*);
  1664.  
  1665. int      cfprintf(const char *fmt, ...);
  1666. int      cffprintf(cfFILE *iop, const char *fmt, ...);
  1667. int      cfsprintf(char *str, const char *fmt, ...);
  1668. int      cfvprintf(void *fmt, ...);
  1669. int      cfvfprintf(cfFILE *iop, const char *fmt, ...);
  1670. int      cfvsprintf(char *str, const char *fmt, ...);
  1671.  
  1672. int cfsscanf(char *str, const char *fmt, ...);
  1673. int cffscanf(cfFILE *iop, const char *fmt, ...);
  1674. int cfscanf(const char *fmt, ...);
  1675.  
  1676.  
  1677. DATA COMPRESSION
  1678.  
  1679. int cfzip(
  1680.           void *something_dst, // path, handle or memory address
  1681.           int dstsize,  // if non zero the size of destination MEMORY buf
  1682.           void *something_src, // path, handle or memory address
  1683.           int srcsize,  // if non zero the size of the source MEMORY buf
  1684.           int level     // compression level 1-9 (0=default,1=fast,15=best compression)
  1685.           )
  1686. Returns compressed size or ERROR.
  1687.  
  1688. NOTE: If nonzero, srcsize and dstsize imply that a memory address is in
  1689.       the something_dst or something_src arg.
  1690.  
  1691.  
  1692. int cfunzip(
  1693.           void *something_dst, // path, handle or memory address
  1694.           int dstsize,  // if non zero the size of destination MEMORY buf
  1695.           void *something_src, // path, handle or memory address
  1696.           int srcsize  // if non zero the size of the source MEMORY buf
  1697.           )
  1698. Returns uncompressed size or ERROR.
  1699.  
  1700. NOTE: If nonzero, srcsize and dstsize imply that a memory address is in
  1701.       the something_dst or something_src arg.
  1702.  
  1703.  
  1704. INFORMATIONAL FUNCTIONS
  1705.  
  1706. int cflastdupname(
  1707.                   void *handle,
  1708.                   void *keyptr,
  1709.                   int   keylen,
  1710.                   DupName *dupname  // filled if successful
  1711.                  )
  1712. If DupNames exist for the key, 'dupname' is filled with the last one.
  1713. Returns OK or ERROR
  1714.  
  1715. long cfcountdups(
  1716.                  void *handle,
  1717.                  void *keyptr,
  1718.                  int   keylen
  1719.                 )
  1720. Returns the actual duplicate count for a key. If DupNames are being used
  1721. then the actual count is the last DupName minus the number of prior deletions.
  1722. Each DupName key has a deletion counter which is incremented for every
  1723. successful delete except cfdelete_lastdupname().
  1724. Normal duplicates are just overtly scanned and counted.
  1725.  
  1726. int cfstat(
  1727.            void *something, // a handle or a path
  1728.            void *stbuf      // pointer to a CFSTAT struct
  1729.           )
  1730. returns OK or ERROR
  1731.  
  1732. int cfsubstat(
  1733.             void *handle,    // only a handle
  1734.             char *name,        // name of element, a chunk or node
  1735.             void *stbuf        // pointer to a CFSTAT struct
  1736.             )
  1737. returns OK or ERROR
  1738. If element is a chunk then OB_CHUNK and M_CHUNK are set and
  1739. st_filesize = st_filealloc = size of the chunk. The rest of the stat
  1740. info refers to the parent of the element.
  1741.  
  1742. typedef struct cffstat {
  1743.         unsigned long   st_smhead;
  1744.         unsigned long   st_smtail;
  1745.         unsigned short  st_id;
  1746.         unsigned short  st_keysize;
  1747.  
  1748.         STOR           st_dups;
  1749.         unsigned long  st_bmhead;
  1750.         unsigned long  st_bmtail;
  1751.         unsigned long  st_mode;
  1752.         short          st_uid;
  1753.         short          st_gid;
  1754.         long           st_mtime;
  1755.         long           st_ctime;
  1756.  
  1757.         unsigned long  st_highleaf;
  1758.         unsigned long  st_size;
  1759.         unsigned long  st_alloc;
  1760.         unsigned long  st_entrycnt;
  1761.         short          st_mapsize;
  1762.         unsigned short st_dupids;
  1763.  
  1764.         long           st_atime;
  1765.         long           st_filesize;
  1766.         long           st_filealloc;
  1767.         long           st_obtype;
  1768.         unsigned int   st_filedups;
  1769.         long           st_ino;
  1770.         short          st_blksize;
  1771.         short          st_dev;
  1772.         short          st_nlink;
  1773.         short          st_rdev;
  1774. } CFSTAT;
  1775.  
  1776.  
  1777.  
  1778.  
  1779.  
  1780. /* MODE BITS in st_mode */
  1781. #define M_ROOTDIR   0x80000000
  1782. #define M_FILEONLY  0x40000000
  1783. #define M_HASHDIR   0x20000000
  1784. #define M_TREEDIR   0x10000000
  1785. #define M_UNTAGGED  0x08000000
  1786. #define M_BITMAP    0x04000000
  1787. #define M_EXTRNFILE 0x02000000
  1788. #define M_PREALLOC  0x01000000
  1789. #define M_ZIPFILE    0x00800000
  1790. #define M_ZIPDATA    0x00400000
  1791. #define M_CHUNK        0x00200000
  1792. #define M_IFMT      0x000F0000
  1793. #define M_IFDIR     0x00004000
  1794. #define M_IFIFO     0x00002000
  1795. #define M_IFCHR     0x00001000
  1796. #define M_IFBLK     0x00003000
  1797. #define M_IFREG     0x00008000
  1798. #define M_IREAD     0x00000100
  1799. #define M_IWRITE    0x00000080
  1800. #define M_IEXEC     0x00000040
  1801.  
  1802.  
  1803. long cfentrycnt(
  1804.                 void *something
  1805.                )
  1806. returns the entrycount of a handle or a path, or ERROR
  1807.  
  1808.  
  1809. long cfdepth(
  1810.              void *handle
  1811.             )
  1812. returns treedepth or ERROR
  1813.  
  1814.  
  1815. long cfbytesused(
  1816.                  void *handle
  1817.                 )
  1818. returns the bytes used in the object or ERROR
  1819.  
  1820.  
  1821. long cfbytesalloc(
  1822.                   void *handle
  1823.                  )
  1824. returns the bytes allocated to the object or ERROR
  1825.  
  1826.  
  1827. long cftotalloc(
  1828.                 void *something,
  1829.                 unsigned long *used,
  1830.                 unsigned long *alloc
  1831.                )
  1832. returns OK if something exists, sets used and alloc to the total space
  1833. allocated to the object and all of it's subobjects in 1000's of bytes.
  1834.  
  1835.  
  1836. long cfstackdepth(
  1837.                   void *handle
  1838.                  )
  1839. returns the current stackdepth of the object or ERROR
  1840.  
  1841.  
  1842. long cfcurbufs(
  1843.                void
  1844.               )
  1845. returns the current allowed localizer buffer space in K bytes.
  1846.  
  1847.  
  1848. long cfisnew(
  1849.              void *handle
  1850.             )
  1851. returns 1 if object is newly created, 0 if not, ERROR if invalid handle
  1852.  
  1853.  
  1854. long cffilesize(
  1855.                 void *handle
  1856.                )
  1857. returns the size of the file property of the object or ERROR
  1858.  
  1859.  
  1860. long cffilealloc(
  1861.                  void *handle
  1862.                 )
  1863. returns the space allocated to the file property or ERROR
  1864.  
  1865.  
  1866. long cfprealloc(
  1867.                 void *handle
  1868.                )
  1869. returns the size of each preallocated chunk or 0 or ERROR
  1870.  
  1871.  
  1872. long cfmapsize(
  1873.                void *handle
  1874.               )
  1875. returns the node size of the object or ERROR
  1876.  
  1877.  
  1878. long cfalignment(
  1879.                  void *handle
  1880.                 )
  1881. returns the alignment for the object (32 is hardwired in version 5.4)
  1882.  
  1883.  
  1884. long cfissorted(
  1885.                 void *handle
  1886.                )
  1887. returns 1 if the object is sorted, 0 if not or ERROR
  1888.  
  1889.  
  1890. void cfprintbitmaps(
  1891.                     void *something  // a path or handle
  1892.                    )
  1893. Prints the bitmaps for the target object and it's parents.
  1894.  
  1895.  
  1896. void cfprintentries(
  1897.                     void *something  // a path or handle
  1898.                    )
  1899. Prints all the entries in the target object's nodes.
  1900.  
  1901. long cfhash(
  1902.             void *keyptr,
  1903.             int   keylen,
  1904.             CAT  *cat    // pointer to a CAT structure
  1905.            )
  1906. Calls the system hash function for the supplied key. The CAT structure
  1907. receives the hashed output. Useful for generating random numbers etc.
  1908. Returns OK.
  1909.    
  1910.  
  1911. void cfmemrange(
  1912.                 long category,
  1913.                 unsigned long *min,
  1914.                 unsigned long *max
  1915.                 )
  1916. Fills in min and max for the category, 0 for unallocated categories.
  1917.  
  1918. void cftotrange(
  1919.                 unsigned long *min,
  1920.                 unsigned long *max
  1921.                 )
  1922. Fills in min and max for all memory allocated.
  1923.  
  1924. long cfobtype(
  1925.               void *something
  1926.              )
  1927. returns the OB bits or ERROR
  1928.  
  1929. #define OB_SHARE    0x00000001  // object can be opened more than once
  1930. #define OB_ISDIR    0x00000002  // object is a directory
  1931. #define OB_BMOK     0x00000004  // bitmaps loaded
  1932. #define OB_SMOK     0x00000008  // storage maps loaded
  1933. #define OB_MEM      0x00000010  // memory object
  1934. #define OB_RAWDEV   0x00000020  // raw device
  1935. #define OB_CFILE    0x00000040  // part of a disk filesys
  1936. #define OB_SETUP    0x00000080  // object is setup
  1937. #define OB_FOD      0x00000100  // on a file oriented device
  1938. #define OB_ROOTDIR  0x00000200  // object is the root directory
  1939. #define OB_DIRTY    0x00000400  // has been written to
  1940. #define OB_DELCLOSE 0x00000800  // delete on close
  1941. #define OB_WRITE    0x00001000  // ok to write to this object
  1942. #define OB_BITMAP   0x00002000  // has a bitmap
  1943. #define OB_XFILE    0x00004000  // is an external OS file
  1944. #define OB_ISNEW    0x00008000  // newly created
  1945. #define OB_SMEM     0x00010000  // extended memory object
  1946. #define OB_FILEONLY 0x40000000  // created with F_FILEONLY
  1947. #define OB_HASHDIR  0x20000000  // uses hashed maps
  1948. #define OB_TREEDIR  0x10000000  // uses B+ tree maps
  1949. #define OB_UNTAGGED 0x08000000  // contains untagged items
  1950. #define OB_PREALLOC 0x01000000  // contains prealloced data and entries
  1951. #define OB_ZIPFILE    0x00800000    // file aspect is compressed
  1952. #define OB_ZIPDATA    0x00400000  // data chunks are compressed
  1953. #define OB_CHUNK    0x00200000    // object is a data chunk or value
  1954.  
  1955.  
  1956.  
  1957.