Logo Search packages:      
Sourcecode: cbmconvert version File versions  Download package

static struct DirEnt* getDirEnt ( struct Image image,
const struct Filename name 
) [static, read]

Find the directory corresponding to a file

Parameters:
image the disk image
name the Commodore file name
Returns:
the corresponding directory entry, or NULL

Definition at line 1211 of file image.c.

References Image::buf, Image::dirtrack, getGeometry(), mapInode(), Filename::name, and Image::type.

Referenced by WriteImage().

{
  const struct DiskGeometry* geom;
  struct DirEnt** directory = 0;
  struct DirEnt* dirent = 0;
  unsigned block, i;
  int freeslotBlock = -1, freeslotEntry = -1;

  if (!name || !image || !image->buf || !(geom = getGeometry (image->type)))
    return 0;

  /* Read the current directory. */

  if (!(block = mapInode ((byte_t***)&directory, image, image->dirtrack, 0,
                    0, 0)))
    return 0;

  /* Check that the directory is long enough to hold the BAM blocks
     and at least one directory sector */
  if (block < geom->BAMblocks) {
    free (directory);
    return 0;
  }

  /* Search for the name in the directory. */
  for (block = geom->BAMblocks; ; block++) {
    for (i = 0; i * sizeof (struct DirEnt) < (directory[block]->nextTrack
                                    ? 256
                                    : directory[block]->nextSector);
       i++) {
      dirent = &directory[block][i];

      if (freeslotBlock == -1 && !dirent->type) {
      /* null file type => unused slot */
      freeslotBlock = block;
      freeslotEntry = i;
      }

      if (!memcmp (dirent->name, name->name, 16)) {
      free (directory);
      return dirent;
      }
    }

    if (!directory[block]->nextTrack)
      break;
  }

  /* The name was not found in the directory. */

  if (image->direntOpts == DirEntDontCreate) {
    free (directory);
    return 0;
  }

  if (freeslotBlock == -1) {
    /* Append a directory entry */

    if (i < 256 / sizeof *dirent) {
      /* grow the directory by growing its last sector */

      directory[block]->nextSector = (sizeof *dirent) *
      (1 + directory[block]->nextSector / sizeof *dirent);
      freeslotBlock = block;
      freeslotEntry = i;
    }
    else {
      /* allocate a new directory block */

      byte_t track, sector;
      byte_t t, s;

      track = image->dirtrack;
      sector = geom->BAMblocks;

      if (!findNextFree (image, &track, &sector)) {
      free (directory);
      return 0;
      }

      t = directory[block]->nextTrack = track;
      s = directory[block]->nextSector = sector;

      if (!allocBlock (image, &t, &s)) {
      directory[block]->nextTrack = 0;
      directory[block]->nextSector = 0xFF;
      free (directory);
      return 0;
      }

      /* Remap the directory from the disk image */

      free (directory);
      directory = 0;

      if (!mapInode ((byte_t***)&directory, image, image->dirtrack, 0, 0, 0))
      return 0;

      block++;

      /* initialize the new directory block */
      memset (directory[block], 0, 256);
      directory[block]->nextSector = 0xFF;

      freeslotBlock = block;
      freeslotEntry = 0;
    }
  }

  /* Clear the directory entry. */

  dirent = &directory[freeslotBlock][freeslotEntry];

  if (freeslotEntry)
    memset (dirent, 0, sizeof *dirent);
  else
    memset (&dirent->type, 0, (sizeof *dirent) - 2);

  free (directory);
  return dirent;
}


Generated by  Doxygen 1.6.0   Back to index