home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / disk / Devs+Handler / PFS75 / ProgrammersInfo < prev    next >
Text File  |  1994-05-15  |  13KB  |  430 lines

  1. /**********************************************************************/
  2. /* This file contains the datastructures used by PFS                  */
  3. /* Most structures that are not directly written to disk are apt      */
  4. /* to change.                                                         */
  5. /**********************************************************************/
  6.  
  7. // max lengte van filename, diskname en comment
  8. #define FNSIZE 108
  9. #define DNSIZE 32
  10. #define CMSIZE 80
  11.  
  12. #define ID_PFS_DISK        (0x50465300L)    //'PFS\0'
  13.  
  14. typedef unsigned char *DSTR;    // lengte, dan karakters
  15.  
  16. // IsDir(x) en IsFile(x) Argument: union objectinfo
  17. #define IsDir(oi) ((oi).file.direntry && ((oi).file.direntry->type)>0)
  18. #define IsFile(oi) ((oi).file.direntry && ((oi).file.direntry->type)<=0)
  19. #define IsVolume(oi) ((oi).volume.root==0)
  20. #define IsSameOI(oi1, oi2) ((oi1.file.direntry == oi2.file.direntry) && \
  21.     (oi1.file.dirblock == oi2.file.dirblock))
  22.  
  23. // IsRoot(fi) checked of *oi bij de rootdir hoort
  24. // IsRootA(fi) checked of oi bij de rootdir hoort
  25. #define IsRoot(oi) (((oi)==NULL) || ((oi)->volume.root == NULL))
  26. #define IsRootA(oi) ((oi).volume.root == NULL)
  27.  
  28. // *lock -> *fileentry
  29. #define LOCKTOFILEENTRY(l) ((struct fileentry *)(((UBYTE*)l)-4))
  30.  
  31. /**********************************************************************/
  32. /*                        File administration                         */
  33. /**********************************************************************/
  34.  
  35. /* FileInfo
  36. **
  37. ** This are internal representations of files. A volumeinfo is recognized
  38. ** by a zero root field.
  39. **
  40. ** The fileinfo->direntry en fileinfo->dirblock directly point into a
  41. ** cached directory block. That block is guaranteed to be present.
  42. ** If a pointer to a objectinfo is NULL, the root of the current
  43. ** volume is meant.
  44. */
  45. struct fileinfo
  46. {
  47.     struct direntry *direntry;
  48.     struct cdirblock *dirblock;
  49. };
  50.  
  51. struct volumeinfo
  52. {
  53.     ULONG    root;                   // always 0
  54.     struct volumedata *volume;
  55. };
  56.  
  57. union objectinfo
  58. {
  59.     struct fileinfo file;           // 0 =>it's a volumeinfo; <>0 => it's a fileinfo
  60.     struct volumeinfo volume;
  61. };
  62.  
  63. /**********************************************************************/
  64. /*                    Fileentries/locks & volumes                     */
  65. /**********************************************************************
  66. **
  67. ** Three structures with the same basis, but different length. The are
  68. ** all coupled with 'next'.
  69. ** lock->fl_Key is the directoryblocknr
  70. */
  71.  
  72. /* entrytype's
  73. ** PS: ETF_VOLUME and ETF_LOCK are both LOCKS! TEST ON BOTH
  74. */
  75. #define ET_VOLUME            0x0004
  76. #define ET_FILEENTRY        0x0008
  77. #define ET_LOCK                0x000c
  78. #define ETF_VOLUME            1
  79. #define ETF_FILEENTRY        2
  80. #define ETF_LOCK            3
  81. #define ET_SHAREDREAD        0
  82. #define ET_SHAREDWRITE        1
  83. #define ET_EXCLREAD            2
  84. #define ET_EXCLWRITE        3
  85.  
  86. #define IsVolumeEntry(e)    ((e)->type.flags.type == ETF_VOLUME)
  87. #define IsFileEntry(e)        ((e)->type.flags.type == ETF_FILEENTRY)
  88. #define IsLockEntry(e)        ((e)->type.flags.type == ETF_LOCK)
  89.  
  90. #define IsVolumeLock(le)    ((le)->type.flags.type == ETF_VOLUME)
  91.  
  92. #define SHAREDLOCK(t) ((t).flags.access <= 1)
  93.  
  94. // ANODENR for fe's and le's; FIANODENR for fileinfo's; NOT FOR VOLUMES!!
  95. #define ANODENR(fe) ((fe)->info.file.direntry->anode)
  96. #define FIANODENR(fi) ((fi)->direntry->anode)
  97.  
  98. union listtype
  99. {
  100.     struct
  101.     {
  102.         unsigned pad:11;
  103.         unsigned dir:1;        // 0 = file; 1 = dir or volume
  104.         unsigned type:2;    // 0 = unknown; 3 = lock; 1 = volume; 2 = fileentry
  105.         unsigned access:2;    // 0 = read shared; 2 = read excl; 1,3 = write shared, excl
  106.     } flags;
  107.  
  108.     UWORD value;
  109. };
  110.  
  111. typedef union listtype listtype;
  112.  
  113. /* Listentry
  114. **
  115. **- All locks on a volume are coupled from volume->firstfe by 'next'.
  116. **  The end of the chain is 0.
  117. **- [volume] points back to the volume
  118. **- [info] is {NULL, don't care} if root.
  119. */
  120.  
  121. /* the general structure */
  122. struct listentry
  123. {
  124.     struct listentry    *next;    // the link
  125.     struct FileLock        lock;    // contains accesstype, dirblocknr
  126.     listtype            type;
  127.     union objectinfo    info;    // directory reference
  128.     struct volumedata    *volume;    // the volume the lock is on
  129. };
  130.  
  131. /* the specific structures */
  132. struct fileentry
  133. {
  134.     struct fileentry    *next;
  135.     struct FileLock        lock;
  136.     listtype            type;
  137.     union objectinfo    info;
  138.     struct volumedata    *volume;
  139.  
  140.     UWORD    currentanode;        // anodenr belonging to offset in file
  141.     UWORD    anodeoffset;        // blocknr within current anode
  142.     UWORD    blockoffset;        // byteoffset within current block
  143.     ULONG    offset;                // offset from start of file
  144. };
  145.  
  146. struct lockentry
  147. {
  148.     struct lockentry    *next;
  149.     struct FileLock        lock;
  150.     listtype            type;
  151.     union objectinfo    info;
  152.     struct volumedata    *volume;
  153.  
  154.     UWORD                nextanode;    // used for examinenext
  155.     struct fileinfo        nextentry;    // and examineall
  156. };
  157.  
  158.  
  159. /* Converts DOS BCPL Lock pointer (returned by Lock()) to a lockentry
  160. ** pointer
  161. */
  162. #define LockEntryFromLock(x) ((x) ? \
  163.  (struct lockentry*)((UBYTE*)BADDR(x)-offsetof(struct lockentry, lock)) : 0)
  164.  
  165. #define ListEntryFromLock(x) ((x) ? \
  166.  (struct listentry*)((UBYTE*)BADDR(x)-offsetof(struct lockentry, lock)) : 0)
  167.  
  168.  
  169. /**********************************************************************/
  170. /*                        Disk administration                         */
  171. /**********************************************************************/
  172.  
  173. struct volumedata
  174. {
  175.     struct volumedata    *next;        // volumechain
  176.     struct DeviceList    *devlist;
  177.     struct rootblock    *rootblk;
  178.  
  179.     struct listentry    *firstfe;        // the fileentrylist
  180.     struct canodeblock    *firstanblk;    // the cached anodeblocklist
  181.     struct cdirblock    *firstdirblk;    // the cached dirblocklist
  182.  
  183.     BOOL    rootblockchangeflag;
  184.     WORD    numsofterrors;
  185.     WORD    diskstate;            // normally ID_VALIDATED
  186.     LONG    numblocks;            // total number of blocks
  187.     LONG    numblocksused;
  188.     LONG    numblocksfree;
  189.     WORD    bytesperblock;
  190. };
  191.  
  192. /**********************************************************************/
  193. /*                            Blockformat                             */
  194. /**********************************************************************/
  195.  
  196. #define DBLKID    0x4442    //'DB'
  197. #define ABLKID    0x4142    //'AB'
  198.  
  199.  
  200. /* Directory blocks
  201. **
  202. ** dirblock structure:
  203. **
  204. ** This is what a dirblock looks like on disk. Reserved fields are for
  205. ** future extension.
  206. **
  207. ** CDirBlock structure:
  208. **
  209. ** This is how a dirblock is cached.
  210. **
  211. ** DirEntry structure:
  212. **
  213. ** The 'type', 'creationtime' and 'protection' are, except for their
  214. ** size, in DOS format.
  215. ** The filename and the comment are dynamic: size followed by that
  216. ** number of characters (like BSTRs). The comment directly follows the
  217. ** filename. The 'next' field contains the size of the direntry. This
  218. ** should always be even. The end of the directoryblock is marked by
  219. ** next = 0.
  220. **
  221. ** The size of a direntry can be calculated by:
  222. ** size = (sizeof(struct direntry) + strlen(name) + strlen(comment))&0xfe
  223. */
  224. #define DB_HEADSPACE (6 + 10)
  225. #define DB_ENTRYSPACE (TD_SECTOR - 16)
  226.  
  227. struct dirblock            // voor disk only (WORD blokno), timestamp later..
  228. {
  229.     UWORD id;                    // 'DB'
  230.     ULONG reserved_1[2];
  231.     UWORD reserved_2;
  232.     UWORD anodenr;                // anodenr belonging to this directory (points to FIRST block of dir)
  233.     UWORD parent;                // parent; ANODE_ROOTDIR = root
  234.     UBYTE entries[DB_ENTRYSPACE];    // entries, fini by NULL
  235. };
  236.  
  237. struct cdirblock
  238. {
  239.     struct cdirblock *next;    // voor cachelist
  240.     struct volumedata *volume;
  241.     UWORD  blocknr;        // for already cached check
  242.     UWORD  usecount;
  243.     UWORD  changeflag;
  244.     UWORD  done;
  245.     struct dirblock blk;
  246. };
  247.  
  248. struct direntry
  249. {
  250.     UBYTE next;            // sizeof direntry
  251.     BYTE  type;            // dir, file, link etc
  252.     UWORD anode;        // anode nummer
  253.     ULONG size;            // sizeof file
  254.     UWORD creationday;    // days since Jan. 1, 1978 (ala ADOS; WORD ipv LONG)
  255.     UWORD creationminute; // minutes past modnight
  256.     UWORD creationtick;    // ticks past minute, not really needed
  257.     UBYTE protection;    // protection bits (ala ADOS)
  258.     UBYTE nlength;        // lenght of filename
  259.     UBYTE startofname;    // filename, followed by commentlen & comment
  260.     UBYTE pad;            // make size even
  261. };
  262.  
  263. // comment: de is struct direntry *
  264. #define COMMENT(de) ((UBYTE*)(&((de)->startofname) + (de)->nlength))
  265. #define OBJECTNAME(de) ((UBYTE*)(&(de->startofname)))
  266.  
  267. // get a pointer to the next direntry; de = struct direntry *
  268. #define NEXTENTRY(de) ((struct direntry*)((UBYTE*)(de) + (de)->next))
  269.  
  270. // get a pointer to the firste direntry; blok is struct dirblock *
  271. #define FIRSTENTRY(blok) ((struct direntry*)((blok)->blk.entries))
  272.  
  273. #define ENTRYLEN(de, comment) ((sizeof(struct direntry) + (de)->nlength + strlen(comment))&0xfffe)
  274.  
  275.  
  276. /* Anode blocks and Anodes
  277. **
  278. ** All space on disk is allocated by anodes. Anodes are runlength
  279. ** lists: a blocknr and a number indicating how many blocks are
  280. ** allocated by this anode.
  281. **
  282. ** The anodes are organized in an array spread over anodeblocks. The
  283. ** anodenr is the index in this array. The anodeblock themselves are
  284. ** allocated in the rootblock.
  285. **
  286. ** The first 6 anodes have a special function, they allocate
  287. ** freespace, the rootdirectory and perform system functions
  288. **
  289. ** Every anodeblock contains ANODESINBLOCK anodes.
  290. **
  291. ** struct canodeblock:
  292. **
  293. ** The anodeblock in the cache..
  294. **
  295. ** struct anode:
  296. **
  297. ** The anode itself. The 'clustersize' is the number of blocks being
  298. ** allocated. The allocated blocks are 'blocknr' up to (but not 
  299. ** including)  'blocknr' + 'clustersize'. The 'next' field is a link
  300. ** to another anode where the allocation continues. At the end of the
  301. ** anode chain next = 0.
  302. **
  303. ** If blocknr = 0 the anode is free, and can be reused. If the anode
  304. ** contains { 0, -1, next} the anode is reserved by a file or
  305. ** directory but is not yet in use. PS: empty anodes, with clustersize
  306. ** 0, are valid.
  307. ** Vrijgeven van een anode:  clustersize = 0; blocknr =  0; next = 0;
  308. */
  309.  
  310. #define ANODESINBLOCK    82
  311.  
  312. /* anode 0 is reserved; EOF; must be 0, -1, 0 (use for endoflist detection)
  313. ** ANODE_FREESPACE MUST have ANODE_RESERVED linked. All reserved blocks
  314. ** must be at the end of the chain. There may not be 'mixed' anodes
  315. ** anywhere
  316. **
  317. ** Anodes < 6 may be {0,0,0} but should NEVER be allocated for other
  318. ** purposes.
  319. ** ANODE_FREESPACE, ANODE_BADBLOCKS and ANODE_EOF should always be
  320. ** reserved {0, -1, 0}.
  321. ** ANODE_USERFIRST is the first anode usable for files etc.
  322. */
  323. #define ANODE_EOF            0
  324. #define ANODE_FREESPACE        1
  325. #define ANODE_RESERVED        2
  326. #define ANODE_TOBEFREED        3
  327. #define ANODE_BADBLOCKS        4
  328. #define ANODE_ROOTDIR        5
  329. #define ANODE_USERFIRST        6
  330.  
  331. struct anode
  332. {
  333.     UWORD clustersize;
  334.     UWORD blocknr;
  335.     UWORD next;
  336. };
  337.  
  338.  
  339. struct anodeblock
  340. {
  341.     UWORD id;
  342.     ULONG reserved_1[2];
  343.     UWORD seqnr;        // sequence number of anodeblock (starts with 0)
  344.     UWORD next;            // chain, 0 = end
  345.     UWORD pad;
  346.     struct anode nodes[ANODESINBLOCK];
  347.     ULONG reserved_2;
  348. };
  349.  
  350. struct canodeblock
  351. {
  352.     struct canodeblock *next;    // for cachelist
  353.     struct volumedata *volume;
  354.     UWORD  blocknr;
  355.     UWORD  usecount;
  356.     UWORD  changeflag;
  357.     UWORD  done;
  358.     struct anodeblock blk;
  359. };
  360.  
  361.  
  362. /* Data blocks
  363. */
  364. #define DATAINBLOCK    512
  365.  
  366. struct datablock
  367. {
  368.     UBYTE data[DATAINBLOCK];    // only data
  369. };
  370.  
  371. /* Rootblock and bootblocks
  372. */
  373. #define BOOTBLOCK1 0
  374. #define BOOTBLOCK2 1
  375. #define ROOTBLOCK 2
  376.  
  377. struct rootblock
  378. {
  379.     LONG  disktype;            // 'FDOS' same place as AmigaDos puts id
  380.     LONG  reserved_1[2];
  381.     UWORD creationday;        // days since Jan. 1, 1978 (ala ADOS; WORD ipv LONG)
  382.     UWORD creationminute;     // minutes past midnight
  383.     UWORD creationtick;        // ticks past minute, not really needed
  384.     UWORD protection;        // protection bits (ala ADOS)
  385.     UBYTE diskname[32];        // DSTR of diskname;
  386.     UWORD firstreserved;    // first reserved block (must be 0)
  387.     UWORD lastreserved;        // end of reserved area
  388.     LONG  reserved_2[10];
  389.     WORD anodeblocks[42];    // 0->notallocated
  390.     UBYTE reserved_3[DATAINBLOCK - 96 - 2*42];
  391. };
  392.  
  393. struct bootblock
  394. {
  395.     LONG disktype;
  396.     UBYTE reserved[508];
  397. };
  398.  
  399.  
  400. /* Reserved areas and other notes
  401. **
  402. ** Anode and directory blocks are allocated in a special reserved area
  403. ** at the start of the partition. The reserved area bounderies are defined
  404. ** in the rootblock and vary with disksize. The reserved area can
  405. ** overflow in the normal area and vice versa.
  406. **
  407. ** Directories are allocated by anodes, but they don't support
  408. ** clustersizes other than 1.
  409. **
  410. ** Allocation strategy
  411. **
  412. ** PFS always always writes directory and anodeblocks in a different
  413. ** place than they came from. The same for files: overwritten files are
  414. ** actually written somewhere else. A kind of 'freed first reused last'
  415. ** (FFRL) algorithm is used, so old versions stay on the disk for a long
  416. ** time. Sometimes PFS will abandon FFRL if this can prevent fragmentation.
  417. ** Recovery tools could make use of this: old versions can be restored
  418. ** if the current one is corrupt, and deleted files can be recovered.
  419. **
  420. ** Update strategy
  421. **
  422. ** Dirty anode and dirblocks are written to disk before the rootblock.
  423. ** Because the rootblock allocates the anodeblock which allocate the
  424. ** directories, and every anode is written on a new position, all
  425. ** changes take effect at the moment the rootblock is written. Before
  426. ** that seemingly nothing has changed.
  427. */
  428.  
  429.  
  430.