Exemplo n.º 1
0
static ntfs_index_context *open_reparse_index(ntfs_volume *vol)
{
	u64 inum;
	ntfs_inode *ni;
	ntfs_inode *dir_ni;
	ntfs_index_context *xr;

		/* do not use path_name_to inode - could reopen root */
	dir_ni = ntfs_inode_open(vol, FILE_Extend);
	ni = (ntfs_inode*)NULL;
	if (dir_ni) {
		inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$Reparse");
		if (inum != (u64)-1)
			ni = ntfs_inode_open(vol, inum);
		ntfs_inode_close(dir_ni);
	}
	if (ni) {
		xr = ntfs_index_ctx_get(ni, reparse_index_name, 2);
		if (!xr) {
			ntfs_inode_close(ni);
		}
	} else
		xr = (ntfs_index_context*)NULL;
	return (xr);
}
Exemplo n.º 2
0
static ntfs_index_context *open_object_id_index(ntfs_volume *vol)
{
	u64 inum;
	ntfs_inode *ni;
	ntfs_inode *dir_ni;
	ntfs_index_context *xo;

		/* do not use path_name_to inode - could reopen root */
	dir_ni = ntfs_inode_open(vol, FILE_Extend);
	ni = (ntfs_inode*)NULL;
	if (dir_ni) {
		inum = ntfs_inode_lookup_by_mbsname(dir_ni,"$ObjId");
		if (inum != (u64)-1)
			ni = ntfs_inode_open(vol, inum);
		ntfs_inode_close(dir_ni);
	}
	if (ni) {
		xo = ntfs_index_ctx_get(ni, objid_index_name, 2);
		if (!xo) {
			ntfs_inode_close(ni);
		}
	} else
		xo = (ntfs_index_context*)NULL;
	return (xo);
}
Exemplo n.º 3
0
static char *search_absolute(ntfs_volume *vol, ntfschar *path,
				int count, BOOL isdir)
{
	ntfs_inode *ni;
	u64 inum;
	char *target;
	int start;
	int len;

	target = (char*)NULL; /* default return */
	ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
	if (ni) {
		start = 0;
		/*
		 * Examine and translate the path, until we reach either
		 *  - the end,
		 *  - an unknown item
		 *  - a non-directory
		 *  - another reparse point,
		 * A reparse point is not dereferenced, it will be
		 * examined later when the translated path is dereferenced,
		 * however the final part of the path will not be adjusted
		 * to correct case.
		 */
		do {
			len = 0;
			while (((start + len) < count)
			    && (path[start + len] != const_cpu_to_le16('\\')))
				len++;
			inum = ntfs_fix_file_name(ni, &path[start], len);
			ntfs_inode_close(ni);
			ni = (ntfs_inode*)NULL;
			if (inum != (u64)-1) {
				inum = MREF(inum);
				ni = ntfs_inode_open(vol, inum);
				start += len;
				if (start < count)
					path[start++] = const_cpu_to_le16('/');
			}
		} while (ni
		    && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
		    && !(ni->flags & FILE_ATTR_REPARSE_POINT)
		    && (start < count));
	if (ni
	    && ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)
		|| (ni->flags & FILE_ATTR_REPARSE_POINT)))
		if (ntfs_ucstombs(path, count, &target, 0) < 0) {
			if (target) {
				free(target);
				target = (char*)NULL;
			}
		}
	if (ni)
		ntfs_inode_close(ni);
	}
	return (target);
}
Exemplo n.º 4
0
static int ntfsrec_cpz_directory_visitor(struct ntfsrec_copy *state, const ntfschar *name, const int name_len, const int name_type, const s64 pos, const MFT_REF mref, const unsigned dt_type) {
    char *local_name = NULL;
    ntfs_inode *inode;
    
    NR_UNUSED(pos);
    
    if ((name_type & FILE_NAME_WIN32_AND_DOS) == FILE_NAME_DOS) {
        return 0;
    }
    
    if (ntfs_ucstombs(name, name_len, &local_name, MAX_PATH_LENGTH) < 0) {
        puts("Error: this filename can't be represented in your locale.");
        return 0;
    }
    
    if (dt_type & NTFS_DT_DIR) {
        ntfs_inode *dir_inode;
        
        if (strcmp(local_name, ".") == 0 || strcmp(local_name, "..") == 0 ||
            strcmp(local_name, "./") == 0 || strcmp(local_name, "../") == 0) {
            free(local_name);
            
            return 0;
        }
        
        dir_inode = ntfs_inode_open(state->volume, mref);
        
        if (dir_inode == NULL) {
            printf("Error: couldn't open folder %s\n", local_name);
            free(local_name);
            return 0;
        }
        
        ntfsrec_recurse_directory(state, dir_inode, local_name);
        
        ntfs_inode_close(dir_inode);
        free(local_name);
        return 0;
    }
    
    inode = ntfs_inode_open(state->volume, mref);
    
    if (inode != NULL) {
        ntfsrec_emit_file(state, inode, local_name);
        ntfs_inode_close(inode);
    } else {
        printf("Error: couldn't open file %s\n", local_name);
    }
    
    free(local_name);
    
    return 0;
}
Exemplo n.º 5
0
/* Restore the DOS name of the @dentry.
 * This closes both @ni and @dir_ni.
 * If either is NULL, then they are opened temporarily.  */
static int
ntfs_3g_restore_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
			 struct wim_dentry *dentry, ntfs_volume *vol)
{
	int ret;
	const char *dos_name;
	size_t dos_name_nbytes;

	/* Note: ntfs_set_ntfs_dos_name() closes both inodes (even if it fails).
	 * And it takes in a multibyte string, even though it translates it to
	 * UTF-16LE internally... which is annoying because we currently have
	 * the UTF-16LE string but not the multibyte string.  */

	ret = utf16le_get_tstr(dentry->short_name, dentry->short_name_nbytes,
			       &dos_name, &dos_name_nbytes);
	if (ret)
		goto out_close;

	if (!dir_ni)
		dir_ni = ntfs_inode_open(vol, dentry->d_parent->d_inode->i_mft_no);
	if (!ni)
		ni = ntfs_inode_open(vol, dentry->d_inode->i_mft_no);
	if (dir_ni && ni) {
		ret = ntfs_set_ntfs_dos_name(ni, dir_ni,
					     dos_name, dos_name_nbytes, 0);
		dir_ni = NULL;
		ni = NULL;
	} else {
		ret = -1;
	}
	utf16le_put_tstr(dos_name);
	if (ret) {
		ERROR_WITH_ERRNO("Failed to set DOS name of \"%s\" in NTFS "
				 "volume", dentry_full_path(dentry));
		ret = WIMLIB_ERR_SET_SHORT_NAME;
		goto out_close;
	}

	/* Unlike most other NTFS-3g functions, ntfs_set_ntfs_dos_name()
	 * changes the directory's last modification timestamp...
	 * Change it back.  */
	return ntfs_3g_restore_timestamps(vol, dentry->d_parent->d_inode);

out_close:
	/* ntfs_inode_close() can take a NULL argument, but it's probably best
	 * not to rely on this behavior.  */
	if (ni)
		ntfs_inode_close(ni);
	if (dir_ni)
		ntfs_inode_close(dir_ni);
	return ret;
}
Exemplo n.º 6
0
static int ntfs_dir(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const unsigned long int cluster, file_info_t *dir_list)
{
  ntfs_inode *inode;
  s64 pos;
  struct ntfs_dir_struct *ls=(struct ntfs_dir_struct*)dir_data->private_dir_data;
  ls->dir_list=dir_list;

  inode = ntfs_inode_open (ls->vol, cluster);
  if (!inode) {
    log_error("ntfs_dir: ntfs_inode_open failed\n");
    return -1;
  }

  /*
   * We now are at the final path component.  If it is a file just
   * list it.  If it is a directory, list its contents.
   */
  pos = 0;
  if (inode->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
    if(ntfs_readdir(inode, &pos, ls, (ntfs_filldir_t)ntfs_td_list_entry)<0)
    {
      log_error("ntfs_readdir failed for cluster %lu: %s\n", cluster,
	  strerror(errno));
    }
  }
  else
    log_critical("ntfs_readdir BUG not MFT_RECORD_IS_DIRECTORY\n");
  /* Finished with the inode; release it. */
  ntfs_inode_close(inode);
  td_list_sort(&dir_list->list, filesort);
  return 0;
}
Exemplo n.º 7
0
status_t
fs_closedir(fs_volume *_vol, fs_vnode *_node, void *cookie)
{
	nspace		*ns = (nspace*)_vol->private_volume;
	vnode		*node = (vnode*)_node->private_node;
	int			result = B_NO_ERROR;
	ntfs_inode	*ni = NULL;

	LOCK_VOL(ns);

	TRACE("fs_closedir - ENTER\n");

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
			result = ENOENT;
			goto exit;
	}

	fs_ntfs_update_times(_vol, ni, NTFS_UPDATE_ATIME);

exit:
	if (ni)
		ntfs_inode_close(ni);

	TRACE("fs_closedir - EXIT\n");

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 8
0
status_t
fs_rstat(fs_volume *_vol, fs_vnode *_node, struct stat *stbuf)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *node = (vnode*)_node->private_node;
	ntfs_inode *ni = NULL;
	ntfs_attr *na;
	status_t result = B_NO_ERROR;

	LOCK_VOL(ns);

	ERRPRINT("fs_rstat - ENTER:\n");

	if (ns == NULL || node == NULL ||stbuf == NULL) {
		result = ENOENT;
		goto exit;
	}

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = ENOENT;
		goto exit;
	}
	if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) {
		// Directory
		stbuf->st_mode = FS_DIR_MODE;
		na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
		if (na) {
			stbuf->st_size = na->data_size;
			stbuf->st_blocks = na->allocated_size >> 9;
			ntfs_attr_close(na);
		}
		stbuf->st_nlink = 1;
	} else {
Exemplo n.º 9
0
static char *search_absolute(ntfs_volume *vol, ntfschar *path,
				int count, BOOL isdir)
{
	ntfs_inode *ni;
	u64 inum;
	char *target;
	int start;
	int len;

	target = (char*)NULL; /* default return */
	ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
	if (ni) {
		start = 0;
		do {
			len = 0;
			while (((start + len) < count)
			    && (path[start + len] != const_cpu_to_le16('\\')))
				len++;
			inum = ntfs_fix_file_name(ni, &path[start], len);
			ntfs_inode_close(ni);
			ni = (ntfs_inode*)NULL;
			if (inum != (u64)-1) {
				inum = MREF(inum);
				ni = ntfs_inode_open(vol, inum);
				start += len;
				if (start < count)
					path[start++] = const_cpu_to_le16('/');
			}
		} while (ni
		    && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
		    && (start < count));
	if (ni
	    && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir))
		if (ntfs_ucstombs(path, count, &target, 0) < 0) {
			if (target) {
				free(target);
				target = (char*)NULL;
			}
		}
	if (ni)
		ntfs_inode_close(ni);
	}
	return (target);
}
Exemplo n.º 10
0
status_t
fs_open_attrib_dir(fs_volume *_vol, fs_vnode *_node, void **_cookie)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *node = (vnode*)_node->private_node;
	attrdircookie *cookie = NULL;
	ntfs_inode *ni = NULL;
	ntfs_attr_search_ctx *ctx = NULL;

	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER\n", __FUNCTION__);

	LOCK_VOL(ns);

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}

	ctx = ntfs_attr_get_search_ctx(ni, NULL);
	if (ctx == NULL) {
		result = errno;
		goto exit;
	}

	cookie = (attrdircookie*)ntfs_calloc(sizeof(attrdircookie));
	if (cookie == NULL) {
		result = ENOMEM;
		goto exit;
	}

	cookie->inode = ni;
	cookie->ctx = ctx;
	ni = NULL;
	ctx = NULL;
	*_cookie = cookie;
	
exit:

	if (ctx)
		ntfs_attr_put_search_ctx(ctx);
	if (ni)
		ntfs_inode_close(ni);
	
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));
	
	UNLOCK_VOL(ns);
	
	return result;
}
Exemplo n.º 11
0
status_t
fs_opendir(fs_volume *_vol, fs_vnode *_node, void** _cookie)
{
	nspace		*ns = (nspace*)_vol->private_volume;
	vnode		*node = (vnode*)_node->private_node;
	dircookie	*cookie = NULL;
	int			result = B_NO_ERROR;
	ntfs_inode	*ni = NULL;

	LOCK_VOL(ns);

	TRACE("fs_opendir - ENTER\n");

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = ENOENT;
		goto exit;
	}

	if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
		result = EMFILE;
		goto exit;
	}

	cookie = (dircookie*)ntfs_calloc(sizeof(dircookie));
	if (cookie != NULL) {
		cookie->pos = 0;
		cookie->ino = 0;
		cookie->readed = 0;
		cookie->last = 0;
		cookie->name[0] = 0;
		cookie->show_sys_files = ns->show_sys_files;
		*_cookie = (void*)cookie;
	} else
		result = ENOMEM;

exit:
	if (ni)
		ntfs_inode_close(ni);

	TRACE("fs_opendir - EXIT\n");

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 12
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char *argv[])
{
	ntfs_volume *vol;
	ntfs_inode *inode;
	ATTR_TYPES attr;
	int result = 1;

	ntfs_log_set_handler(ntfs_log_handler_stderr);

	if (!parse_options(argc, argv))
		return 1;

	utils_set_locale();

	vol = utils_mount_volume(opts.device, MS_RDONLY |
			(opts.force ? MS_RECOVER : 0));
	if (!vol) {
		ntfs_log_perror("ERROR: couldn't mount volume");
		return 1;
	}

	if (opts.inode != -1)
		inode = ntfs_inode_open(vol, opts.inode);
	else
		inode = ntfs_pathname_to_inode(vol, NULL, opts.file);

	if (!inode) {
		ntfs_log_perror("ERROR: Couldn't open inode");
		return 1;
	}

	attr = AT_DATA;
	if (opts.attr != cpu_to_le32(-1))
		attr = opts.attr;

	result = cat(vol, inode, attr, opts.attr_name, opts.attr_name_len);

	ntfs_inode_close(inode);
	ntfs_umount(vol, FALSE);

	return result;
}
Exemplo n.º 13
0
/* Restore the timestamps on the NTFS inode corresponding to @inode.  */
static int
ntfs_3g_restore_timestamps(ntfs_volume *vol, const struct wim_inode *inode)
{
	ntfs_inode *ni;
	int res;

	ni = ntfs_inode_open(vol, inode->i_mft_no);
	if (!ni)
		goto fail;

	res = ntfs_3g_set_timestamps(ni, inode);

	if (ntfs_inode_close(ni) || res)
		goto fail;

	return 0;

fail:
	ERROR_WITH_ERRNO("Failed to update timestamps of \"%s\" in NTFS volume",
			 dentry_full_path(inode_first_extraction_dentry(inode)));
	return WIMLIB_ERR_SET_TIMESTAMPS;
}
Exemplo n.º 14
0
status_t
fs_get_vnode_name(fs_volume *_vol, fs_vnode *_vnode, char *buffer,
	size_t bufferSize)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *node = (vnode*)_vnode->private_node;
	ntfs_inode *ni = NULL;
	status_t result = B_NO_ERROR;

	char path[MAX_PATH];
	char *name;

	LOCK_VOL(ns);

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = ENOENT;
		goto exit;
	}

	if (utils_inode_get_name(ni, path, MAX_PATH) == 0) {
		result = EINVAL;
		goto exit;
	}

	name = strrchr(path, '/');
	name++;

	strlcpy(buffer, name, bufferSize);

exit:
	if (ni)
		ntfs_inode_close(ni);

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 15
0
status_t 
fs_read_attrib_stat(fs_volume *_vol, fs_vnode *_node, void *_cookie,
	struct stat *stat)
{
	nspace *ns = (nspace *)_vol->private_volume;
	vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;	
	status_t result = B_NO_ERROR;	

	LOCK_VOL(ns);

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}
	na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
	if (na == NULL) {
		result = errno;
		goto exit;		
	}

	stat->st_type = cookie->type;
	stat->st_size = na ? na->data_size - sizeof(uint32) : 0;

exit:
	if (na != NULL)
		ntfs_attr_close(na);
	if (ni != NULL)
		ntfs_inode_close(ni);	

	UNLOCK_VOL(ns);
	
	return B_NO_ERROR;
}
Exemplo n.º 16
0
status_t
fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
	int openMode, void **_cookie)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *node = (vnode*)_node->private_node;
	attrcookie *cookie = NULL;
	ntfschar *uname = NULL;
	int ulen;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;
	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER\n", __FUNCTION__);

	LOCK_VOL(ns);

	if (node == NULL) {
		result = EINVAL;
		goto exit;
	}

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}

	// UXA demangling TODO

	// check for EA first... TODO: WRITEME


	// check for a named stream
	if (true) {
		uname = ntfs_calloc(MAX_PATH);
		ulen = ntfs_mbstoucs(name, &uname);
		if (ulen < 0) {
			result = EILSEQ;
			goto exit;
		}

		na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
		if (na) {
			if (openMode & O_TRUNC) {
				if (ntfs_attr_truncate(na, 0))
					result = errno;
			}
		} else {
			result = ENOENT;
			goto exit;
		}
	}


	cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));

	if (cookie != NULL) {
		cookie->omode = openMode;
		*_cookie = (void*)cookie;
		cookie->inode = ni;
		cookie->stream = na;
		ni = NULL;
		na = NULL;
	} else
		result = ENOMEM;

exit:
	if (uname)
		free(uname);

	if (na)
		ntfs_attr_close(na);

	if (ni)
		ntfs_inode_close(ni);

	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 17
0
static char *search_relative(ntfs_inode *ni, ntfschar *path, int count)
{
	char *target = (char*)NULL;
	ntfs_inode *curni;
	ntfs_inode *newni;
	u64 inum;
	int pos;
	int lth;
	BOOL ok;
	BOOL morelinks;
	int max = 32; /* safety */

	pos = 0;
	ok = TRUE;
	morelinks = FALSE;
	curni = ntfs_dir_parent_inode(ni);
		/*
		 * Examine and translate the path, until we reach either
		 *  - the end,
		 *  - an unknown item
		 *  - a non-directory
		 *  - another reparse point,
		 * A reparse point is not dereferenced, it will be
		 * examined later when the translated path is dereferenced,
		 * however the final part of the path will not be adjusted
		 * to correct case.
		 */
	while (curni && ok && !morelinks && (pos < (count - 1)) && --max) {
		if ((count >= (pos + 2))
		    && (path[pos] == const_cpu_to_le16('.'))
		    && (path[pos+1] == const_cpu_to_le16('\\'))) {
			path[1] = const_cpu_to_le16('/');
			pos += 2;
		} else {
			if ((count >= (pos + 3))
			    && (path[pos] == const_cpu_to_le16('.'))
			    &&(path[pos+1] == const_cpu_to_le16('.'))
			    && (path[pos+2] == const_cpu_to_le16('\\'))) {
				path[2] = const_cpu_to_le16('/');
				pos += 3;
				newni = ntfs_dir_parent_inode(curni);
				if (curni != ni)
					ntfs_inode_close(curni);
				curni = newni;
				if (!curni)
					ok = FALSE;
			} else {
				lth = 0;
				while (((pos + lth) < count)
				    && (path[pos + lth] != const_cpu_to_le16('\\')))
					lth++;
				if (lth > 0)
					inum = ntfs_fix_file_name(curni,&path[pos],lth);
				else
					inum = (u64)-1;
				if (!lth
				    || ((curni != ni)
					&& ntfs_inode_close(curni))
				    || (inum == (u64)-1))
					ok = FALSE;
				else {
					curni = ntfs_inode_open(ni->vol, MREF(inum));
					if (!curni)
						ok = FALSE;
					else {
						if (curni->flags & FILE_ATTR_REPARSE_POINT)
							morelinks = TRUE;
						if (ok && ((pos + lth) < count)) {
							path[pos + lth] = const_cpu_to_le16('/');
							pos += lth + 1;
							if (morelinks
							   && ntfs_inode_close(curni))
								ok = FALSE;
						} else {
							pos += lth;
							if (!morelinks
							  && (ni->mrec->flags ^ curni->mrec->flags)
							    & MFT_RECORD_IS_DIRECTORY)
								ok = FALSE;
							if (ntfs_inode_close(curni))
								ok = FALSE;
						}
					}
				}
			}
		}
	}

	if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) {
		free(target); // needed ?
		target = (char*)NULL;
	}
	return (target);
}
Exemplo n.º 18
0
/**
 * main - Begin here
 *
 * Start from here.
 *
 * Return:  0  Success, the program worked
 *	    1  Error, something went wrong
 */
int main(int argc, char *argv[])
{
    u8 *pfx_buf;
    char *password;
    ntfs_rsa_private_key rsa_key;
    ntfs_volume *vol;
    ntfs_inode *inode;
    ntfs_fek *fek;
    unsigned pfx_size;
    int res;
    NTFS_DF_TYPES df_type;
    char thumbprint[NTFS_SHA1_THUMBPRINT_SIZE];

#ifdef DEBUG
    ntfs_log_set_handler(ntfs_log_handler_stderr);
#endif

    if (!parse_options(argc, argv))
        return 1;
    utils_set_locale();

    /* Initialize crypto in ntfs. */
    if (ntfs_crypto_init()) {
        ntfs_log_error("Failed to initialize crypto.  Aborting.\n");
        return 1;
    }
    /* Load the PKCS#12 (.pfx) file containing the user's private key. */
    if (ntfs_pkcs12_load_pfxfile(opts.keyfile, &pfx_buf, &pfx_size)) {
        ntfs_log_error("Failed to load key file.  Aborting.\n");
        ntfs_crypto_deinit();
        return 1;
    }
    /* Ask the user for their password. */
    password = getpass("Enter the password with which the private key was "
                       "encrypted: ");
    if (!password) {
        ntfs_log_perror("Failed to obtain user password");
        free(pfx_buf);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Obtain the user's private RSA key from the key file. */
    rsa_key = ntfs_pkcs12_extract_rsa_key(pfx_buf, pfx_size, password,
                                          thumbprint, sizeof(thumbprint), &df_type);
    /* Destroy the password. */
    memset(password, 0, strlen(password));
    /* No longer need the pfx file contents. */
    free(pfx_buf);
    if (!rsa_key) {
        ntfs_log_error("Failed to extract the private RSA key.\n");
        ntfs_crypto_deinit();
        return 1;
    }
    /* Mount the ntfs volume. */
    vol = utils_mount_volume(opts.device, NTFS_MNT_RDONLY |
                             (opts.force ? NTFS_MNT_RECOVER : 0));
    if (!vol) {
        ntfs_log_error("Failed to mount ntfs volume.  Aborting.\n");
        ntfs_rsa_private_key_release(rsa_key);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Open the encrypted ntfs file. */
    if (opts.inode != -1)
        inode = ntfs_inode_open(vol, opts.inode);
    else
        inode = ntfs_pathname_to_inode(vol, NULL, opts.file);
    if (!inode) {
        ntfs_log_error("Failed to open encrypted file.  Aborting.\n");
        ntfs_umount(vol, FALSE);
        ntfs_rsa_private_key_release(rsa_key);
        ntfs_crypto_deinit();
        return 1;
    }
    /* Obtain the file encryption key of the encrypted file. */
    fek = ntfs_inode_fek_get(inode, rsa_key, thumbprint,
                             sizeof(thumbprint), df_type);
    ntfs_rsa_private_key_release(rsa_key);
    if (fek) {
        res = ntfs_cat_decrypt(inode, fek);
        ntfs_fek_release(fek);
    } else {
        ntfs_log_error("Failed to obtain file encryption key.  "
                       "Aborting.\n");
        res = 1;
    }
    ntfs_inode_close(inode);
    ntfs_umount(vol, FALSE);
    ntfs_crypto_deinit();
    return res;
}
Exemplo n.º 19
0
status_t
fs_remove_attrib(fs_volume *_vol, fs_vnode *_node, const char* name)
{
	nspace *ns = (nspace *)_vol->private_volume;
	vnode *node = (vnode *)_node->private_node;
	char ntfs_attr_name[MAX_PATH]={0};
	ntfschar *uname = NULL;
	int ulen;
	ntfs_inode *ni = NULL;		
	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER - name: [%s]\n", __FUNCTION__, name);
	
	if (ns->flags & B_FS_IS_READONLY) {
		ERROR("ntfs is read-only\n");
		return B_READ_ONLY_DEVICE;
	}

	LOCK_VOL(ns);
	
	if (node == NULL) {
		result = EINVAL;
		goto exit;
	}

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}		
	
	strcat(ntfs_attr_name, kHaikuAttrPrefix);
	strcat(ntfs_attr_name, name);
	
	uname = ntfs_calloc(MAX_PATH);
	ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
	if (ulen < 0) {
		result = EILSEQ;
		goto exit;
	}	
	
	if (ntfs_attr_remove(ni, AT_DATA, uname, ulen)) {
		result = ENOENT;
		goto exit;
	}

	if (!(ni->flags & FILE_ATTR_ARCHIVE)) {
		ni->flags |= FILE_ATTR_ARCHIVE;
		NInoFileNameSetDirty(ni);
	}
	notify_attribute_changed(ns->id, MREF(ni->mft_no), name, B_ATTR_REMOVED);
exit:	
	if (uname != NULL)
		free(uname);

	if (ni != NULL)
		ntfs_inode_close(ni);
		
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
Exemplo n.º 20
0
status_t
fs_write_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
	const void *buffer, size_t *_length)
{
	nspace *ns = (nspace *)_vol->private_volume;
	vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;
	size_t  size = *_length;
	char *attr_name = NULL;
	char *real_name = NULL;
	int total = 0;
	status_t result = B_NO_ERROR;

	TRACE("%s - ENTER  vnode: %d\n", __FUNCTION__, node->vnid);
	
	if (ns->flags & B_FS_IS_READONLY) {		
		return B_READ_ONLY_DEVICE;
	}

	if (pos < 0) {
		*_length = 0;
		return EINVAL;
	}

	LOCK_VOL(ns);

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}
	na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
	if (na == NULL) {
		result = errno;
		goto exit;		
	}		

	pos += sizeof(uint32);

	// it is a named stream
	if (na != NULL) {
		if (cookie->omode & O_APPEND)
			pos = na->data_size;

		if (pos + size > na->data_size) {
			ntfs_mark_free_space_outdated(ns);
			if (ntfs_attr_truncate(na, pos + size))
				size = na->data_size - pos;
			else
				notify_stat_changed(ns->id, MREF(ni->mft_no), B_STAT_SIZE);
		}

		while (size) {
			off_t bytesWritten = ntfs_attr_pwrite(na, pos, size, buffer);
			if (bytesWritten < (s64)size)
				ERROR("%s - ntfs_attr_pwrite returned less bytes than "
					"requested.\n", __FUNCTION__);
			if (bytesWritten <= 0) {
				ERROR("%s - ntfs_attr_pwrite()<=0\n", __FUNCTION__);
				*_length = 0;
				result = EINVAL;
				goto exit;
			}
			size -= bytesWritten;
			pos += bytesWritten;
			total += bytesWritten;
		}

		*_length = total;
	} else {
		*_length = 0;
		result =  EINVAL;
		goto exit;
	}
	
	if (ntfs_ucstombs(na->name, na->name_len, &attr_name, 0) >= 0) {
		if (attr_name != NULL) {
			if(strncmp(attr_name, kHaikuAttrPrefix, strlen(kHaikuAttrPrefix)) !=0 )
				goto exit;
			real_name = attr_name + strlen(kHaikuAttrPrefix);						
			notify_attribute_changed(ns->id, MREF(ni->mft_no),
				real_name, B_ATTR_CHANGED);
			free(attr_name);
		}
	}
		
exit:	
	if (na != NULL)
		ntfs_attr_close(na);
	if (ni != NULL)
		ntfs_inode_close(ni);
		
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
Exemplo n.º 21
0
status_t
fs_readdir(fs_volume *_vol, fs_vnode *_node, void *_cookie, struct dirent *buf,
	size_t bufsize, uint32 *num)
{
	nspace		*ns = (nspace*)_vol->private_volume;
	vnode		*node = (vnode*)_node->private_node;
	dircookie	*cookie = (dircookie*)_cookie;
	uint32 		nameLength = bufsize - sizeof(struct dirent), realLen;
	int 		result = B_NO_ERROR;
	ntfs_inode	*ni = NULL;

	LOCK_VOL(ns);

	TRACE("fs_readdir - ENTER (sizeof(buf)=%d, bufsize=%d, num=%d\n",
		sizeof(buf), bufsize, *num);

	if (!ns || !node || !cookie || !num || bufsize < sizeof(buf)) {
	 	result = EINVAL;
		goto exit;
	}

	if (cookie->readed == 1 || cookie->last == 1) {
		 result = ENOENT;
		 goto exit;
	}

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		ERROR("fs_readdir - dir not opened\n");
		result = ENOENT;
		goto exit;
	}

	result = ntfs_readdir(ni, &cookie->pos, cookie,
		(ntfs_filldir_t)_ntfs_dirent_filler);

	realLen = nameLength > 255 ? 255 : nameLength;
	buf->d_dev = ns->id;
	buf->d_ino = cookie->ino;
	strlcpy(buf->d_name, cookie->name, realLen + 1);
	buf->d_reclen = sizeof(struct dirent) + realLen;

	if (result == 0)
		cookie->last = 1;

	result = B_NO_ERROR;

	TRACE("fs_readdir - FILE: [%s]\n",buf->d_name);

exit:
	if (ni)
		ntfs_inode_close(ni);

	if (result == B_NO_ERROR)
		*num = 1;
	else
		*num = 0;

	if (result == ENOENT)
		result = B_NO_ERROR;

	TRACE("fs_readdir - EXIT result (%s)\n", strerror(result));

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 22
0
status_t
fs_open_attrib(fs_volume *_vol, fs_vnode *_node, const char *name,
	int openMode, void **_cookie)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *node = (vnode*)_node->private_node;
	attrcookie *cookie = NULL;
	ntfschar *uname = NULL;
	int ulen;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;
	status_t result = B_NO_ERROR;
	uint32	type = B_XATTR_TYPE;

	TRACE("%s - ENTER - name: [%s] vnid: %d\n", __FUNCTION__, name,  node->vnid);

	LOCK_VOL(ns);

	if (node == NULL) {
		result = EINVAL;
		goto exit;
	}

	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}

	// UXA demangling TODO

	// check for EA first... TODO: WRITEME


	// check for a named stream
	if (true) {
		char ntfs_attr_name[MAX_PATH] = {0};
		strcat(ntfs_attr_name, kHaikuAttrPrefix);
		strcat(ntfs_attr_name, name);
		
		uname = ntfs_calloc(MAX_PATH);
		ulen = ntfs_mbstoucs(ntfs_attr_name, &uname);
		if (ulen < 0) {
			result = EILSEQ;
			goto exit;
		}

		na = ntfs_attr_open(ni, AT_DATA, uname, ulen);
		if (na != NULL) {
			if (openMode & O_TRUNC) {
				if (ns->flags & B_FS_IS_READONLY) {		
					result = B_READ_ONLY_DEVICE;
					goto exit;
				} else {
					if (ntfs_attr_truncate(na, sizeof(uint32))) {
						result = errno;
						goto exit;
					}
				}
			}
			if (ntfs_attr_pread(na, 0, sizeof(uint32), &type) != sizeof(uint32)) {
				result = errno;
				goto exit;
			}
		} else {
			result = ENOENT;
			goto exit;
		}
	}


	cookie = (attrcookie*)ntfs_calloc(sizeof(attrcookie));

	if (cookie != NULL) {
		cookie->omode = openMode;
		cookie->vnid = node->vnid;
		cookie->uname = uname;
		cookie->uname_len = ulen;
		cookie->type = type;
		*_cookie = (void*)cookie;
		uname = NULL;
	} else
		result = ENOMEM;

exit:
	if (uname != NULL)
		free(uname);

	if (na != NULL)
		ntfs_attr_close(na);

	if (ni != NULL)
		ntfs_inode_close(ni);

	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 23
0
/**
 * ntfs_inode_sync_file_name - update FILE_NAME attributes
 * @ni:		ntfs inode to update FILE_NAME attributes
 *
 * Update all FILE_NAME attributes for inode @ni in the index.
 *
 * Return 0 on success or -1 on error with errno set to the error code.
 */
static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
{
	ntfs_attr_search_ctx *ctx = NULL;
	ntfs_index_context *ictx;
	ntfs_inode *index_ni;
	FILE_NAME_ATTR *fn;
	FILE_NAME_ATTR *fnx;
	REPARSE_POINT *rpp;
	le32 reparse_tag;
	int err = 0;

	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);

	ctx = ntfs_attr_get_search_ctx(ni, NULL);
	if (!ctx) {
		err = errno;
		goto err_out;
	}
	/* Collect the reparse tag, if any */
	reparse_tag = cpu_to_le32(0);
	if (ni->flags & FILE_ATTR_REPARSE_POINT) {
		if (!ntfs_attr_lookup(AT_REPARSE_POINT, NULL,
				0, CASE_SENSITIVE, 0, NULL, 0, ctx)) {
			rpp = (REPARSE_POINT*)((u8 *)ctx->attr +
					le16_to_cpu(ctx->attr->value_offset));
			reparse_tag = rpp->reparse_tag;
		}
		ntfs_attr_reinit_search_ctx(ctx);
	}
	/* Walk through all FILE_NAME attributes and update them. */
	while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
		fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
				le16_to_cpu(ctx->attr->value_offset));
		if (MREF_LE(fn->parent_directory) == ni->mft_no) {
			/*
			 * WARNING: We cheat here and obtain 2 attribute
			 * search contexts for one inode (first we obtained
			 * above, second will be obtained inside
			 * ntfs_index_lookup), it's acceptable for library,
			 * but will deadlock in the kernel.
			 */
			index_ni = ni;
		} else
			if (dir_ni)
				index_ni = dir_ni;
			else
				index_ni = ntfs_inode_open(ni->vol,
					le64_to_cpu(fn->parent_directory));
		if (!index_ni) {
			if (!err)
				err = errno;
			ntfs_log_perror("Failed to open inode %lld with index",
				(long long)le64_to_cpu(fn->parent_directory));
			continue;
		}
		ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
		if (!ictx) {
			if (!err)
				err = errno;
			ntfs_log_perror("Failed to get index ctx, inode %lld",
					(long long)index_ni->mft_no);
			if ((ni != index_ni) && !dir_ni
			    && ntfs_inode_close(index_ni) && !err)
				err = errno;
			continue;
		}
		if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
			if (!err) {
				if (errno == ENOENT)
					err = EIO;
				else
					err = errno;
			}
			ntfs_log_perror("Index lookup failed, inode %lld",
					(long long)index_ni->mft_no);
			ntfs_index_ctx_put(ictx);
			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
				err = errno;
			continue;
		}
		/* Update flags and file size. */
		fnx = (FILE_NAME_ATTR *)ictx->data;
		fnx->file_attributes =
				(fnx->file_attributes & ~FILE_ATTR_VALID_FLAGS) |
				(ni->flags & FILE_ATTR_VALID_FLAGS);
		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
			fnx->data_size = fnx->allocated_size
				= const_cpu_to_le64(0);
		else {
			fnx->allocated_size = cpu_to_sle64(ni->allocated_size);
			fnx->data_size = cpu_to_sle64(ni->data_size);
			/*
			 * The file name record has also to be fixed if some
			 * attribute update implied the unnamed data to be
			 * made non-resident
			 */
			fn->allocated_size = fnx->allocated_size;
		}
			/* update or clear the reparse tag in the index */
		fnx->reparse_point_tag = reparse_tag;
		if (!test_nino_flag(ni, TimesSet)) {
			fnx->creation_time = ni->creation_time;
			fnx->last_data_change_time = ni->last_data_change_time;
			fnx->last_mft_change_time = ni->last_mft_change_time;
			fnx->last_access_time = ni->last_access_time;
		} else {
			fnx->creation_time = fn->creation_time;
			fnx->last_data_change_time = fn->last_data_change_time;
			fnx->last_mft_change_time = fn->last_mft_change_time;
			fnx->last_access_time = fn->last_access_time;
		}
		ntfs_index_entry_mark_dirty(ictx);
		ntfs_index_ctx_put(ictx);
		if ((ni != index_ni) && !dir_ni
		    && ntfs_inode_close(index_ni) && !err)
			err = errno;
	}
	/* Check for real error occurred. */
	if (errno != ENOENT) {
		err = errno;
		ntfs_log_perror("Attribute lookup failed, inode %lld",
				(long long)ni->mft_no);
		goto err_out;
	}
	ntfs_attr_put_search_ctx(ctx);
	if (err) {
		errno = err;
		return -1;
	}
	return 0;
err_out:
	if (ctx)
		ntfs_attr_put_search_ctx(ctx);
	errno = err;
	return -1;
}
Exemplo n.º 24
0
status_t
fs_read_vnode(fs_volume *_vol, ino_t vnid, fs_vnode *_node, int *_type,
	uint32 *_flags, bool reenter)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *newNode = NULL;
	ntfs_inode *ni = NULL;
	status_t result = B_NO_ERROR;

	if (!reenter)
		LOCK_VOL(ns);

	ERRPRINT("fs_read_vnode - ENTER\n");

	_node->private_node = NULL;
	_node->ops = &gNTFSVnodeOps;
	_flags = 0;

	newNode = (vnode*)ntfs_calloc(sizeof(vnode));
	if (newNode != NULL) {
		char *name = NULL;

		ni = ntfs_inode_open(ns->ntvol, vnid);
		if (ni == NULL) {
			result = ENOENT;
			goto exit;
		}

		// get the node type
		result = get_node_type(ni, _type);
		if (result != B_OK)
			goto exit;

		newNode->vnid = vnid;
		newNode->parent_vnid = ntfs_get_parent_ref(ni);

		if (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
			set_mime(newNode, ".***");
		else {
			name = (char*)malloc(MAX_PATH);
			if (name != NULL) {
				if (utils_inode_get_name(ni, name,MAX_PATH) == 1)
					set_mime(newNode, name);
				free(name);
			}
		}

		_node->private_node = newNode;
	} else
		result = ENOMEM;

exit:
	if (ni != NULL)
		ntfs_inode_close(ni);

	if (result != B_OK && newNode != NULL)
		free(newNode);

	ERRPRINT("fs_read_vnode - EXIT, result is %s\n", strerror(result));

	if (!reenter)
		UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 25
0
/**
 * ntfs_inode_sync_file_name - update FILE_NAME attributes
 * @ni:		ntfs inode to update FILE_NAME attributes
 *
 * Update all FILE_NAME attributes for inode @ni in the index.
 *
 * Return 0 on success or -1 on error with errno set to the error code.
 */
static int ntfs_inode_sync_file_name(ntfs_inode *ni)
{
	ntfs_attr_search_ctx *ctx = NULL;
	ntfs_index_context *ictx;
	ntfs_inode *index_ni;
	FILE_NAME_ATTR *fn;
	int err = 0;

	ntfs_log_trace("Entering for inode %lld\n", (long long)ni->mft_no);

	ctx = ntfs_attr_get_search_ctx(ni, NULL);
	if (!ctx) {
		err = errno;
		goto err_out;
	}
	/* Walk through all FILE_NAME attributes and update them. */
	while (!ntfs_attr_lookup(AT_FILE_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
		fn = (FILE_NAME_ATTR *)((u8 *)ctx->attr +
				le16_to_cpu(ctx->attr->value_offset));
		if (MREF_LE(fn->parent_directory) == ni->mft_no) {
			/*
			 * WARNING: We cheat here and obtain 2 attribute
			 * search contexts for one inode (first we obtained
			 * above, second will be obtained inside
			 * ntfs_index_lookup), it's acceptable for library,
			 * but will deadlock in the kernel.
			 */
			index_ni = ni;
		} else
			index_ni = ntfs_inode_open(ni->vol,
					le64_to_cpu(fn->parent_directory));
		if (!index_ni) {
			if (!err)
				err = errno;
			ntfs_log_perror("Failed to open inode %lld with index",
				(long long)le64_to_cpu(fn->parent_directory));
			continue;
		}
		ictx = ntfs_index_ctx_get(index_ni, NTFS_INDEX_I30, 4);
		if (!ictx) {
			if (!err)
				err = errno;
			ntfs_log_perror("Failed to get index ctx, inode %lld",
					(long long)index_ni->mft_no);
			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
				err = errno;
			continue;
		}
		if (ntfs_index_lookup(fn, sizeof(FILE_NAME_ATTR), ictx)) {
			if (!err) {
				if (errno == ENOENT)
					err = EIO;
				else
					err = errno;
			}
			ntfs_log_perror("Index lookup failed, inode %lld",
					(long long)index_ni->mft_no);
			ntfs_index_ctx_put(ictx);
			if (ni != index_ni && ntfs_inode_close(index_ni) && !err)
				err = errno;
			continue;
		}
		/* Update flags and file size. */
		fn = (FILE_NAME_ATTR *)ictx->data;
		fn->file_attributes =
				(fn->file_attributes & ~FILE_ATTR_VALID_FLAGS) |
				(ni->flags & FILE_ATTR_VALID_FLAGS);
		fn->allocated_size = cpu_to_sle64(ni->allocated_size);
		fn->data_size = cpu_to_sle64(ni->data_size);
		if (test_nino_flag(ni, TimesDirty)) {
			fn->creation_time = utc2ntfs(ni->creation_time);
			fn->last_data_change_time = utc2ntfs(ni->last_data_change_time);
			fn->last_mft_change_time = utc2ntfs(ni->last_mft_change_time);
			fn->last_access_time = utc2ntfs(ni->last_access_time);
		}
		ntfs_index_entry_mark_dirty(ictx);
		ntfs_index_ctx_put(ictx);
		if ((ni != index_ni) && ntfs_inode_close(index_ni) && !err)
			err = errno;
	}
	/* Check for real error occurred. */
	if (errno != ENOENT) {
		err = errno;
		ntfs_log_perror("Attribute lookup failed, inode %lld",
				(long long)ni->mft_no);
		goto err_out;
	}
	ntfs_attr_put_search_ctx(ctx);
	if (err) {
		errno = err;
		return -1;
	}
	return 0;
err_out:
	if (ctx)
		ntfs_attr_put_search_ctx(ctx);
	errno = err;
	return -1;
}
Exemplo n.º 26
0
static int ntfs_copy(disk_t *disk_car, const partition_t *partition, dir_data_t *dir_data, const file_info_t *file)
{
  const unsigned long int first_inode=file->st_ino;
  ntfs_inode *inode;
  struct ntfs_dir_struct *ls=(struct ntfs_dir_struct*)dir_data->private_dir_data;
  inode = ntfs_inode_open (ls->vol, first_inode);
  if (!inode) {
    log_error("ntfs_copy: ntfs_inode_open failed for %s\n", dir_data->current_directory);
    return -1;
  }
  {
    char *buffer;
    char *new_file;
    ntfs_attr *attr=NULL;
    FILE *f_out;
    char *stream_name;
    s64 offset;
    u32 block_size;
    buffer = (char *)MALLOC(bufsize);
    if (!buffer)
    {
      ntfs_inode_close(inode);
      return -2;
    }
    stream_name=strrchr(dir_data->current_directory, ':');
    if(stream_name)
      stream_name++;
    if(stream_name != NULL)
    {
      ntfschar *stream_name_ucs=NULL;
#ifdef NTFS_MBSTOUCS_HAVE_TWO_ARGUMENTS
      const int len=ntfs_mbstoucs(stream_name, &stream_name_ucs);
#else
      const int len=ntfs_mbstoucs(stream_name, &stream_name_ucs, 0);
#endif
      if(len < 0)
	log_error("ntfs_mbstoucs failed\n");
      else
	attr = ntfs_attr_open(inode, AT_DATA, stream_name_ucs, len);
    }
    else
      attr = ntfs_attr_open(inode, AT_DATA, NULL, 0);
    if (!attr)
    {
      log_error("Cannot find attribute type 0x%lx.\n", (long) AT_DATA);
      free(buffer);
      ntfs_inode_close(inode);
      return -3;
    }
    if ((inode->mft_no < 2) && (attr->type == AT_DATA))
      block_size = ls->vol->mft_record_size;
    else if (attr->type == AT_INDEX_ALLOCATION)
      block_size = index_get_size(inode);
    else
      block_size = 0;
#if defined(__CYGWIN__) || defined(__MINGW32__)
    if(stream_name)
    {
      /* fopen() create normal files instead of ADS with ':' replaced by an UTF char
       * replace ':' by '_' instead */
      stream_name--;
      *stream_name='_';
      f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory);
    }
    else
      f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory);
#else
    f_out=fopen_local(&new_file, dir_data->local_dir, dir_data->current_directory);
#endif
    if(!f_out)
    {
      log_critical("Can't create file %s: %s\n",new_file, strerror(errno));
      free(new_file);
      ntfs_attr_close(attr);
      free(buffer);
      ntfs_inode_close(inode);
      return -4;
    }
    offset = 0;
    for (;;)
    {
      s64 bytes_read, written;
      if (block_size > 0) {
	// These types have fixup
	bytes_read = ntfs_attr_mst_pread(attr, offset, 1, block_size, buffer);
	bytes_read *= block_size;
      } else {
	bytes_read = ntfs_attr_pread(attr, offset, bufsize, buffer);
      }
      //ntfs_log_info("read %lld bytes\n", bytes_read);
      if (bytes_read < 0) {
	log_error("ERROR: Couldn't read file");
	break;
      }
      if (!bytes_read)
	break;

      written = fwrite(buffer, 1, bytes_read, f_out);
      if (written != bytes_read)
      {
	log_error("ERROR: Couldn't output all data!");
	break;
      }
      offset += bytes_read;
    }
    fclose(f_out);
    set_date(new_file, file->td_atime, file->td_mtime);
    free(new_file);
    ntfs_attr_close(attr);
    free(buffer);
  }
  /* Finished with the inode; release it. */
  ntfs_inode_close(inode);
  return 0;
}
Exemplo n.º 27
0
static char *search_relative(ntfs_inode *ni, ntfschar *path, int count)
{
	char *target = (char*)NULL;
	ntfs_inode *curni;
	ntfs_inode *newni;
	u64 inum;
	int pos;
	int lth;
	BOOL ok;
	int max = 32; /* safety */

	pos = 0;
	ok = TRUE;
	curni = ntfs_dir_parent_inode(ni);
	while (curni && ok && (pos < (count - 1)) && --max) {
		if ((count >= (pos + 2))
		    && (path[pos] == const_cpu_to_le16('.'))
		    && (path[pos+1] == const_cpu_to_le16('\\'))) {
			path[1] = const_cpu_to_le16('/');
			pos += 2;
		} else {
			if ((count >= (pos + 3))
			    && (path[pos] == const_cpu_to_le16('.'))
			    &&(path[pos+1] == const_cpu_to_le16('.'))
			    && (path[pos+2] == const_cpu_to_le16('\\'))) {
				path[2] = const_cpu_to_le16('/');
				pos += 3;
				newni = ntfs_dir_parent_inode(curni);
				if (curni != ni)
					ntfs_inode_close(curni);
				curni = newni;
				if (!curni)
					ok = FALSE;
			} else {
				lth = 0;
				while (((pos + lth) < count)
				    && (path[pos + lth] != const_cpu_to_le16('\\')))
					lth++;
				if (lth > 0)
					inum = ntfs_fix_file_name(curni,&path[pos],lth);
				else
					inum = (u64)-1;
				if (!lth
				    || ((curni != ni)
					&& ntfs_inode_close(curni))
				    || (inum == (u64)-1))
					ok = FALSE;
				else {
					curni = ntfs_inode_open(ni->vol, MREF(inum));
					if (!curni)
						ok = FALSE;
					else {
						if (ok && ((pos + lth) < count)) {
							path[pos + lth] = const_cpu_to_le16('/');
							pos += lth + 1;
						} else {
							pos += lth;
							if ((ni->mrec->flags ^ curni->mrec->flags)
							    & MFT_RECORD_IS_DIRECTORY)
								ok = FALSE;
							if (ntfs_inode_close(curni))
								ok = FALSE;
						}
					}
				}
			}
		}
	}

	if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) {
		free(target); // needed ?
		target = (char*)NULL;
	}
	return (target);
}
Exemplo n.º 28
0
status_t 
fs_read_attrib(fs_volume *_vol, fs_vnode *_node, void *_cookie, off_t pos,
	void *buffer, size_t *len)
{
	nspace *ns = (nspace *)_vol->private_volume;
	vnode *node = (vnode *)_node->private_node;
	attrcookie *cookie = (attrcookie *)_cookie;
	ntfs_inode *ni = NULL;
	ntfs_attr *na = NULL;
	size_t size = *len;
	int total = 0;
	status_t result = B_NO_ERROR;

	if (pos < 0) {
		*len = 0;
		return EINVAL;
	}

	LOCK_VOL(ns);

	TRACE("%s - ENTER  vnid: %d\n", __FUNCTION__, node->vnid);
	
	ni = ntfs_inode_open(ns->ntvol, node->vnid);
	if (ni == NULL) {
		result = errno;
		goto exit;
	}
	na = ntfs_attr_open(ni, AT_DATA, cookie->uname, cookie->uname_len);
	if (na == NULL) {
		result = errno;
		goto exit;		
	}	
	
	pos += sizeof(uint32);

	// it is a named stream
	if (na != NULL) {
		if (pos + size > na->data_size)
			size = na->data_size - pos;

		while (size) {
			off_t bytesRead = ntfs_attr_pread(na, pos, size, buffer);
			if (bytesRead < (s64)size) {
				ERROR("ntfs_attr_pread returned less bytes than "
					"requested.\n");
			}
			if (bytesRead <= 0) {
				*len = 0;
				result = EINVAL;
				goto exit;
			}
			size -= bytesRead;
			pos += bytesRead;
			total += bytesRead;
		}

		*len = total;
	} else {
		*len = 0;
		result = ENOENT; // TODO
	}

exit:
	if (na != NULL)
		ntfs_attr_close(na);
	if (ni != NULL)
		ntfs_inode_close(ni);
			
	TRACE("%s - EXIT, result is %s\n", __FUNCTION__, strerror(result));

	UNLOCK_VOL(ns);
	
	return result;
}
Exemplo n.º 29
0
status_t
fs_walk(fs_volume *_vol, fs_vnode *_dir, const char *file, ino_t *vnid)
{
	nspace *ns = (nspace*)_vol->private_volume;
	vnode *baseNode = (vnode*)_dir->private_node;
	vnode *newNode = NULL;
	ntfschar *unicode = NULL;
	ntfs_inode *bi = NULL;
	status_t result = B_NO_ERROR;
	int len;

	LOCK_VOL(ns);

	ERRPRINT("fs_walk - ENTER : find for \"%s\"\n",file);

	if (ns == NULL || _dir == NULL || file == NULL || vnid == NULL) {
		result = EINVAL;
		goto exit;
	}

	if (!strcmp(file, ".")) {
		*vnid = baseNode->vnid;
		if (get_vnode(_vol, *vnid, (void**)&newNode) != 0)
			result = ENOENT;
	} else if (!strcmp(file, "..") && baseNode->vnid != FILE_root) {
		*vnid = baseNode->parent_vnid;
		if (get_vnode(_vol, *vnid, (void**)&newNode) != 0)
			result = ENOENT;
	} else {
		unicode = ntfs_calloc(MAX_PATH);
		len = ntfs_mbstoucs(file, &unicode);
		if (len < 0) {
			result = EILSEQ;
			goto exit;
		}

		bi = ntfs_inode_open(ns->ntvol, baseNode->vnid);
		if (!bi) {
			result = ENOENT;
			goto exit;
		}

		*vnid = MREF(ntfs_inode_lookup_by_name(bi, unicode, len));
		ERRPRINT("fs_walk - VNID = %d\n",*vnid);

		ntfs_inode_close(bi);
		free(unicode);

		if (*vnid == (u64)-1) {
			result = EINVAL;
			goto exit;
		}

		if (get_vnode(_vol, *vnid, (void**)&newNode) != 0)
			result = ENOENT;

		if (newNode!=NULL)
			newNode->parent_vnid = baseNode->vnid;
	}

exit:
	ERRPRINT("fs_walk - EXIT, result is %s\n", strerror(result));

	UNLOCK_VOL(ns);

	return result;
}
Exemplo n.º 30
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;
}