예제 #1
0
파일: hfs.c 프로젝트: 3a9LL/panda
/*
 * NAME:	hfs->mount()
 * DESCRIPTION:	open an HFS volume; return volume descriptor or 0 (error)
 */
hfsvol *hfs_mount( int os_fd, int pnum)
{
  hfsvol *vol, *check;
  int mode = HFS_MODE_RDONLY;

  /* see if the volume is already mounted */
  for (check = hfs_mounts; check; check = check->next)
    {
      if (check->pnum == pnum && v_same(check, os_fd) == 1)
	{
	    vol = check;
	    goto done;
	}
    }

  vol = ALLOC(hfsvol, 1);
  if (vol == NULL)
    ERROR(ENOMEM, NULL);

  v_init(vol, mode);

  vol->flags |= HFS_VOL_READONLY;
  if( v_open(vol, os_fd) == -1 )
	  goto fail;

  /* mount the volume */

  if (v_geometry(vol, pnum) == -1 ||
      v_mount(vol) == -1)
    goto fail;

  /* add to linked list of volumes */

  vol->prev = NULL;
  vol->next = hfs_mounts;

  if (hfs_mounts)
    hfs_mounts->prev = vol;

  hfs_mounts = vol;

done:
  ++vol->refs;
  curvol = vol;

  return vol;

fail:
  if (vol)
    {
      v_close(vol);
      FREE(vol);
    }

  return NULL;
}
예제 #2
0
파일: hfs.c 프로젝트: HankG/ciderpress
/*
 * NAME:	hfs_callback_open()
 * DESCRIPTION:	open an HFS volume; return volume descriptor or 0 (error)
 */
hfsvol* hfs_callback_open(oscallback func, void* cookie, int mode)
{
  hfsvol *vol;

  vol = ALLOC(hfsvol, 1);
  if (vol == 0)
    ERROR(ENOMEM, 0);

  v_init(vol, mode);

  /* open the medium */

  switch (mode & HFS_MODE_MASK)
    {
    case HFS_MODE_RDWR:
    case HFS_MODE_ANY:
	break;

    case HFS_MODE_RDONLY:
    default:
      vol->flags |= HFS_VOL_READONLY;
    }

  /* set up vol->priv */
  v_callback_open(vol, func, cookie);


  /* mount the volume */

  if (v_geometry(vol, 0 /*we don't see partition map*/) == -1 ||
      v_mount(vol) == -1)
    goto fail;

  assert(func != 0);
  assert(cookie != 0);

/*done*/
  ++vol->refs;

  return vol;

fail:
  if (vol)
    {
      v_close(vol);
      FREE(vol);
    }

  return 0;
}
예제 #3
0
파일: hfs.c 프로젝트: HankG/ciderpress
/*
 * NAME:	hfs->zero()
 * DESCRIPTION:	initialize medium with new/empty DDR and partition map
 */
int hfs_zero(const char *path, unsigned int maxparts, unsigned long *blocks)
{
  hfsvol vol;

  v_init(&vol, HFS_OPT_NOCACHE);

  if (maxparts < 1)
    ERROR(EINVAL, "must allow at least 1 partition");

  if (v_open(&vol, path, HFS_MODE_RDWR) == -1 ||
      v_geometry(&vol, 0) == -1)
    goto fail;

  if (m_zeroddr(&vol) == -1 ||
      m_zeropm(&vol, 1 + maxparts) == -1)
    goto fail;

  if (blocks)
    {
      Partition map;
      int found;

      found = m_findpmentry(&vol, "Apple_Free", &map, 0);
      if (found == -1)
	goto fail;

      if (! found)
	ERROR(EIO, "unable to determine free partition space");

      *blocks = map.pmPartBlkCnt;
    }

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

  return 0;

fail:
  v_close(&vol);
  return -1;
}
예제 #4
0
파일: main.c 프로젝트: andyvand/fusehfs
/*
 * NAME:	main()
 * DESCRIPTION:	program entry
 */
int main(int argc, char *argv[])
{
  char *path;
  int nparts, pnum, result;
  hfsvol vol;

  suid_init();

  if (argc == 2)
    {
      if (strcmp(argv[1], "--version") == 0)
	{
	  printf("%s - %s\n", hfsutils_version, hfsutils_copyright);
	  printf("`%s --license' for licensing information.\n", argv[0]);
	  return 0;
	}
      else if (strcmp(argv[1], "--license") == 0)
	{
	  printf("\n%s", hfsutils_license);
	  return 0;
	}
    }

  options = HFSCK_REPAIR;

  while (1)
    {
      int opt;

      opt = getopt(argc, argv, "vna");
      if (opt == EOF)
	break;

      switch (opt)
	{
	case '?':
	  return usage(argv);

	case 'v':
	  options |= HFSCK_VERBOSE;
	  break;

	case 'n':
	  options &= ~HFSCK_REPAIR;
	  break;

	case 'a':
	  options |= HFSCK_YES;
	  break;
	}
    }

  if (argc - optind < 1 ||
      argc - optind > 2)
    return usage(argv);

  path = argv[optind];

  suid_enable();
  nparts = hfs_nparts(path);
  suid_disable();

  if (nparts == 0)
    {
      fprintf(stderr, "%s: partitioned medium contains no HFS partitions\n",
	      argv[0]);
      return 1;
    }

  if (argc - optind == 2)
    {
      pnum = atoi(argv[optind + 1]);

      if (pnum < 0)
	{
	  fprintf(stderr, "%s: invalid partition number\n", argv[0]);
	  return 1;
	}

      if (nparts == -1 && pnum > 0)
	{
	  fprintf(stderr, "%s: warning: ignoring partition number for"
		  " non-partitioned medium\n", argv[0]);
	  pnum = 0;
	}
      else if (nparts > 0 && pnum == 0)
	{
	  fprintf(stderr, "%s: cannot specify whole medium"
		  " (has %d partition%s)\n", argv[0], nparts,
		  nparts == 1 ? "" : "s");
	  return 1;
	}
      else if (nparts > 0 && pnum > nparts)
	{
	  fprintf(stderr, "%s: invalid partition number (only %d available)\n",
		  argv[0], nparts);
	  return 1;
	}
    }
  else
    {
      if (nparts > 1)
	{
	  fprintf(stderr, "%s: must specify partition number (%d available)\n",
		  argv[0], nparts);
	  return 1;
	}
      else if (nparts == -1)
	pnum = 0;
      else
	pnum = 1;
    }

  v_init(&vol, HFS_OPT_NOCACHE);

  if (REPAIR)
    {
      suid_enable();
      result = v_open(&vol, path, HFS_MODE_RDWR);
      suid_disable();

      if (result == -1)
	{
	  vol.flags |= HFS_VOL_READONLY;

	  suid_enable();
	  result = v_open(&vol, path, HFS_MODE_RDONLY);
	  suid_disable();
	}
    }

  if (result == -1)
    {
      perror(path);
      return 1;
    }

  if (REPAIR && (vol.flags & HFS_VOL_READONLY))
    {
      fprintf(stderr, "%s: warning: %s not writable; cannot repair\n",
	      argv[0], path);

      options &= ~HFSCK_REPAIR;
    }

  if (v_geometry(&vol, pnum) == -1 ||
      l_getmdb(&vol, &vol.mdb, 0) == -1)
    {
      perror(path);
      v_close(&vol);
      return 1;
    }

  result = hfsck(&vol);

  vol.flags |= HFS_VOL_MOUNTED;

  if (v_close(&vol) == -1)
    {
      perror("closing volume");
      return 1;
    }

  return result;
}
예제 #5
0
파일: hfs.c 프로젝트: HankG/ciderpress
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;
}
예제 #6
0
파일: hfs.c 프로젝트: HankG/ciderpress
/*
 * NAME:	hfs->mount()
 * DESCRIPTION:	open an HFS volume; return volume descriptor or 0 (error)
 */
hfsvol *hfs_mount(const char *path, int pnum, int mode)
{
  hfsvol *vol, *check;

  /* see if the volume is already mounted */

  for (check = hfs_mounts; check; check = check->next)
    {
      if (check->pnum == pnum && v_same(check, path) == 1)
	{
	  /* verify compatible read/write mode */

	  if (((check->flags & HFS_VOL_READONLY) &&
	       ! (mode & HFS_MODE_RDWR)) ||
	      (! (check->flags & HFS_VOL_READONLY) &&
	       (mode & (HFS_MODE_RDWR | HFS_MODE_ANY))))
	    {
	      vol = check;
	      goto done;
	    }
	}
    }

  vol = ALLOC(hfsvol, 1);
  if (vol == 0)
    ERROR(ENOMEM, 0);

  v_init(vol, mode);

  /* open the medium */

  switch (mode & HFS_MODE_MASK)
    {
    case HFS_MODE_RDWR:
    case HFS_MODE_ANY:
      if (v_open(vol, path, HFS_MODE_RDWR) != -1)
	break;

      if ((mode & HFS_MODE_MASK) == HFS_MODE_RDWR)
	goto fail;

    case HFS_MODE_RDONLY:
    default:
      vol->flags |= HFS_VOL_READONLY;

      if (v_open(vol, path, HFS_MODE_RDONLY) == -1)
	goto fail;
    }

  /* mount the volume */

  if (v_geometry(vol, pnum) == -1 ||
      v_mount(vol) == -1)
    goto fail;

  /* add to linked list of volumes */

  vol->prev = 0;
  vol->next = hfs_mounts;

  if (hfs_mounts)
    hfs_mounts->prev = vol;

  hfs_mounts = vol;

done:
  ++vol->refs;
  curvol = vol;

  return vol;

fail:
  if (vol)
    {
      v_close(vol);
      FREE(vol);
    }

  return 0;
}