summaryrefslogtreecommitdiffstats
path: root/src/ntfs_utl.c
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2007-10-29 22:38:52 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2007-10-29 22:38:52 +0100
commit9928d99936105b4653d2d1b8ca74dc3ffba5c71e (patch)
tree06aa4f5e9f0055027c6fb54dd47a8414cf2fba32 /src/ntfs_utl.c
First version in git
Diffstat (limited to 'src/ntfs_utl.c')
-rw-r--r--src/ntfs_utl.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/src/ntfs_utl.c b/src/ntfs_utl.c
new file mode 100644
index 0000000..6f7b216
--- /dev/null
+++ b/src/ntfs_utl.c
@@ -0,0 +1,195 @@
+/**
+ * ntfs_utl.c - Part of the TestDisk project.
+ *
+ * Copyright (c) 2004-2007 Christophe Grenier
+ *
+ * Original version comes from the Linux-NTFS project.
+ * Copyright (c) 2003 Lode Leroy
+ * Copyright (c) 2003 Anton Altaparmakov
+ * Copyright (c) 2003 Richard Russon
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (in the main directory of the Linux-NTFS
+ * distribution in the file COPYING); if not, write to the Free Software
+ * Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_LIBNTFS
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#endif
+#include <stdarg.h>
+#include "types.h"
+
+#include <ntfs/attrib.h>
+#include "ntfs_utl.h"
+#include "common.h"
+#include "log.h"
+
+/**
+ * find_attribute - Find an attribute of the given type
+ * @type: An attribute type, e.g. AT_FILE_NAME
+ * @ctx: A search context, created using ntfs_get_attr_search_ctx
+ *
+ * Using the search context to keep track, find the first/next occurrence of a
+ * given attribute type.
+ *
+ * N.B. This will return a pointer into @mft. As long as the search context
+ * has been created without an inode, it won't overflow the buffer.
+ *
+ * Return: Pointer Success, an attribute was found
+ * NULL Error, no matching attributes were found
+ */
+ATTR_RECORD * find_attribute(const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
+{
+ if (!ctx) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) {
+#ifdef DEBUG_NTFS
+ log_debug("find_attribute didn't find an attribute of type: 0x%02x.\n", type);
+#endif
+ return NULL; /* None / no more of that type */
+ }
+#ifdef DEBUG_NTFS
+ log_debug("find_attribute found an attribute of type: 0x%02x.\n", type);
+#endif
+ return ctx->attr;
+}
+
+/**
+ * find_first_attribute - Find the first attribute of a given type
+ * @type: An attribute type, e.g. AT_FILE_NAME
+ * @mft: A buffer containing a raw MFT record
+ *
+ * Search through a raw MFT record for an attribute of a given type.
+ * The return value is a pointer into the MFT record that was supplied.
+ *
+ * N.B. This will return a pointer into @mft. The pointer won't stray outside
+ * the buffer, since we created the search context without an inode.
+ *
+ * Return: Pointer Success, an attribute was found
+ * NULL Error, no matching attributes were found
+ */
+ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
+{
+ ntfs_attr_search_ctx *ctx;
+ ATTR_RECORD *rec;
+
+ if (!mft) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ ctx = ntfs_attr_get_search_ctx(NULL, mft);
+ if (!ctx) {
+ log_error("Couldn't create a search context.\n");
+ return NULL;
+ }
+
+ rec = find_attribute(type, ctx);
+ ntfs_attr_put_search_ctx(ctx);
+#ifdef DEBUG_NTFS
+ if (rec)
+ log_debug("find_first_attribute: found attr of type 0x%02x.\n", type);
+ else
+ log_debug("find_first_attribute: didn't find attr of type 0x%02x.\n", type);
+#endif
+ return rec;
+}
+
+/**
+ * utils_cluster_in_use - Determine if a cluster is in use
+ * @vol: An ntfs volume obtained from ntfs_mount
+ * @lcn: The Logical Cluster Number to test
+ *
+ * The metadata file $Bitmap has one binary bit representing each cluster on
+ * disk. The bit will be set for each cluster that is in use. The function
+ * reads the relevant part of $Bitmap into a buffer and tests the bit.
+ *
+ * This function has a static buffer in which it caches a section of $Bitmap.
+ * If the lcn, being tested, lies outside the range, the buffer will be
+ * refreshed.
+ *
+ * Return: 1 Cluster is in use
+ * 0 Cluster is free space
+ * -1 Error occurred
+ */
+int utils_cluster_in_use(ntfs_volume *vol, long long lcn)
+{
+ static unsigned char buffer[512];
+ static long long bmplcn = -sizeof(buffer) - 1; /* Which bit of $Bitmap is in the buffer */
+
+ int byte, bit;
+ ntfs_attr *attr;
+
+ if (!vol) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Does lcn lie in the section of $Bitmap we already have cached? */
+ if ((bmplcn <0 ) || (lcn < bmplcn) || (lcn >= (bmplcn + (sizeof(buffer) << 3)))) {
+#ifdef DEBUG_NTFS
+ log_debug("Bit lies outside cache.\n");
+#endif
+ attr = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
+ if (!attr) {
+ log_error("Couldn't open $Bitmap\n");
+ return -1;
+ }
+
+ /* Mark the buffer as in use, in case the read is shorter. */
+ memset(buffer, 0xFF, sizeof(buffer));
+ bmplcn = lcn & (~((sizeof(buffer) << 3) - 1));
+
+ if (ntfs_attr_pread(attr, (bmplcn>>3), sizeof(buffer), buffer) < 0) {
+ log_error("Couldn't read $Bitmap\n");
+ ntfs_attr_close(attr);
+ return -1;
+ }
+#ifdef DEBUG_NTFS
+ log_debug("Reloaded bitmap buffer.\n");
+#endif
+ ntfs_attr_close(attr);
+ }
+
+ bit = 1 << (lcn & 7);
+ byte = (lcn >> 3) & (sizeof(buffer) - 1);
+#ifdef DEBUG_NTFS
+ log_debug("cluster = %lld, bmplcn = %lld, byte = %d, bit = %d, in use %d\n", lcn, bmplcn, byte, bit, buffer[byte] & bit);
+#endif
+ return (buffer[byte] & bit);
+}
+
+#endif