|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 3063 (0xbf7) Types: TextFile Notes: UNIX file Names: »discbuf.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »cmd/dump/discbuf.c«
/* * This file contains a * mini disc buffer cache manager. */ #include <stdio.h> #include <discbuf.h> DISCBUF *dblist; FILE *dbfp; /* * Claim a buffer and * read block `block' into it. * Return a pointer to the * buffer. */ DISCBUF * dbread(block) long block; { register DISCBUF *dbp; dbp = dbgrab(block); if ((dbp->db_flag&DB_OK) == 0) { lseek(fileno(dbfp), BUFSIZ*dbp->db_block, 0); if (read(fileno(dbfp), dbp->db_data, BUFSIZ) != BUFSIZ) dbfatal("cache read error, block %D", block); dbp->db_flag |= DB_OK; } return (dbp); } /* * This routine grabs a buffer * and declares it to be the contents * of block `block'. * The data in the block is set to * all zeros. */ DISCBUF * dbzero(block) long block; { register DISCBUF *dbp; register char *p; register n; dbp = dbgrab(block); dbp->db_flag = DB_OK; p = dbp->db_data; n = BUFSIZ; do { *p++ = 0; } while (--n); return (dbp); } /* * Buffer grab. * Try to find a buffer that * has the block in it. * If not, use the oldest free * buffer. */ DISCBUF * dbgrab(block) long block; { register DISCBUF *dbp1, *dbp2; register DISCBUF *fbp1, *fbp2; dbp1 = fbp1 = fbp2 = NULL; dbp2 = dblist; while (dbp2!=NULL && dbp2->db_block!=block) { if (dbp2->db_refc == 0) { fbp1 = dbp1; fbp2 = dbp2; } dbp1 = dbp2; dbp2 = dbp2->db_fp; } if (dbp2 == NULL) { if (fbp2 == NULL) dbfatal("cache full"); dbp1 = fbp1; dbp2 = fbp2; if ((dbp2->db_flag&DB_DIRT) != 0) dbwrite(dbp2); dbp2->db_flag = 0; dbp2->db_block = block; } ++dbp2->db_refc; if (dbp1 != NULL) { dbp1->db_fp = dbp2->db_fp; dbp2->db_fp = dblist; dblist = dbp2; } return (dbp2); } /* * Flush the buffer cache. All * dirty buffers get written out to * the disc. * If `flag' is true the buffer * cache is released. */ dbflush(flag) { register DISCBUF *dbp; register DISCBUF *fbp; dbp = dblist; while (dbp != NULL) { if ((dbp->db_flag&(DB_OK|DB_DIRT)) == (DB_OK|DB_DIRT)) dbwrite(dbp); if (flag) { fbp = dbp; dbp = dbp->db_fp; free((char *) fbp); } else { dbp->db_flag = 0; dbp->db_refc = 0; dbp = dbp->db_fp; } } if (flag) dblist = NULL; } /* * Allocate a buffer cache. * The argument `nbuf' is the number * of buffers to claim. */ dbclaim(nbuf) { register DISCBUF *dbp; if (dblist != NULL) dbfatal("already claimed"); while (nbuf--) { if ((dbp = (DISCBUF *) malloc(sizeof(DISCBUF))) == NULL) dbfatal("no memory"); dbp->db_flag = 0; dbp->db_refc = 0; dbp->db_fp = dblist; dblist = dbp; } } /* * Write a buffer to the disc. */ dbwrite(dbp) register DISCBUF *dbp; { lseek(fileno(dbfp), BUFSIZ*dbp->db_block, 0); if (write(fileno(dbfp), dbp->db_data, BUFSIZ) != BUFSIZ) dbfatal("cache write error, block %D", dbp->db_block); } /* * Release a buffer. * The reference count is updated */ dbfree(dbp, flag) register DISCBUF *dbp; { dbp->db_flag |= flag; if (--dbp->db_refc < 0) dbfatal("refc < 0"); } /* * Fatal errors. */ dbfatal(a) { fprintf(stderr, "discbuf: %r\n", &a); exit(1); }