/*****************************************************************/ /** Microsoft LAN Manager **/ /** Copyright(c) Microsoft Corp., 1988-1990 **/ /*****************************************************************/ /*** MAP.C - Routines to manipulate disk maps and allocate memory * * DAMAGE * Gregory A. Jones * * Modification history: * G.A. Jones 06/02/88 Original for Pinball 1.0. * G.A. Jones 09/07/88 Adapted from CHKDSK's MAP.C and MEM.C. * G.A. Jones 09/08/88 Coded get_object. * G.A. Jones 09/19/88 Set dirty flag to FALSE on new object. */ #include #include #include #include "defs.h" #include "types.h" #include "globals.h" /*** clr_bit - clear a bit in a bitmap * * This routine is called to clear a bit in a bitmap. This * indicates a sector in use by the file system. * * clr_bit (lsn) * * ENTRY lsn - sector number to allocate * * EXIT Return value 0 if success, 1 if no bitmap, * 2 if bad sector number * * CALLS None * * EFFECTS Clears a bit in the global bitmap * * WARNINGS Bitmap should be allocated first */ USHORT clr_bit (ULONG lsn) { register ULONG byte; register USHORT bit; #ifdef TRACE_BITS fprintf (stderr, "clr_bit (%lx)\n", lsn); fflush (stderr); #endif if (!bitmap) /* bitmap is not allocated yet */ return (1); /* return error condition */ if (lsn > number_of_sectors) /* sector outside bitmap */ return (2); /* return error condition */ byte = lsn >> 3; /* divide by 8 without a DIV */ bit = (USHORT)(lsn & 7); /* "mod" by 8 without a DIV */ bitmap [byte] &= ~(1 << bit); /* clear the bit by ANDing with its inverse */ return (0); } /*** set_bit - set a bit in a bitmap * * This routine is called to set a bit in a bitmap. This * indicates a sector not in use by the file system. * * set_bit (lsn) * * ENTRY lsn - sector number to free * * EXIT Return value 0 if success, 1 if no bitmap, * 2 if bad sector number * * CALLS None * * EFFECTS Sets a bit in the global bitmap * * WARNINGS Bitmap should be allocated first */ USHORT set_bit (ULONG lsn) { register ULONG byte; register USHORT bit; #ifdef TRACE_BITS fprintf (stderr, "set_bit (%lx)\n", lsn); fflush (stderr); #endif if (!bitmap) /* bitmap is not allocated yet */ return (1); /* return error condition */ if (lsn > number_of_sectors) /* sector outside bitmap */ return (2); /* return error condition */ byte = lsn >> 3; /* divide by 8 without a DIV */ bit = (USHORT)(lsn & 7); /* "mod" by 8 without a DIV */ bitmap [byte] |= (1 << bit); /* set the bit by ORing with it */ return (0); } /*** allocate_block - allocate a memory chunk in multiples of 512 bytes * * This function is called to allocate a block of memory which is * a multiple of 512 bytes (one sector). This is a useful tool for * allocating a memory structure to store a run of sectors in. * * BUGBUG - make this a macro to save stack and execution time? * * allocate_block (nblocks) * * ENTRY nblocks - number of 512-byte blocks to allocate * * EXIT Returns NULL if insufficient memory, pointer if success * * CALLS malloc * * EFFECTS Allocates memory * * WARNINGS May return NULL pointer */ void *allocate_block (USHORT nblocks) { #ifdef TRACE fprintf (stderr, "allocate_block (%d)\n", nblocks); fflush (stderr); #endif return (malloc (nblocks * BYTES_PER_SECTOR)); } /*** free_block - free a memory chunk allocated by allocate_block * * This function is called to free a block of memory which was * allocated by the allocate_block function. * * BUGBUG - make this a macro to save stack and execution time? * * free_block (mem) * * ENTRY mem - pointer to memory to free * * EXIT No return value * * CALLS _ffree * * EFFECTS Deallocates memory * * WARNINGS "mem" will point to free space after this call */ void free_block (void *mem) { #ifdef TRACE fprintf (stderr, "free_block ()\n"); fflush (stderr); #endif free (mem); } /*** allocate_maps - allocate bit maps and disk map * * This function is called to allocate memory for both copies of * the bitmap, as well as CHKDSK's internal disk map. The bit * maps are not initialized, since they will be filled with disk * data; the disk map is initialized to DISK_UNKNOWN. * * Memory for the bitmaps is allocate one block (2K) overlong so * that reading the maps in will not overflow them. * * allocate_maps (nsects) * * ENTRY nsects - number of sectors in partition * * EXIT No return value * * CALLS malloc * memset * * EFFECTS Allocates memory * Initializes disk map * * WARNINGS May exit program if insufficient memory */ void allocate_maps (ULONG nsects) { ULONG i; #ifdef TRACE fprintf (stderr, "allocate_maps ()\n"); fflush (stderr); #endif i = (nsects - 1L) / ((ULONG)BYTES_PER_BITMAP * 8L) + 2L; if (((bitmap = calloc (i, 2048)) == NULL) || ((bitmap2 = calloc (i, 2048)) == NULL)) exit_error (INSF_MEM_ERROR); } /*** free_map - free a huge map * * This function is called to free memory allocated for a bit * map with halloc. * * free_map (p) * * ENTRY p - pointer to memory to free * * EXIT No return value * * CALLS hfree * * EFFECTS Deallocates memory */ void free_map (void * p) { #ifdef TRACE fprintf (stderr, "free_map ()\n"); fflush (stderr); #endif if (p) free (p); } /*** get_object - fill in currobj with information about an object * * This function is called to get a filesystem object off the disk * and store information about it in the current object structure. * It allocates memory for the object (or part of it, if it is a * large object such as a big data run), and reads the object into * memory. "currobj" is filled in with information about the object. * * If the memory pointer in currobj is already filled in, the memory * is re-used, and data is read from the offset stored in currobj. * This allows large data runs to be examined without reading the * entire run into memory. * * This routine expects the "sec" and "len" fields of currobj to * be set to point to the desired object before being called. If * a new portion of an object is being paged in, "offset" must also * be set; otherwise, "offset" is set to zero. * * The offset passed must be a multiple of one sector; allowing * byte granularity would complicate this routine tremendously. * * get_object () * * ENTRY No parameters * currobj.sec, .len, and .offset set appropriately * * EXIT No return value * currobj.mem, .offset filled in * * CALLS allocate_block * read_scratch * * WARNINGS if (currobj.mem), offset % 512 must be zero * * EFFECTS Allocates memory * Reads disk * Changes global variable "currobj" */ void get_object () { ULONG l; if (currobj.mem) { /* get different portion of object */ l = currobj.sec + currobj.offset; /* get sector address of what we want */ read_scratch (l, currobj.mem, SECTORS_PER_BLOCK); /* read 2K */ } else { /* get new object */ l = (currobj.len > SECTORS_PER_BLOCK) ? SECTORS_PER_BLOCK : currobj.len; currobj.mem = allocate_block (l); read_scratch (currobj.sec, currobj.mem, l); currobj.offset = 0L; currobj.dirty = FALSE; } }