Example #1
0
/*
 * NAME:	vol->mkdir()
 * DESCRIPTION:	create a new HFS directory
 */
int v_mkdir(hfsvol *vol, long parid, const char *name)
{
    CatKeyRec key;
    CatDataRec data;
    long id;
    byte record[HFS_MAX_CATRECLEN];
    int i, reclen;

    if (bt_space(&vol->cat, 2) == -1)
        goto fail;

    id = vol->mdb.drNxtCNID++;
    vol->flags |= HFS_VOL_UPDATE_MDB;

    /* create directory record */

    data.cdrType   = cdrDirRec;
    data.cdrResrv2 = 0;

    data.u.dir.dirFlags = 0;
    data.u.dir.dirVal   = 0;
    data.u.dir.dirDirID = id;
    data.u.dir.dirCrDat = d_mtime(time(0));
    data.u.dir.dirMdDat = data.u.dir.dirCrDat;
    data.u.dir.dirBkDat = 0;

    memset(&data.u.dir.dirUsrInfo,  0, sizeof(data.u.dir.dirUsrInfo));
    memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo));
    for (i = 0; i < 4; ++i)
        data.u.dir.dirResrv[i] = 0;

    r_makecatkey(&key, parid, name);
    r_packcatrec(&key, &data, record, &reclen);

    if (bt_insert(&vol->cat, record, reclen) == -1)
        goto fail;

    /* create thread record */

    data.cdrType   = cdrThdRec;
    data.cdrResrv2 = 0;

    data.u.dthd.thdResrv[0] = 0;
    data.u.dthd.thdResrv[1] = 0;
    data.u.dthd.thdParID    = parid;
    strcpy(data.u.dthd.thdCName, name);

    r_makecatkey(&key, id, "");
    r_packcatrec(&key, &data, record, &reclen);

    if (bt_insert(&vol->cat, record, reclen) == -1 ||
            v_adjvalence(vol, parid, 1, 1) == -1)
        goto fail;

    return 0;

fail:
    return -1;
}
Example #2
0
/*
 * NAME:	hfs->write()
 * DESCRIPTION:	write to an open file
 */
unsigned long hfs_write(hfsfile *file, const void *buf, unsigned long len)
{
  unsigned long *lglen, *pylen, count;
  const byte *ptr = buf;

  if (file->vol->flags & HFS_VOL_READONLY)
    ERROR(EROFS, 0);

  f_getptrs(file, 0, &lglen, &pylen);

  count = len;

  /* set flag to update (at least) the modification time */

  if (count)
    {
      file->cat.u.fil.filMdDat = d_mtime(time(0));
      file->flags |= HFS_FILE_UPDATE_CATREC;
    }

  while (count)
    {
      unsigned long bnum, offs, chunk;

      bnum  = file->pos >> HFS_BLOCKSZ_BITS;
      offs  = file->pos & (HFS_BLOCKSZ - 1);

      chunk = HFS_BLOCKSZ - offs;
      if (chunk > count)
	chunk = count;

      if (file->pos + chunk > *pylen)
	{
	  if (bt_space(&file->vol->ext, 1) == -1 ||
	      f_alloc(file) == -1)
	    goto fail;
	}

      if (offs == 0 && chunk == HFS_BLOCKSZ)
	{
	  if (f_putblock(file, bnum, (block *) ptr) == -1)
	    goto fail;
	}
      else
	{
	  block b;

	  if (f_getblock(file, bnum, &b) == -1)
	    goto fail;

	  memcpy(b + offs, ptr, chunk);

	  if (f_putblock(file, bnum, &b) == -1)
	    goto fail;
	}

      ptr += chunk;

      file->pos += chunk;
      count     -= chunk;

      if (file->pos > *lglen)
	*lglen = file->pos;
    }

  return len;

fail:
  return -1;
}
Example #3
0
/*
 * NAME:	vol->newfolder()
 * DESCRIPTION:	create a new HFS folder
 */
int v_newfolder(hfsvol *vol, long parid, char *name)
{
  CatKeyRec key;
  CatDataRec data;
  long id;
  unsigned char record[HFS_CATRECMAXLEN];
  int i, reclen;

  if (bt_space(&vol->cat, 2) < 0)
    return -1;

  id = vol->mdb.drNxtCNID++;
  vol->flags |= HFS_UPDATE_MDB;

  /* create directory record */

  data.cdrType   = cdrDirRec;
  data.cdrResrv2 = 0;

  data.u.dir.dirFlags = 0;
  data.u.dir.dirVal   = 0;
  data.u.dir.dirDirID = id;
#ifdef UHFS
  data.u.dir.dirCrDat = 0;
#else
  data.u.dir.dirCrDat = d_tomtime(time(0));
#endif
  data.u.dir.dirMdDat = data.u.dir.dirCrDat;
  data.u.dir.dirBkDat = 0;

  memset(&data.u.dir.dirUsrInfo,  0, sizeof(data.u.dir.dirUsrInfo));
  memset(&data.u.dir.dirFndrInfo, 0, sizeof(data.u.dir.dirFndrInfo));
  for (i = 0; i < 4; ++i)
    data.u.dir.dirResrv[i] = 0;

  r_makecatkey(&key, parid, name);
  r_packcatkey(&key, record, &reclen);
  r_packcatdata(&data, HFS_RECDATA(record), &reclen);

  if (bt_insert(&vol->cat, record, reclen) < 0)
    return -1;

  /* create thread record */

  data.cdrType   = cdrThdRec;
  data.cdrResrv2 = 0;

  data.u.dthd.thdResrv[0] = 0;
  data.u.dthd.thdResrv[1] = 0;
  data.u.dthd.thdParID    = parid;
  strcpy(data.u.dthd.thdCName, name);

  r_makecatkey(&key, id, "");
  r_packcatkey(&key, record, &reclen);
  r_packcatdata(&data, HFS_RECDATA(record), &reclen);

  if (bt_insert(&vol->cat, record, reclen) < 0 ||
      v_adjvalence(vol, parid, 1, 1) < 0)
    return -1;

  return 0;
}
Example #4
0
/*
 * NAME:	hfs->create()
 * DESCRIPTION:	create and open a new file
 */
hfsfile *hfs_create(hfsvol *vol, const char *path,
		    const char *type, const char *creator)
{
  hfsfile *file = 0;
  unsigned long parid;
  char name[HFS_MAX_FLEN + 1];
  CatKeyRec key;
  byte record[HFS_MAX_CATRECLEN];
  unsigned reclen;
  int found;

  if (getvol(&vol) == -1)
    goto fail;

  file = ALLOC(hfsfile, 1);
  if (file == 0)
    ERROR(ENOMEM, 0);

  found = v_resolve(&vol, path, &file->cat, &parid, name, 0);
  if (found == -1 || parid == 0)
    goto fail;

  if (found)
    ERROR(EEXIST, 0);

  if (parid == HFS_CNID_ROOTPAR)
    ERROR(EINVAL, 0);

  if (vol->flags & HFS_VOL_READONLY)
    ERROR(EROFS, 0);

  /* create file `name' in parent `parid' */

  if (bt_space(&vol->cat, 1) == -1)
    goto fail;

  f_init(file, vol, vol->mdb.drNxtCNID++, name);
  vol->flags |= HFS_VOL_UPDATE_MDB;

  file->parid = parid;

  /* create catalog record */

  file->cat.u.fil.filUsrWds.fdType =
    d_getsl((const unsigned char *) type);
  file->cat.u.fil.filUsrWds.fdCreator =
    d_getsl((const unsigned char *) creator);

  file->cat.u.fil.filCrDat = d_mtime(time(0));
  file->cat.u.fil.filMdDat = file->cat.u.fil.filCrDat;

  r_makecatkey(&key, file->parid, file->name);
  r_packcatrec(&key, &file->cat, record, &reclen);

  if (bt_insert(&vol->cat, record, reclen) == -1 ||
      v_adjvalence(vol, file->parid, 0, 1) == -1)
    goto fail;

  /* package file handle for user */

  file->next = vol->files;

  if (vol->files)
    vol->files->prev = file;

  vol->files = file;

  return file;

fail:
  FREE(file);
  return 0;
}
Example #5
0
int hfs_callback_format(oscallback func, void* cookie, int mode,
	const char* vname)
#endif
{
  hfsvol vol;
  btree *ext = &vol.ext;
  btree *cat = &vol.cat;
  unsigned int i, *badalloc = 0;

  v_init(&vol, mode);

  if (! validvname(vname))
    goto fail;

#ifdef CP_NOT_USED
  if (v_open(&vol, path, HFS_MODE_RDWR) == -1 ||
      v_geometry(&vol, pnum) == -1)
    goto fail;
#else
  if (v_callback_open(&vol, func, cookie) != 0 ||
	  v_geometry(&vol, 0) != 0)
	goto fail;
#endif

  /* initialize volume geometry */

  vol.lpa = 1 + ((vol.vlen - 6) >> 16);

  if (vol.flags & HFS_OPT_2048)
    vol.lpa = (vol.lpa + 3) & ~3;

  vol.vbmsz = (vol.vlen / vol.lpa + 0x0fff) >> 12;

  vol.mdb.drSigWord  = HFS_SIGWORD;
  vol.mdb.drCrDate   = d_mtime(time(0));
  vol.mdb.drLsMod    = vol.mdb.drCrDate;
  vol.mdb.drAtrb     = 0;
  vol.mdb.drNmFls    = 0;
  vol.mdb.drVBMSt    = 3;
  vol.mdb.drAllocPtr = 0;

  vol.mdb.drAlBlkSiz = vol.lpa << HFS_BLOCKSZ_BITS;
  vol.mdb.drClpSiz   = vol.mdb.drAlBlkSiz << 2;
  vol.mdb.drAlBlSt   = vol.mdb.drVBMSt + vol.vbmsz;

  if (vol.flags & HFS_OPT_2048)
    vol.mdb.drAlBlSt = ((vol.vstart & 3) + vol.mdb.drAlBlSt + 3) & ~3;

  vol.mdb.drNmAlBlks = (vol.vlen - 2 - vol.mdb.drAlBlSt) / vol.lpa;

  vol.mdb.drNxtCNID  = HFS_CNID_ROOTDIR;  /* modified later */
  vol.mdb.drFreeBks  = vol.mdb.drNmAlBlks;

  strcpy(vol.mdb.drVN, vname);

  vol.mdb.drVolBkUp  = 0;
  vol.mdb.drVSeqNum  = 0;
  vol.mdb.drWrCnt    = 0;

  vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz;
  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz;

  vol.mdb.drNmRtDirs = 0;
  vol.mdb.drFilCnt   = 0;
  vol.mdb.drDirCnt   = -1;  /* incremented when root directory is created */

  for (i = 0; i < 8; ++i)
    vol.mdb.drFndrInfo[i] = 0;

  vol.mdb.drEmbedSigWord            = 0x0000;
  vol.mdb.drEmbedExtent.xdrStABN    = 0;
  vol.mdb.drEmbedExtent.xdrNumABlks = 0;

  /* vol.mdb.drXTFlSize */
  /* vol.mdb.drCTFlSize */

  /* vol.mdb.drXTExtRec[0..2] */
  /* vol.mdb.drCTExtRec[0..2] */

  vol.flags |= HFS_VOL_UPDATE_MDB | HFS_VOL_UPDATE_ALTMDB;

  /* initialize volume bitmap */

  vol.vbm = ALLOC(block, vol.vbmsz);
  if (vol.vbm == 0)
    ERROR(ENOMEM, 0);

  memset(vol.vbm, 0, vol.vbmsz << HFS_BLOCKSZ_BITS);

  vol.flags |= HFS_VOL_UPDATE_VBM;

  /* perform initial bad block sparing */

#ifdef CP_NOT_USED
  if (nbadblocks > 0)
    {
      if (nbadblocks * 4 > vol.vlen)
	ERROR(EINVAL, "volume contains too many bad blocks");

      badalloc = ALLOC(unsigned int, nbadblocks);
      if (badalloc == 0)
	ERROR(ENOMEM, 0);

      if (vol.mdb.drNmAlBlks == 1594)
	vol.mdb.drFreeBks = --vol.mdb.drNmAlBlks;

      for (i = 0; i < nbadblocks; ++i)
	{
	  unsigned long bnum;
	  unsigned int anum;

	  bnum = badblocks[i];

	  if (bnum < vol.mdb.drAlBlSt || bnum == vol.vlen - 2)
	    ERROR(EINVAL, "can't spare critical bad block");
	  else if (bnum >= vol.vlen)
	    ERROR(EINVAL, "bad block not in volume");

	  anum = (bnum - vol.mdb.drAlBlSt) / vol.lpa;

	  if (anum < vol.mdb.drNmAlBlks)
	    BMSET(vol.vbm, anum);

	  badalloc[i] = anum;
	}

      vol.mdb.drAtrb |= HFS_ATRB_BBSPARED;
    }
#endif

  /* create extents overflow file */

  n_init(&ext->hdrnd, ext, ndHdrNode, 0);

  ext->hdrnd.nnum       = 0;
  ext->hdrnd.nd.ndNRecs = 3;
  ext->hdrnd.roff[1]    = 0x078;
  ext->hdrnd.roff[2]    = 0x0f8;
  ext->hdrnd.roff[3]    = 0x1f8;

  memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128);

  ext->hdr.bthDepth    = 0;
  ext->hdr.bthRoot     = 0;
  ext->hdr.bthNRecs    = 0;
  ext->hdr.bthFNode    = 0;
  ext->hdr.bthLNode    = 0;
  ext->hdr.bthNodeSize = HFS_BLOCKSZ;
  ext->hdr.bthKeyLen   = 0x07;
  ext->hdr.bthNNodes   = 0;
  ext->hdr.bthFree     = 0;
  for (i = 0; i < 76; ++i)
    ext->hdr.bthResv[i] = 0;

  ext->map = ALLOC(byte, HFS_MAP1SZ);
  if (ext->map == 0)
    ERROR(ENOMEM, 0);

  memset(ext->map, 0, HFS_MAP1SZ);
  BMSET(ext->map, 0);

  ext->mapsz = HFS_MAP1SZ;
  ext->flags = HFS_BT_UPDATE_HDR;

  /* create catalog file */

  n_init(&cat->hdrnd, cat, ndHdrNode, 0);

  cat->hdrnd.nnum       = 0;
  cat->hdrnd.nd.ndNRecs = 3;
  cat->hdrnd.roff[1]    = 0x078;
  cat->hdrnd.roff[2]    = 0x0f8;
  cat->hdrnd.roff[3]    = 0x1f8;

  memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128);

  cat->hdr.bthDepth    = 0;
  cat->hdr.bthRoot     = 0;
  cat->hdr.bthNRecs    = 0;
  cat->hdr.bthFNode    = 0;
  cat->hdr.bthLNode    = 0;
  cat->hdr.bthNodeSize = HFS_BLOCKSZ;
  cat->hdr.bthKeyLen   = 0x25;
  cat->hdr.bthNNodes   = 0;
  cat->hdr.bthFree     = 0;
  for (i = 0; i < 76; ++i)
    cat->hdr.bthResv[i] = 0;

  cat->map = ALLOC(byte, HFS_MAP1SZ);
  if (cat->map == 0)
    ERROR(ENOMEM, 0);

  memset(cat->map, 0, HFS_MAP1SZ);
  BMSET(cat->map, 0);

  cat->mapsz = HFS_MAP1SZ;
  cat->flags = HFS_BT_UPDATE_HDR;

  /* allocate space for header nodes (and initial extents) */

  if (bt_space(ext, 1) == -1 ||
      bt_space(cat, 1) == -1)
    goto fail;

  --ext->hdr.bthFree;
  --cat->hdr.bthFree;

  /* create extent records for bad blocks */

#ifdef CP_NOT_USED
  if (nbadblocks > 0)
    {
      hfsfile bbfile;
      ExtDescriptor extent;
      ExtDataRec *extrec;
      ExtKeyRec key;
      byte record[HFS_MAX_EXTRECLEN];
      unsigned int reclen;

      f_init(&bbfile, &vol, HFS_CNID_BADALLOC, "bad blocks");

      qsort(badalloc, nbadblocks, sizeof(*badalloc),
	    (int (*)(const void *, const void *)) compare);

      for (i = 0; i < nbadblocks; ++i)
	{
	  if (i == 0 || badalloc[i] != extent.xdrStABN)
	    {
	      extent.xdrStABN    = badalloc[i];
	      extent.xdrNumABlks = 1;

	      if (extent.xdrStABN < vol.mdb.drNmAlBlks &&
		  f_addextent(&bbfile, &extent) == -1)
		goto fail;
	    }
	}

      /* flush local extents into extents overflow file */

      f_getptrs(&bbfile, &extrec, 0, 0);

      r_makeextkey(&key, bbfile.fork, bbfile.cat.u.fil.filFlNum, 0);
      r_packextrec(&key, extrec, record, &reclen);

      if (bt_insert(&vol.ext, record, reclen) == -1)
	goto fail;
    }
#endif

  vol.flags |= HFS_VOL_MOUNTED;

  /* create root directory */

  if (v_mkdir(&vol, HFS_CNID_ROOTPAR, vname) == -1)
    goto fail;

  vol.mdb.drNxtCNID = 16;  /* first CNID not reserved by Apple */

  /* write boot blocks */

  if (m_zerobb(&vol) == -1)
    goto fail;

  /* zero other unused space, if requested */

  if (vol.flags & HFS_OPT_ZERO)
    {
      block b;
      unsigned long bnum;

      memset(&b, 0, sizeof(b));

      /* between MDB and VBM (never) */

      for (bnum = 3; bnum < vol.mdb.drVBMSt; ++bnum)
	b_writelb(&vol, bnum, &b);

      /* between VBM and first allocation block (sometimes if HFS_OPT_2048) */

      for (bnum = vol.mdb.drVBMSt + vol.vbmsz; bnum < vol.mdb.drAlBlSt; ++bnum)
	b_writelb(&vol, bnum, &b);

      /* between last allocation block and alternate MDB (sometimes) */

      for (bnum = vol.mdb.drAlBlSt + vol.mdb.drNmAlBlks * vol.lpa;
	   bnum < vol.vlen - 2; ++bnum)
	b_writelb(&vol, bnum, &b);

      /* final block (always) */

      b_writelb(&vol, vol.vlen - 1, &b);
    }

  /* flush remaining state and close volume */

  if (v_close(&vol) == -1)
    goto fail;

  FREE(badalloc);

  return 0;

fail:
  v_close(&vol);

  FREE(badalloc);

  return -1;
}
Example #6
0
/*
 * NAME:	hfs->format()
 * DESCRIPTION:	write a new filesystem
 */
int hfs_format(char *path, int pnum, char *vname)
{
  hfsvol vol;
  btree *ext = &vol.ext;
  btree *cat = &vol.cat;
  unsigned int vbmsz;
  int i, result = 0;
  block vbm[16];
  char *map;

  if (mystrchr(vname, ':'))
    {
      ERROR(EINVAL, "volume name may not contain colons");
      return -1;
    }

  i = strlen(vname);
  if (i < 1 || i > HFS_MAX_VLEN)
    {
      ERROR(EINVAL, "volume name must be 1-27 chars");
      return -1;
    }

  vol.flags  = 0;
  vol.pnum   = pnum;
  vol.vstart = 0;
  vol.vlen   = 0;
  vol.lpa    = 0;
  vol.vbm    = vbm;
  vol.cwd    = HFS_CNID_ROOTDIR;

  vol.refs   = 0;
  vol.files  = 0;
  vol.dirs   = 0;
  vol.prev   = 0;
  vol.next   = 0;

#if 0
  vol.fd = open(path, O_RDWR);

  if (vol.fd < 0)
    {
      ERROR(errno, "error opening device for writing");
      return -1;
    }
#endif

  if (l_lockvol(&vol) < 0)
    {
#if 0
      close(vol.fd);
#endif
      return -1;
    }

  if (pnum > 0)
    {
      if (l_readpm(&vol) < 0)
	{
#if 0
	  close(vol.fd);
#endif
	  return -1;
	}
    }
  else  /* determine size of entire device */
    {
      unsigned long low, high, mid;
      block b;

      for (low = 0, high = 2879; b_readlb(&vol, high, &b) >= 0; high *= 2)
	low = high;

      while (low < high - 1)
	{
	  mid = (low + high) / 2;

	  if (b_readlb(&vol, mid, &b) < 0)
	    high = mid;
	  else
	    low = mid;
	}

      vol.vlen = low + 1;
    }

  if (vol.vlen < 800 * 1024 / HFS_BLOCKSZ)
    {
#if 0
      close(vol.fd);
#endif

      ERROR(EINVAL, "volume size must be >= 800K");
      return -1;
    }

  /* initialize volume geometry */

  vol.lpa = 1 + vol.vlen / 65536;

  vbmsz = (vol.vlen / vol.lpa + 4095) / 4096;

  vol.mdb.drSigWord  = 0x4244;
  vol.mdb.drCrDate   = d_tomtime(/*time*/(0));
  vol.mdb.drLsMod    = vol.mdb.drCrDate;
  vol.mdb.drAtrb     = 0;
  vol.mdb.drNmFls    = 0;
  vol.mdb.drVBMSt    = 3;
  vol.mdb.drAllocPtr = 0;
  vol.mdb.drNmAlBlks = (vol.vlen - 5 - vbmsz) / vol.lpa;
  vol.mdb.drAlBlkSiz = vol.lpa * HFS_BLOCKSZ;
  vol.mdb.drClpSiz   = vol.mdb.drAlBlkSiz * 4;
  vol.mdb.drAlBlSt   = 3 + vbmsz;
  vol.mdb.drNxtCNID  = HFS_CNID_ROOTDIR;  /* modified later */
  vol.mdb.drFreeBks  = vol.mdb.drNmAlBlks;

  strcpy(vol.mdb.drVN, vname);

  vol.mdb.drVolBkUp  = 0;
  vol.mdb.drVSeqNum  = 0;
  vol.mdb.drWrCnt    = 0;
  vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz;
  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz;
  vol.mdb.drNmRtDirs = 0;
  vol.mdb.drFilCnt   = 0;
  vol.mdb.drDirCnt   = -1;  /* incremented when root folder is created */

  for (i = 0; i < 8; ++i)
    vol.mdb.drFndrInfo[i] = 0;

  vol.mdb.drVCSize   = 0;
  vol.mdb.drVBMCSize = 0;
  vol.mdb.drCtlCSize = 0;

  vol.mdb.drXTFlSize = 0;
  vol.mdb.drCTFlSize = 0;

  for (i = 0; i < 3; ++i)
    {
      vol.mdb.drXTExtRec[i].xdrStABN    = 0;
      vol.mdb.drXTExtRec[i].xdrNumABlks = 0;

      vol.mdb.drCTExtRec[i].xdrStABN    = 0;
      vol.mdb.drCTExtRec[i].xdrNumABlks = 0;
    }

  /* initialize volume bitmap */

  memset(vol.vbm, 0, sizeof(vbm));

  /* create extents overflow file */

  ext->f.vol   = &vol;
  ext->f.parid = 0;
  strcpy(ext->f.name, "extents overflow");

  ext->f.cat.cdrType          = cdrFilRec;
  /* ext->f.cat.cdrResrv2 */
  ext->f.cat.u.fil.filFlags   = 0;
  ext->f.cat.u.fil.filTyp     = 0;
  /* ext->f.cat.u.fil.filUsrWds */
  ext->f.cat.u.fil.filFlNum   = HFS_CNID_EXT;
  ext->f.cat.u.fil.filStBlk   = 0;
  ext->f.cat.u.fil.filLgLen   = 0;
  ext->f.cat.u.fil.filPyLen   = 0;
  ext->f.cat.u.fil.filRStBlk  = 0;
  ext->f.cat.u.fil.filRLgLen  = 0;
  ext->f.cat.u.fil.filRPyLen  = 0;
  ext->f.cat.u.fil.filCrDat   = vol.mdb.drCrDate;
  ext->f.cat.u.fil.filMdDat   = vol.mdb.drLsMod;
  ext->f.cat.u.fil.filBkDat   = 0;
  /* ext->f.cat.u.fil.filFndrInfo */
  ext->f.cat.u.fil.filClpSize = 0;

  for (i = 0; i < 3; ++i)
    {
      ext->f.cat.u.fil.filExtRec[i].xdrStABN     = 0;
      ext->f.cat.u.fil.filExtRec[i].xdrNumABlks  = 0;

      ext->f.cat.u.fil.filRExtRec[i].xdrStABN    = 0;
      ext->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
    }
  /* ext->f.cat.u.fil.filResrv */
  f_selectfork(&ext->f, 0);

  ext->f.clump = vol.mdb.drXTClpSiz;
  ext->f.flags = 0;

  ext->f.prev = ext->f.next = 0;

  n_init(&ext->hdrnd, ext, ndHdrNode, 0);

  ext->hdrnd.nnum       = 0;
  ext->hdrnd.nd.ndNRecs = 3;
  ext->hdrnd.roff[1]    = 0x078;
  ext->hdrnd.roff[2]    = 0x0f8;
  ext->hdrnd.roff[3]    = 0x1f8;

  memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128);

  ext->hdr.bthDepth    = 0;
  ext->hdr.bthRoot     = 0;
  ext->hdr.bthNRecs    = 0;
  ext->hdr.bthFNode    = 0;
  ext->hdr.bthLNode    = 0;
  ext->hdr.bthNodeSize = HFS_BLOCKSZ;
  ext->hdr.bthKeyLen   = 0x07;
  ext->hdr.bthNNodes   = 0;
  ext->hdr.bthFree     = 0;
  for (i = 0; i < 76; ++i)
    ext->hdr.bthResv[i] = 0;

  map = ALLOC(char, HFS_MAP1SZ);
  if (map == 0)
    {
      if (result == 0)
	{
	  ERROR(ENOMEM, 0);
	  result = -1;
	}
    }
  else
    {
      memset(map, 0, HFS_MAP1SZ);
      BMSET(map, 0);
    }

  ext->map     = map;
  ext->mapsz   = HFS_MAP1SZ;
  ext->flags   = HFS_UPDATE_BTHDR;
  ext->compare = r_compareextkeys;

  if (result == 0 && bt_space(ext, 1) < 0)
    result = -1;

  --ext->hdr.bthFree;

  /* create catalog file */

  cat->f.vol   = &vol;
  cat->f.parid = 0;
  strcpy(cat->f.name, "catalog");

  cat->f.cat.cdrType          = cdrFilRec;
  /* cat->f.cat.cdrResrv2 */
  cat->f.cat.u.fil.filFlags   = 0;
  cat->f.cat.u.fil.filTyp     = 0;
  /* cat->f.cat.u.fil.filUsrWds */
  cat->f.cat.u.fil.filFlNum   = HFS_CNID_CAT;
  cat->f.cat.u.fil.filStBlk   = 0;
  cat->f.cat.u.fil.filLgLen   = 0;
  cat->f.cat.u.fil.filPyLen   = 0;
  cat->f.cat.u.fil.filRStBlk  = 0;
  cat->f.cat.u.fil.filRLgLen  = 0;
  cat->f.cat.u.fil.filRPyLen  = 0;
  cat->f.cat.u.fil.filCrDat   = vol.mdb.drCrDate;
  cat->f.cat.u.fil.filMdDat   = vol.mdb.drLsMod;
  cat->f.cat.u.fil.filBkDat   = 0;
  /* cat->f.cat.u.fil.filFndrInfo */
  cat->f.cat.u.fil.filClpSize = 0;

  for (i = 0; i < 3; ++i)
    {
      cat->f.cat.u.fil.filExtRec[i].xdrStABN     = 0;
      cat->f.cat.u.fil.filExtRec[i].xdrNumABlks  = 0;

      cat->f.cat.u.fil.filRExtRec[i].xdrStABN    = 0;
      cat->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
    }
  /* cat->f.cat.u.fil.filResrv */
  f_selectfork(&cat->f, 0);

  cat->f.clump = vol.mdb.drCTClpSiz;
  cat->f.flags = 0;

  cat->f.prev = cat->f.next = 0;

  n_init(&cat->hdrnd, cat, ndHdrNode, 0);

  cat->hdrnd.nnum       = 0;
  cat->hdrnd.nd.ndNRecs = 3;
  cat->hdrnd.roff[1]    = 0x078;
  cat->hdrnd.roff[2]    = 0x0f8;
  cat->hdrnd.roff[3]    = 0x1f8;

  memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128);

  cat->hdr.bthDepth    = 0;
  cat->hdr.bthRoot     = 0;
  cat->hdr.bthNRecs    = 0;
  cat->hdr.bthFNode    = 0;
  cat->hdr.bthLNode    = 0;
  cat->hdr.bthNodeSize = HFS_BLOCKSZ;
  cat->hdr.bthKeyLen   = 0x25;
  cat->hdr.bthNNodes   = 0;
  cat->hdr.bthFree     = 0;
  for (i = 0; i < 76; ++i)
    cat->hdr.bthResv[i] = 0;

  map = ALLOC(char, HFS_MAP1SZ);
  if (map == 0)
    {
      if (result == 0)
	{
	  ERROR(ENOMEM, 0);
	  result = -1;
	}
    }
  else
    {
      memset(map, 0, HFS_MAP1SZ);
      BMSET(map, 0);
    }

  cat->map     = map;
  cat->mapsz   = HFS_MAP1SZ;
  cat->flags   = HFS_UPDATE_BTHDR;
  cat->compare = r_comparecatkeys;

  if (result == 0 && bt_space(cat, 1) < 0)
    result = -1;

  --cat->hdr.bthFree;

  /* create root folder */

  if (result == 0 && v_newfolder(&vol, HFS_CNID_ROOTPAR, vname) < 0)
    result = -1;

  vol.mdb.drNxtCNID = 16;

  /* finish up */

  if (result == 0)
    {
      block b;

      /* write boot blocks */

      memset(&b, 0, sizeof(b));
      b_writelb(&vol, 0, &b);
      b_writelb(&vol, 1, &b);

      /* flush other disk state */

      vol.flags |= HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB | HFS_UPDATE_VBM;

      if (v_flush(&vol, 1) < 0)
	result = -1;
    }

  if (
#if 0
      close(vol.fd) < 0 && 
#endif
      result == 0)
    {
      ERROR(errno, "error closing device");
      result = -1;
    }

  FREE(vol.ext.map);
  FREE(vol.cat.map);

  return result;
}
Example #7
0
/*
 * NAME:	hfs->create()
 * DESCRIPTION:	create a new file
 */
int hfs_create(hfsvol *vol, char *path, char *type, char *creator)
{
  CatKeyRec key;
  CatDataRec data;
  long id, parid;
  char name[HFS_MAX_FLEN + 1];
  unsigned char record[HFS_CATRECMAXLEN];
  int found, i, reclen;

  if (v_getvol(&vol) < 0)
    return -1;

  found = v_resolve(&vol, path, &data, &parid, name, 0);
  if (found < 0 || parid == 0)
    return -1;
  else if (found)
    {
      ERROR(EEXIST, 0);
      return -1;
    }

  if (parid == HFS_CNID_ROOTPAR)
    {
      ERROR(EINVAL, 0);
      return -1;
    }

  if (vol->flags & HFS_READONLY)
    {
      ERROR(EROFS, 0);
      return -1;
    }

  /* create file `name' in parent `parid' */

  if (bt_space(&vol->cat, 1) < 0)
    return -1;

  id = vol->mdb.drNxtCNID++;
  vol->flags |= HFS_UPDATE_MDB;

  /* create file record */

  data.cdrType   = cdrFilRec;
  data.cdrResrv2 = 0;

  data.u.fil.filFlags = 0;
  data.u.fil.filTyp   = 0;

  memset(&data.u.fil.filUsrWds, 0, sizeof(data.u.fil.filUsrWds));

  data.u.fil.filUsrWds.fdType    = d_getl((unsigned char *) type);
  data.u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) creator);

  data.u.fil.filFlNum  = id;
  data.u.fil.filStBlk  = 0;
  data.u.fil.filLgLen  = 0;
  data.u.fil.filPyLen  = 0;
  data.u.fil.filRStBlk = 0;
  data.u.fil.filRLgLen = 0;
  data.u.fil.filRPyLen = 0;
  data.u.fil.filCrDat  = d_tomtime(/*time*/(0));
  data.u.fil.filMdDat  = data.u.fil.filCrDat;
  data.u.fil.filBkDat  = 0;

  memset(&data.u.fil.filFndrInfo, 0, sizeof(data.u.fil.filFndrInfo));

  data.u.fil.filClpSize = 0;

  for (i = 0; i < 3; ++i)
    {
      data.u.fil.filExtRec[i].xdrStABN     = 0;
      data.u.fil.filExtRec[i].xdrNumABlks  = 0;

      data.u.fil.filRExtRec[i].xdrStABN    = 0;
      data.u.fil.filRExtRec[i].xdrNumABlks = 0;
    }

  data.u.fil.filResrv = 0;

  r_makecatkey(&key, parid, name);
  r_packcatkey(&key, record, &reclen);
  r_packcatdata(&data, HFS_RECDATA(record), &reclen);

  if (bt_insert(&vol->cat, record, reclen) < 0 ||
      v_adjvalence(vol, parid, 0, 1) < 0)
    return -1;

  return 0;
}
Example #8
0
/*
 * NAME:	hfs->write()
 * DESCRIPTION:	write to an open file
 */
long hfs_write(hfsfile *file, void *buf, unsigned long len)
{
  unsigned long *lglen, *pylen, count;
  unsigned char *ptr = buf;

  if (file->vol->flags & HFS_READONLY)
    {
      ERROR(EROFS, 0);
      return -1;
    }

  f_getptrs(file, &lglen, &pylen, 0);

  count = len;

  /* set flag to update (at least) the modification time */

  if (count)
    {
      file->cat.u.fil.filMdDat = d_tomtime(/*time*/(0));
      file->flags |= HFS_UPDATE_CATREC;
    }

  while (count)
    {
      block b;
      unsigned long bnum, offs, chunk;

      bnum  = file->pos / HFS_BLOCKSZ;
      offs  = file->pos % HFS_BLOCKSZ;

      chunk = HFS_BLOCKSZ - offs;
      if (chunk > count)
	chunk = count;

      if (file->pos + chunk > *pylen)
	{
	  if (bt_space(&file->vol->ext, 1) < 0 ||
	      f_alloc(file) < 0)
	    return -1;
	}

      if (offs > 0 || chunk < HFS_BLOCKSZ)
	{
	  if (f_getblock(file, bnum, &b) < 0)
	    return -1;
	}

      memcpy(b + offs, ptr, chunk);
      ptr += chunk;

      if (f_putblock(file, bnum, &b) < 0)
	return -1;

      file->pos += chunk;
      count     -= chunk;

      if (file->pos > *lglen)
	*lglen = file->pos;
    }

  return len;
}