Пример #1
0
int ntfs_delete_reparse_index(ntfs_inode *ni)
{
	ntfs_index_context *xr;
	ntfs_inode *xrni;
	ntfs_attr *na;
	le32 reparse_tag;
	int res;

	res = 0;
	na = ntfs_attr_open(ni, AT_REPARSE_POINT, AT_UNNAMED, 0);
	if (na) {
			/*
			 * read the existing reparse data (the tag is enough)
			 * and un-index it
			 */
		xr = open_reparse_index(ni->vol);
		if (xr) {
			if (remove_reparse_index(na,xr,&reparse_tag) < 0)
				res = -1;
			xrni = xr->ni;
			ntfs_index_entry_mark_dirty(xr);
			NInoSetDirty(xrni);
			ntfs_index_ctx_put(xr);
			ntfs_inode_close(xrni);
		}
		ntfs_attr_close(na);
	}
	return (res);
}
Пример #2
0
int ntfs_delete_object_id_index(ntfs_inode *ni)
{
	ntfs_index_context *xo;
	ntfs_inode *xoni;
	ntfs_attr *na;
	OBJECT_ID_ATTR old_attr;
	int res;

	res = 0;
	na = ntfs_attr_open(ni, AT_OBJECT_ID, AT_UNNAMED, 0);
	if (na) {
			/*
			 * read the existing object id
			 * and un-index it
			 */
		xo = open_object_id_index(ni->vol);
		if (xo) {
			if (remove_object_id_index(na,xo,&old_attr) < 0)
				res = -1;
			xoni = xo->ni;
			ntfs_index_entry_mark_dirty(xo);
			NInoSetDirty(xoni);
			ntfs_index_ctx_put(xo);
			ntfs_inode_close(xoni);
		}
		ntfs_attr_close(na);
	}
	return (res);
}
Пример #3
0
int ntfs_set_ntfs_object_id(ntfs_inode *ni,
			const char *value, size_t size, int flags)
{
	OBJECT_ID_INDEX_KEY key;
	ntfs_inode *xoni;
	ntfs_index_context *xo;
	int res;

	res = 0;
	if (ni && value && (size >= sizeof(GUID))) {
		xo = open_object_id_index(ni->vol);
		if (xo) {
			/* make sure the GUID was not used somewhere */
			memcpy(&key.object_id, value, sizeof(GUID));
			if (ntfs_index_lookup(&key,
					sizeof(OBJECT_ID_INDEX_KEY), xo)) {
				ntfs_index_ctx_reinit(xo);
				res = add_object_id(ni, flags);
				if (!res) {
						/* update value and index */
					res = update_object_id(ni,xo,
						(const OBJECT_ID_ATTR*)value,
						size);
				}
			} else {
					/* GUID is present elsewhere */
				res = -1;
				errno = EEXIST;
			}
			xoni = xo->ni;
			ntfs_index_entry_mark_dirty(xo);
			NInoSetDirty(xoni);
			ntfs_index_ctx_put(xo);
			ntfs_inode_close(xoni);
		} else {
			res = -1;
		}
	} else {
		errno = EINVAL;
		res = -1;
	}
	return (res ? -1 : 0);
}
Пример #4
0
int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni,
		const void *key, const int keylen)
{
	int ret = STATUS_ERROR;
	ntfs_index_context *icx;

	icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
	if (!icx)
		return -1;

	while (1) {
				
		if (ntfs_index_lookup(key, keylen, icx))
			goto err_out;

		if ((((FILE_NAME_ATTR *)icx->data)->file_attributes &
				FILE_ATTR_REPARSE_POINT)
		   && !ntfs_possible_symlink(ni)) {
			errno = EOPNOTSUPP;
			goto err_out;
		}

		ret = ntfs_index_rm(icx);
		if (ret == STATUS_ERROR)
			goto err_out;
		else if (ret == STATUS_OK)
			break;
		
		ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
		ntfs_index_ctx_reinit(icx);
	}

	ntfs_inode_mark_dirty(icx->actx->ntfs_ino);
out:	
	ntfs_index_ctx_put(icx);
	return ret;
err_out:
	ret = STATUS_ERROR;
	ntfs_log_perror("Delete failed");
	goto out;
}
Пример #5
0
/**
 * ntfs_index_add_filename - add filename to directory index
 * @ni:		ntfs inode describing directory to which index add filename
 * @fn:		FILE_NAME attribute to add
 * @mref:	reference of the inode which @fn describes
 *
 * Return 0 on success or -1 on error with errno set to the error code.
 */
int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref)
{
	INDEX_ENTRY *ie;
	ntfs_index_context *icx;
	int fn_size, ie_size, err, ret = -1;

	ntfs_log_trace("Entering\n");
	
	if (!ni || !fn) {
		ntfs_log_error("Invalid arguments.\n");
		errno = EINVAL;
		return -1;
	}
	
	fn_size = (fn->file_name_length * sizeof(ntfschar)) +
			sizeof(FILE_NAME_ATTR);
	ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7;
	
	ie = ntfs_calloc(ie_size);
	if (!ie)
		return -1;

	ie->indexed_file = cpu_to_le64(mref);
	ie->length 	 = cpu_to_le16(ie_size);
	ie->key_length 	 = cpu_to_le16(fn_size);
	memcpy(&ie->key, fn, fn_size);
	
	icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4);
	if (!icx)
		goto out;
	
	ret = ntfs_ie_add(icx, ie);
	err = errno;
	ntfs_index_ctx_put(icx);
	errno = err;
out:
	free(ie);
	return ret;
}
Пример #6
0
static int merge_index_data(ntfs_inode *ni,
			const OBJECT_ID_ATTR *objectid_attr,
			OBJECT_ID_ATTR *full_objectid)
{
	OBJECT_ID_INDEX_KEY key;
	struct OBJECT_ID_INDEX *entry;
	ntfs_index_context *xo;
	ntfs_inode *xoni;
	int res;

	res = -1;
	xo = open_object_id_index(ni->vol);
	if (xo) {
		memcpy(&key.object_id,objectid_attr,sizeof(GUID));
		if (!ntfs_index_lookup(&key,
				sizeof(OBJECT_ID_INDEX_KEY), xo)) {
			entry = (struct OBJECT_ID_INDEX*)xo->entry;
			/* make sure inode numbers match */
			if (entry
			    && (MREF(le64_to_cpu(entry->data.file_id))
					== ni->mft_no)) {
				memcpy(&full_objectid->birth_volume_id,
						&entry->data.birth_volume_id,
						sizeof(GUID));
				memcpy(&full_objectid->birth_object_id,
						&entry->data.birth_object_id,
						sizeof(GUID));
				memcpy(&full_objectid->domain_id,
						&entry->data.domain_id,
						sizeof(GUID));
				res = 0;
			}
		}
		xoni = xo->ni;
		ntfs_index_ctx_put(xo);
		ntfs_inode_close(xoni);
	}
	return (res);
}
Пример #7
0
/**
 * ntfs_mark_quotas_out_of_date - mark the quotas out of date on an ntfs volume
 * @vol:	ntfs volume on which to mark the quotas out of date
 *
 * Mark the quotas out of date on the ntfs volume @vol and return TRUE on
 * success and FALSE on error.
 */
BOOL ntfs_mark_quotas_out_of_date(ntfs_volume *vol)
{
	ntfs_index_context *ictx;
	QUOTA_CONTROL_ENTRY *qce;
	const le32 qid = QUOTA_DEFAULTS_ID;
	int err;

	ntfs_debug("Entering.");
	if (NVolQuotaOutOfDate(vol))
		goto done;
	if (!vol->quota_ino || !vol->quota_q_ino) {
		ntfs_error(vol->sb, "Quota inodes are not open.");
		return FALSE;
	}
	down(&vol->quota_q_ino->i_sem);
	ictx = ntfs_index_ctx_get(NTFS_I(vol->quota_q_ino));
	if (!ictx) {
		ntfs_error(vol->sb, "Failed to get index context.");
		goto err_out;
	}
	err = ntfs_index_lookup(&qid, sizeof(qid), ictx);
	if (err) {
		if (err == -ENOENT)
			ntfs_error(vol->sb, "Quota defaults entry is not "
					"present.");
		else
			ntfs_error(vol->sb, "Lookup of quota defaults entry "
					"failed.");
		goto err_out;
	}
	if (ictx->data_len < offsetof(QUOTA_CONTROL_ENTRY, sid)) {
		ntfs_error(vol->sb, "Quota defaults entry size is invalid.  "
				"Run chkdsk.");
		goto err_out;
	}
	qce = (QUOTA_CONTROL_ENTRY*)ictx->data;
	if (le32_to_cpu(qce->version) != QUOTA_VERSION) {
		ntfs_error(vol->sb, "Quota defaults entry version 0x%x is not "
				"supported.", le32_to_cpu(qce->version));
		goto err_out;
	}
	ntfs_debug("Quota defaults flags = 0x%x.", le32_to_cpu(qce->flags));
	/* If quotas are already marked out of date, no need to do anything. */
	if (qce->flags & QUOTA_FLAG_OUT_OF_DATE)
		goto set_done;
	/*
	 * If quota tracking is neither requested, nor enabled and there are no
	 * pending deletes, no need to mark the quotas out of date.
	 */
	if (!(qce->flags & (QUOTA_FLAG_TRACKING_ENABLED |
			QUOTA_FLAG_TRACKING_REQUESTED |
			QUOTA_FLAG_PENDING_DELETES)))
		goto set_done;
	/*
	 * Set the QUOTA_FLAG_OUT_OF_DATE bit thus marking quotas out of date.
	 * This is verified on WinXP to be sufficient to cause windows to
	 * rescan the volume on boot and update all quota entries.
	 */
	qce->flags |= QUOTA_FLAG_OUT_OF_DATE;
	/* Ensure the modified flags are written to disk. */
	ntfs_index_entry_flush_dcache_page(ictx);
	ntfs_index_entry_mark_dirty(ictx);
set_done:
	ntfs_index_ctx_put(ictx);
	up(&vol->quota_q_ino->i_sem);
	/*
	 * We set the flag so we do not try to mark the quotas out of date
	 * again on remount.
	 */
	NVolSetQuotaOutOfDate(vol);
done:
	ntfs_debug("Done.");
	return TRUE;
err_out:
	if (ictx)
		ntfs_index_ctx_put(ictx);
	up(&vol->quota_q_ino->i_sem);
	return FALSE;
}
Пример #8
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;
}
Пример #9
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;
}
Пример #10
0
static u64 ntfs_fix_file_name(ntfs_inode *dir_ni, ntfschar *uname,
		int uname_len)
{
	ntfs_volume *vol = dir_ni->vol;
	ntfs_index_context *icx;
	u64 mref;
	le64 lemref;
	int lkup;
	int olderrno;
	int i;
	u32 cpuchar;
	INDEX_ENTRY *entry;
	FILE_NAME_ATTR *found;
	struct {
		FILE_NAME_ATTR attr;
		ntfschar file_name[NTFS_MAX_NAME_LEN + 1];
	} find;

	mref = (u64)-1; /* default return (not found) */
	icx = ntfs_index_ctx_get(dir_ni, NTFS_INDEX_I30, 4);
	if (icx) {
		if (uname_len > NTFS_MAX_NAME_LEN)
			uname_len = NTFS_MAX_NAME_LEN;
		find.attr.file_name_length = uname_len;
		for (i=0; i<uname_len; i++) {
			cpuchar = le16_to_cpu(uname[i]);
			/*
			 * We need upper or lower value, whichever is smaller,
			 * but we can only convert to upper case, so we
			 * will fail when searching for an upper case char
			 * whose lower case is smaller (such as umlauted Y)
			 */
			if ((cpuchar < vol->upcase_len)
			    && (le16_to_cpu(vol->upcase[cpuchar]) < cpuchar))
				find.attr.file_name[i] = vol->upcase[cpuchar];
			else
				find.attr.file_name[i] = uname[i];
		}
		olderrno = errno;
		lkup = ntfs_index_lookup((char*)&find, uname_len, icx);
		if (errno == ENOENT)
			errno = olderrno;
		/*
		 * We generally only get the first matching candidate,
		 * so we still have to check whether this is a real match
		 */
		if (icx->entry && (icx->entry->ie_flags & INDEX_ENTRY_END))
				/* get next entry if reaching end of block */
			entry = ntfs_index_next(icx->entry, icx);
		else
			entry = icx->entry;
		if (entry) {
			found = &entry->key.file_name;
			if (lkup
			   && ntfs_names_are_equal(find.attr.file_name,
				find.attr.file_name_length,
				found->file_name, found->file_name_length,
				IGNORE_CASE,
				vol->upcase, vol->upcase_len))
					lkup = 0;
			if (!lkup) {
				/*
				 * name found :
				 *    fix original name and return inode
				 */
				lemref = entry->indexed_file;
				mref = le64_to_cpu(lemref);
				if (NVolCaseSensitive(vol) || !vol->locase) {
					for (i=0; i<found->file_name_length; i++)
						uname[i] = found->file_name[i];
				} else {
					for (i=0; i<found->file_name_length; i++)
						uname[i] = vol->locase[found->file_name[i]];
				}
			}
		}
		ntfs_index_ctx_put(icx);
	}
	return (mref);
}
Пример #11
0
int ntfs_remove_ntfs_reparse_data(ntfs_inode *ni)
{
	int res;
	int olderrno;
	ntfs_attr *na;
	ntfs_inode *xrni;
	ntfs_index_context *xr;
	le32 reparse_tag;

	res = 0;
	if (ni) {
		/*
		 * open and delete the reparse data
		 */
		na = ntfs_attr_open(ni, AT_REPARSE_POINT,
			AT_UNNAMED,0);
		if (na) {
			/* first remove index (reparse data needed) */
			xr = open_reparse_index(ni->vol);
			if (xr) {
				if (remove_reparse_index(na,xr,
						&reparse_tag) < 0) {
					res = -1;
				} else {
					/* now remove attribute */
					res = ntfs_attr_rm(na);
					if (!res) {
						ni->flags &=
						    ~FILE_ATTR_REPARSE_POINT;
						NInoFileNameSetDirty(ni);
					} else {
					/*
					 * If we could not remove the
					 * attribute, try to restore the
					 * index and log the error. There
					 * will be an inconsistency if
					 * the reindexing fails.
					 */
						set_reparse_index(ni, xr,
							reparse_tag);
						ntfs_log_error(
						"Failed to remove reparse data."
						" Possible corruption.\n");
					}
				}
				xrni = xr->ni;
				ntfs_index_entry_mark_dirty(xr);
				NInoSetDirty(xrni);
				ntfs_index_ctx_put(xr);
				ntfs_inode_close(xrni);
			}
			olderrno = errno;
			ntfs_attr_close(na);
					/* avoid errno pollution */
			if (errno == ENOENT)
				errno = olderrno;
		} else {
			errno = ENODATA;
			res = -1;
		}
		NInoSetDirty(ni);
	} else {
		errno = EINVAL;
		res = -1;
	}
	return (res ? -1 : 0);
}
Пример #12
0
int ntfs_set_ntfs_reparse_data(ntfs_inode *ni,
			const char *value, size_t size, int flags)
{
	int res;
	u8 dummy;
	ntfs_inode *xrni;
	ntfs_index_context *xr;

	res = 0;
	if (ni && valid_reparse_data(ni, (const REPARSE_POINT*)value, size)) {
		xr = open_reparse_index(ni->vol);
		if (xr) {
			if (!ntfs_attr_exist(ni,AT_REPARSE_POINT,
						AT_UNNAMED,0)) {
				if (!(flags & XATTR_REPLACE)) {
			/*
			 * no reparse data attribute : add one,
			 * apparently, this does not feed the new value in
			 * Note : NTFS version must be >= 3
			 */
					if (ni->vol->major_ver >= 3) {
						res = ntfs_attr_add(ni,
							AT_REPARSE_POINT,
							AT_UNNAMED,0,&dummy,
							(s64)0);
						if (!res) {
						    ni->flags |=
							FILE_ATTR_REPARSE_POINT;
						    NInoFileNameSetDirty(ni);
						}
						NInoSetDirty(ni);
					} else {
						errno = EOPNOTSUPP;
						res = -1;
					}
				} else {
					errno = ENODATA;
					res = -1;
				}
			} else {
				if (flags & XATTR_CREATE) {
					errno = EEXIST;
					res = -1;
				}
			}
			if (!res) {
					/* update value and index */
				res = update_reparse_data(ni,xr,value,size);
			}
			xrni = xr->ni;
			ntfs_index_entry_mark_dirty(xr);
			NInoSetDirty(xrni);
			ntfs_index_ctx_put(xr);
			ntfs_inode_close(xrni);
		} else {
			res = -1;
		}
	} else {
		errno = EINVAL;
		res = -1;
	}
	return (res ? -1 : 0);
}
Пример #13
0
int ntfs_remove_ntfs_object_id(ntfs_inode *ni)
{
	int res;
	int olderrno;
	ntfs_attr *na;
	ntfs_inode *xoni;
	ntfs_index_context *xo;
	int oldsize;
	OBJECT_ID_ATTR old_attr;

	res = 0;
	if (ni) {
		/*
		 * open and delete the object id
		 */
		na = ntfs_attr_open(ni, AT_OBJECT_ID,
			AT_UNNAMED,0);
		if (na) {
			/* first remove index (old object id needed) */
			xo = open_object_id_index(ni->vol);
			if (xo) {
				oldsize = remove_object_id_index(na,xo,
						&old_attr);
				if (oldsize < 0) {
					res = -1;
				} else {
					/* now remove attribute */
					res = ntfs_attr_rm(na);
					if (res
					    && (oldsize > (int)sizeof(GUID))) {
					/*
					 * If we could not remove the
					 * attribute, try to restore the
					 * index and log the error. There
					 * will be an inconsistency if
					 * the reindexing fails.
					 */
						set_object_id_index(ni, xo,
							&old_attr);
						ntfs_log_error(
						"Failed to remove object id."
						" Possible corruption.\n");
					}
				}

				xoni = xo->ni;
				ntfs_index_entry_mark_dirty(xo);
				NInoSetDirty(xoni);
				ntfs_index_ctx_put(xo);
				ntfs_inode_close(xoni);
			}
			olderrno = errno;
			ntfs_attr_close(na);
					/* avoid errno pollution */
			if (errno == ENOENT)
				errno = olderrno;
		} else {
			errno = ENODATA;
			res = -1;
		}
		NInoSetDirty(ni);
	} else {
		errno = EINVAL;
		res = -1;
	}
	return (res ? -1 : 0);
}