Beispiel #1
0
/**
 * ntfs_td_list_entry
 * FIXME: Should we print errors as we go along? (AIA)
 */
static int ntfs_td_list_entry(  struct ntfs_dir_struct *ls, const ntfschar *name, 
		const int name_len, const int name_type, const s64 pos,
		const MFT_REF mref, const unsigned dt_type)
{
  int result = 0;
  char *filename;
  ntfs_inode *ni;
  ntfs_attr_search_ctx *ctx_si = NULL;
  file_info_t *new_file=NULL;
  /* Keep FILE_NAME_WIN32 and FILE_NAME_POSIX */
  if ((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_DOS)
    return 0;

  filename = (char *)calloc (1, MAX_PATH);
  if (!filename)
  {
    log_critical("ntfs_td_list_entry calloc failed\n");
    return -1;
  }

#ifdef HAVE_ICONV
  if (ntfs_ucstoutf8(ls->cd, name, name_len, &filename, MAX_PATH) < 0 &&
      ntfs_ucstombs (name, name_len, &filename, MAX_PATH) < 0) {
    log_error("Cannot represent filename in current locale.\n");
    goto freefn;
  }
#else
  if (ntfs_ucstombs (name, name_len, &filename, MAX_PATH) < 0) {
    log_error("Cannot represent filename in current locale.\n");
    goto freefn;
  }
#endif

  result = 0;					/* These are successful */
  if ((ls->dir_data->param & FLAG_LIST_SYSTEM)!=FLAG_LIST_SYSTEM &&
      MREF(mref) < FILE_first_user && filename[0] == '$')	/* Hide system file */
      goto freefn;
  result = -1;				/* Everything else is bad */

  ni = ntfs_inode_open(ls->vol, mref);
  if (!ni)
    goto freefn;
  new_file=(file_info_t*)MALLOC(sizeof(*new_file));
  new_file->status=0;
  new_file->st_ino=MREF(mref);
  new_file->st_uid=0;
  new_file->st_gid=0;

  ctx_si = ntfs_attr_get_search_ctx(ni, ni->mrec);
  if (ctx_si)
  {
    if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, CASE_SENSITIVE, 0, NULL, 0, ctx_si)==0)
    {
      const ATTR_RECORD *attr = ctx_si->attr;
      const STANDARD_INFORMATION *si = (const STANDARD_INFORMATION*)((const char*)attr +
	  le16_to_cpu(attr->value_offset));
      if(si)
      {
	new_file->td_atime=td_ntfs2utc(sle64_to_cpu(si->last_access_time));
	new_file->td_mtime=td_ntfs2utc(sle64_to_cpu(si->last_data_change_time));
	new_file->td_ctime=td_ntfs2utc(sle64_to_cpu(si->creation_time));
      }
    }
    ntfs_attr_put_search_ctx(ctx_si);
  }
  {
    ATTR_RECORD *rec;
    int first=1;
    ntfs_attr_search_ctx *ctx = NULL;
    if (dt_type == NTFS_DT_DIR)
    {
      new_file->name=strdup(filename);
      new_file->st_mode = LINUX_S_IFDIR| LINUX_S_IRUGO | LINUX_S_IXUGO;
      new_file->st_size=0;
      td_list_add_tail(&new_file->list, &ls->dir_list->list);
      first=0;
    }
    ctx = ntfs_attr_get_search_ctx(ni, ni->mrec);
    /* A file has always an unnamed date stream and
     * may have named alternate data streams (ADS) */
    while((rec = find_attribute(AT_DATA, ctx)))
    {
      const s64 filesize = ntfs_get_attribute_value_length(ctx->attr);
      if(rec->name_length &&
	  (ls->dir_data->param & FLAG_LIST_ADS)!=FLAG_LIST_ADS)
	continue;
      if(first==0)
      {
	const file_info_t *old_file=new_file;
	new_file=(file_info_t *)MALLOC(sizeof(*new_file));
	memcpy(new_file, old_file, sizeof(*new_file));
      }
      new_file->st_mode = LINUX_S_IFREG | LINUX_S_IRUGO;
      new_file->st_size=filesize;
      if (rec->name_length)
      {
	char *stream_name=NULL;
	new_file->status=FILE_STATUS_ADS;
	new_file->name = (char *)MALLOC(MAX_PATH);
	if (ntfs_ucstombs((ntfschar *) ((char *) rec + le16_to_cpu(rec->name_offset)),
	      rec->name_length, &stream_name, 0) < 0)
	{
	  log_error("ERROR: Cannot translate name into current locale.\n");
	  snprintf(new_file->name, MAX_PATH, "%s:???", filename);
	}
	else
	{
	  snprintf(new_file->name, MAX_PATH, "%s:%s", filename, stream_name);
	}
	free(stream_name);
      }
      else
      {
	new_file->name=strdup(filename);
      }
      td_list_add_tail(&new_file->list, &ls->dir_list->list);
      first=0;
    }
    ntfs_attr_put_search_ctx(ctx);
    if(first)
    {
      free(new_file);
    }
  }

  result = 0;
  /* close the inode. */
  ntfs_inode_close(ni);
freefn:
  free (filename);
  return result;
}
Beispiel #2
0
/**
 * ntfs_inode_open - open an inode ready for access
 * @vol:	volume to get the inode from
 * @mref:	inode number / mft record number to open
 *
 * Allocate an ntfs_inode structure and initialize it for the given inode
 * specified by @mref. @mref specifies the inode number / mft record to read,
 * including the sequence number, which can be 0 if no sequence number checking
 * is to be performed.
 *
 * Then, allocate a buffer for the mft record, read the mft record from the
 * volume @vol, and attach it to the ntfs_inode structure (->mrec). The
 * mft record is mst deprotected and sanity checked for validity and we abort
 * if deprotection or checks fail.
 *
 * Finally, search for an attribute list attribute in the mft record and if one
 * is found, load the attribute list attribute value and attach it to the
 * ntfs_inode structure (->attr_list). Also set the NI_AttrList bit to indicate
 * this.
 *
 * Return a pointer to the ntfs_inode structure on success or NULL on error,
 * with errno set to the error code.
 */
ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
{
	s64 l;
	ntfs_inode *ni = NULL;
	ntfs_attr_search_ctx *ctx;
	STANDARD_INFORMATION *std_info;
	le32 lthle;
	int olderrno;

	ntfs_log_enter("Entering for inode %lld\n", (long long)MREF(mref));
	if (!vol) {
		errno = EINVAL;
		goto out;
	}
	ni = __ntfs_inode_allocate(vol);
	if (!ni)
		goto out;
	if (ntfs_file_record_read(vol, mref, &ni->mrec, NULL))
		goto err_out;
	if (!(ni->mrec->flags & MFT_RECORD_IN_USE)) {
		errno = ENOENT;
		goto err_out;
	}
	ni->mft_no = MREF(mref);
	ctx = ntfs_attr_get_search_ctx(ni, NULL);
	if (!ctx)
		goto err_out;
	/* Receive some basic information about inode. */
	if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED,
				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
		if (!ni->mrec->base_mft_record)
			ntfs_log_perror("No STANDARD_INFORMATION in base record"
					" %lld", (long long)MREF(mref));
		goto put_err_out;
	}
	std_info = (STANDARD_INFORMATION *)((u8 *)ctx->attr +
			le16_to_cpu(ctx->attr->value_offset));
	ni->flags = std_info->file_attributes;
	ni->creation_time = ntfs2utc(std_info->creation_time);
	ni->last_data_change_time = ntfs2utc(std_info->last_data_change_time);
	ni->last_mft_change_time = ntfs2utc(std_info->last_mft_change_time);
	ni->last_access_time = ntfs2utc(std_info->last_access_time);
  		/* JPA insert v3 extensions if present */
                /* length may be seen as 72 (v1.x) or 96 (v3.x) */
	lthle = ctx->attr->length;
	if (le32_to_cpu(lthle) > sizeof(STANDARD_INFORMATION)) {
		set_nino_flag(ni, v3_Extensions);
		ni->owner_id = std_info->owner_id;
		ni->security_id = std_info->security_id;
		ni->quota_charged = std_info->quota_charged;
		ni->usn = std_info->usn;
	} else {
		clear_nino_flag(ni, v3_Extensions);
		ni->owner_id = 0;
		ni->security_id = 0;
	}
	/* Set attribute list information. */
	olderrno = errno;
	if (ntfs_attr_lookup(AT_ATTRIBUTE_LIST, AT_UNNAMED, 0, 0, 0, NULL, 0,
			ctx)) {
		if (errno != ENOENT)
			goto put_err_out;
		/* Attribute list attribute does not present. */
		/* restore previous errno to avoid misinterpretation */
		errno = olderrno;
		goto get_size;
	}
	NInoSetAttrList(ni);
	l = ntfs_get_attribute_value_length(ctx->attr);
	if (!l)
		goto put_err_out;
	if (l > 0x40000) {
		errno = EIO;
		ntfs_log_perror("Too large attrlist attribute (%lld), inode "
				"%lld", (long long)l, (long long)MREF(mref));
		goto put_err_out;
	}
	ni->attr_list_size = l;
	ni->attr_list = ntfs_malloc(ni->attr_list_size);
	if (!ni->attr_list)
		goto put_err_out;
	l = ntfs_get_attribute_value(vol, ctx->attr, ni->attr_list);
	if (!l)
		goto put_err_out;
	if (l != ni->attr_list_size) {
		errno = EIO;
		ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
				"%lld", (long long)l, ni->attr_list_size,
				(long long)MREF(mref));
		goto put_err_out;
	}
get_size:
	olderrno = errno;
	if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
		if (errno != ENOENT)
			goto put_err_out;
		/* Directory or special file. */
		/* restore previous errno to avoid misinterpretation */
		errno = olderrno;
		ni->data_size = ni->allocated_size = 0;
	} else {
		if (ctx->attr->non_resident) {
			ni->data_size = sle64_to_cpu(ctx->attr->data_size);
			if (ctx->attr->flags &
					(ATTR_IS_COMPRESSED | ATTR_IS_SPARSE))
				ni->allocated_size = sle64_to_cpu(
						ctx->attr->compressed_size);
			else
				ni->allocated_size = sle64_to_cpu(
						ctx->attr->allocated_size);
		} else {
			ni->data_size = le32_to_cpu(ctx->attr->value_length);
			ni->allocated_size = (ni->data_size + 7) & ~7;
		}
	}
	ntfs_attr_put_search_ctx(ctx);
out:
	ntfs_log_leave("\n");
	return ni;

put_err_out:
	ntfs_attr_put_search_ctx(ctx);
err_out:
	__ntfs_inode_release(ni);
	ni = NULL;
	goto out;
}