scrounge.c

来自「磁盘格式解读」· C语言 代码 · 共 659 行 · 第 1/2 页

C
659
字号
        if(g_verifyMode)
        {
          if(compareFileData(ofile, data, length) != 0)
            RETWARNX("verify failed. read file data wrong.");
        }
        else
#endif
          if(write(ofile, data, length) != (int32)length)
            RETWARN("couldn't write data to output file");

        dataSize -= length;
      }

      /* For non resident data it's a bit more involved */
      else
      {
        datarun = ntfsx_attribute_getdatarun(attribdata);
        nonres = (ntfs_attribnonresident*)attrhead;

        /* Allocate a cluster for reading and writing */
        ntfsx_cluster_reserve(&cluster, pi);

        if(ntfsx_datarun_first(datarun))
        {
          do
          {
            /* 
             * In some cases NTFS sloppily leaves many extra
             * data runs mapped for a file, so just cut out 
             * when that's the case 
             */
            if(dataSize == 0)
              break;

            /* Sparse clusters we just write zeros */
            if(datarun->sparse)
            {
              memset(cluster.data, 0, cluster.size);

              for(i = 0; i < datarun->length && dataSize; i++)
              {
                num = cluster.size;

                if(dataSize < 0xFFFFFFFF && num > (uint32)dataSize)
                  num = (uint32)dataSize;

#ifdef _DEBUG
                if(g_verifyMode)
                {
                  if(compareFileData(ofile, cluster.data, num) != 0)
                    RETWARNX("verify failed. read file data wrong.");
                }
                else
#endif
                  if(write(ofile, cluster.data, num) != (int32)num)
                    err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);

                dataSize -= num;
              }
            }

            /* Handle not sparse clusters */
            else
            {
              if(pi->locks)
              {
                /* Add a location lock so any raw scrounging won't do 
                   this cluster later */
                addLocationLock(pi->locks, CLUSTER_TO_SECTOR(*pi, datarun->cluster), 
                      CLUSTER_TO_SECTOR(*pi, datarun->cluster + datarun->length));
              }

              for(i = 0; i < datarun->length && dataSize; i++)
              {
                num = min(cluster.size, (uint32)dataSize);
                dataSector = CLUSTER_TO_SECTOR(*pi, (datarun->cluster + i));

                if(!ntfsx_cluster_read(&cluster, pi, dataSector, pi->device))
                {
                  warn("couldn't read sector from disk");
                  break;
                }

#ifdef _DEBUG
                if(g_verifyMode)
                {
                  if(compareFileData(ofile, cluster.data, num) != 0)
                    RETWARNX("verify failed. read file data wrong.");
                }
                else
#endif
                  if(write(ofile, cluster.data, num) != (int32)num)
                    err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);

                dataSize -= num;
              }
            }
          }
          while(ntfsx_datarun_next(datarun));
        }

        ntfsx_datarun_free(datarun);
        datarun = NULL;
      }

      ntfsx_attribute_free(attribdata);
      attribdata = NULL;

      /* Cut out when there's extra clusters allocated */
      if(dataSize == 0)
        break;
    }

    if(!haddata)
      RETWARNX("invalid mft record. no data attribute found");

		if(dataSize != 0)
      warnx("invalid mft record. couldn't find all data for file");

    /* 
     * Now we write blanks for all the sparse non-inited data 
     * We might be able to just resize the file to the right 
     * size, but let's go the safe way and write out zeros
     */

    if(sparseSize > 0)
    {
      ntfsx_cluster_reserve(&cluster, pi);
      memset(cluster.data, 0, cluster.size);

      while(sparseSize > 0)
      {
        num = cluster.size;

        if(sparseSize < 0xFFFFFFFF && num > (uint32)sparseSize)
          num = (uint32)sparseSize;

#ifdef _DEBUG
        if(g_verifyMode)
        {
          if(compareFileData(ofile, cluster.data, num) != 0)
            RETWARNX("verify failed. read file data wrong.");
        }
        else
#endif
          if(write(ofile, cluster.data, num) != (int32)num)
            err(1, "couldn't write to output file: " FC_PRINTF, basics.filename);

        sparseSize -= num;
      }
    }

    close(ofile);
    ofile = -1;

#ifdef _DEBUG
    if(!g_verifyMode)
#endif
    {
      setFileTime(basics.filename, &(basics.created), 
                &(basics.accessed), &(basics.modified));

      setFileAttributes(basics.filename, basics.flags);
    }
  }

cleanup:
  if(record)
    ntfsx_record_free(record);

  ntfsx_cluster_release(&cluster);

  if(attribdata)
    ntfsx_attribute_free(attribdata);

  if(datarun)
    ntfsx_datarun_free(datarun);

  if(attrenum)
    ntfsx_attrib_enum_free(attrenum);

  if(ofile != -1)
    close(ofile);
}


void scroungeMFT(partitioninfo* pi, ntfsx_mftmap* map)
{
  ntfsx_record* record = NULL;
  uint64 sector;
  filebasics basics;
  ntfs_recordheader* header;

  /* Try and find the MFT at the given location */
  sector = pi->mft + pi->first;

  if(sector >= pi->end)
    errx(2, "invalid mft. past end of partition");

  record = ntfsx_record_alloc(pi);

  /* Read the MFT record */
	if(!ntfsx_record_read(record, sector, pi->device))
		err(1, "couldn't read mft");

  header = ntfsx_record_header(record);
  ASSERT(header);

  if(!(header->flags & kNTFS_RecFlagUse))
    errx(2, "invalid mft. marked as not in use");

  /* Load the MFT data runs */

  if(!ntfsx_mftmap_load(map, record, pi->device))
    err(1, "error reading in mft");

  /* Try and get a file name out of the header */

  processRecordFileBasics(pi, record, &basics);

  if(fcscmp(basics.filename, kNTFS_MFTName))
    errx(2, "invalid mft. wrong record");

  fprintf(stderr, "[Processing MFT...]\n");

  if(ntfsx_mftmap_length(map) == 0)
    errx(1, "invalid mft. no records in mft");

  ntfsx_record_free(record);
}


void scroungeUsingMFT(partitioninfo* pi)
{
	uint64 numRecords = 0;
	fchar_t dir[MAX_PATH];
  ntfsx_mftmap map;
  uint64 length;
  uint64 sector;
  uint64 i;

  fprintf(stderr, "[Scrounging via MFT...]\n");

	/* Save current directory away */
	fc_getcwd(dir, MAX_PATH);

  /* Get the MFT map ready */
  memset(&map, 0, sizeof(map));
  ntfsx_mftmap_init(&map, pi);
  pi->mftmap = &map;


  /* 
   * Make sure the MFT is actually where they say it is.
   * This also fills in the valid cluster size if needed
   */
  scroungeMFT(pi, &map);
  length = ntfsx_mftmap_length(&map);
 
  for(i = 1; i < length; i ++)
  {
    sector = ntfsx_mftmap_sectorforindex(&map, i);
    if(sector == kInvalidSector)
    {
      warnx("invalid index in mft: %d", i);
      continue;
    }

    /* Process the record */
    processMFTRecord(pi, sector, 0);

  	/* Move to right output directory */
    fc_chdir(dir);
	}

  pi->mftmap = NULL;
}

void scroungeUsingRaw(partitioninfo* pi)
{
  byte buffSec[kSectorSize];
  fchar_t dir[MAX_PATH + 1];
  uint64 sec;
  drivelocks locks;
  int64 pos;
  size_t sz;
  uint32 magic = kNTFS_RecMagic;

  fprintf(stderr, "[Scrounging raw records...]\n");

	/* Save current directory away */
	fc_getcwd(dir, MAX_PATH);

  /* Get the locks ready */
  memset(&locks, 0, sizeof(locks));
  pi->locks = &locks;

	/* Loop through sectors */
	for(sec = pi->first; sec < pi->end; sec++)
	{
    if(checkLocationLock(&locks, sec))
      continue;

  	/* Read	the record */
    pos = SECTOR_TO_BYTES(sec);
    if(lseek64(pi->device, pos, SEEK_SET) == -1)
      errx(1, "can't seek device to sector");

    sz = read(pi->device, buffSec, kSectorSize);
    if(sz == -1 || sz != kSectorSize)
    {
      warn("can't read drive sector");
      continue;
    }

		/* Check beginning of sector for the magic signature */
		if(!memcmp(&magic, &buffSec, sizeof(magic)))
		{
      /* Process the record */
      processMFTRecord(pi, sec, 0);
		}

  	/* Move to right output directory */
    fc_chdir(dir);
	}

  pi->locks = NULL;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?