Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/libntfs
In directory usw-pr-cvs1:/tmp/cvs-serv20229
Modified Files:
Makefile.am Makefile.in attrib.c disk_io.c mft.c mst.c
unistr.c volume.c
Removed Files:
bitmap.c
Log Message:
Cleanup library code. Throw away unused stuff.
Index: Makefile.am
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/Makefile.am,v
retrieving revision 1.9
retrieving revision 1.10
diff -U2 -r1.9 -r1.10
--- Makefile.am 6 Dec 2001 01:14:52 -0000 1.9
+++ Makefile.am 14 Apr 2002 14:08:29 -0000 1.10
@@ -22,11 +22,9 @@
attrib.c \
bootsect.c \
- bitmap.c \
mft.c \
volume.c \
disk_io.c \
- ntfs_rec.c \
- unistr.c \
- ntfsd.c
+ mst.c \
+ unistr.c
INCLUDES = $(linux_ntfsincludedir) $(all_includes)
Index: Makefile.in
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/Makefile.in,v
retrieving revision 1.13
retrieving revision 1.14
diff -U2 -r1.13 -r1.14
--- Makefile.in 26 Jan 2002 04:32:35 -0000 1.13
+++ Makefile.in 14 Apr 2002 14:08:29 -0000 1.14
@@ -106,11 +106,9 @@
attrib.c \
bootsect.c \
- bitmap.c \
mft.c \
volume.c \
disk_io.c \
- ntfs_rec.c \
- unistr.c \
- ntfsd.c
+ mst.c \
+ unistr.c
@@ -125,6 +123,6 @@
LIBS = @LIBS@
libntfs_la_LIBADD =
-libntfs_la_OBJECTS = attrib.lo bootsect.lo bitmap.lo mft.lo volume.lo \
-disk_io.lo ntfs_rec.lo unistr.lo ntfsd.lo
+libntfs_la_OBJECTS = attrib.lo bootsect.lo mft.lo volume.lo disk_io.lo \
+mst.lo unistr.lo
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -138,7 +136,6 @@
TAR = gtar
GZIP_ENV = --best
-DEP_FILES = .deps/attrib.P .deps/bitmap.P .deps/bootsect.P \
-.deps/disk_io.P .deps/mft.P .deps/ntfs_rec.P .deps/ntfsd.P \
-.deps/unistr.P .deps/volume.P
+DEP_FILES = .deps/attrib.P .deps/bootsect.P .deps/disk_io.P .deps/mft.P \
+.deps/mst.P .deps/unistr.P .deps/volume.P
SOURCES = $(libntfs_la_SOURCES)
OBJECTS = $(libntfs_la_OBJECTS)
Index: attrib.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/attrib.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -U2 -r1.16 -r1.17
--- attrib.c 13 Jun 2001 00:40:49 -0000 1.16
+++ attrib.c 14 Apr 2002 14:08:29 -0000 1.17
@@ -4,5 +4,5 @@
* attrib.c - Attribute handling code. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
@@ -35,108 +35,5 @@
#include "support.h"
#include "mft.h"
-
-int write_non_resident_attr(attr *a)
-{
- return -ENOTSUP;
-}
-
-int ntfs_flush_attr(attr *a)
-{
- int err = 0;
-
- if (!AttrDirty(a) || !AttrMapped(a))
- return 0;
- if (!AttrNonResident(a)) {
- /* Resident, just flush the mft entry. */
- if (err = ntfs_flush_mft_entry(a->a_m_entry))
- return err;
- ClearAttrDirty(a);
- } else /* Non-resident, write out to disk. */
- err = write_non_resident_attr(a);
- ntfs_flush();
- return err;
-}
-
-BOOL __set_attr_dirty(attr *a)
-{
- ntfs_volume *v;
-
- /* If resident just mark mft entry as dirty. */
- if (!AttrNonResident(a)) {
- ntfs_set_mft_entry_dirty(a->a_m_entry);
- return;
- }
- /* It is non-resident so add to dirty list. */
- v = a->a_vol;
- list_add_tail(&a->a_dirty_list, &v->dirty_attrs);
- v->nr_dirty_attrs++;
- return TRUE;
-}
-
-__inline__ attr *__allocate_attr(void)
-{
- attr *a = (attr *)malloc(sizeof(attr));
- if (!a)
- return NULL;
- memset(a, 0, sizeof(attr));
- INIT_LIST_HEAD(&a->a_dirty_list);
- return a;
-}
-
-__inline__ int __free_attr(attr *a)
-{
- if (a->a_count || AttrDirty(a) || AttrMapped(a))
- return -EBUSY;
- if (a->a_run_list)
- free(a->a_run_list);
- free(a);
- return 0;
-}
-
-int __map_attr_value(attr *a)
-{
- if (!AttrNonResident(a)) {
- }
- return -ENOTSUP;
-}
-
-int __unmap_attr_value(attr *a)
-{
- if (!AttrMapped(a))
- return 0;
- return -ENOTSUP;
-}
-
-int insert_attr(mft_entry *me, attr **a, ATTR_RECORD *arec, attr_val *aval,
- const BOOL dirty, const BOOL nonresident, run_list *arl,
- const BOOL inattrlist, ATTR_LIST_ENTRY *alist,
- ATTR_LIST_ENTRY *alistentry, const BOOL inextrecord)
-{
- attr *aent;
-
- if (!*a && !(*a = __allocate_attr()))
- return -errno;
- aent = *a;
- aent->a_rec = arec;
- if (aval) {
- if (nonresident) {
- aent->a_run_list = arl;
- SetAttrNonResident(aent);
- }
- aent->a_val = aval;
-
- } else {
- if (__map_attr_value(aent)) {
- // error
- }
- }
-
- return -ENOTSUP;
-}
-
-int remove_attr(attr *a)
-{
- return -ENOTSUP;
-}
+#include "debug.h"
/**
@@ -194,5 +91,5 @@
#ifdef DEBUG
if (!ctx || !ctx->mrec || !ctx->attr) {
- fprintf(stderr, "find_attr() received NULL pointer!\n");
+ Dputs("find_attr() received NULL pointer!");
return FALSE;
}
@@ -285,7 +182,5 @@
}
}
-#ifdef DEBUG
- fprintf(stderr, "find_attr(): File is corrupt. Run chkdsk.\n");
-#endif
+ Dputs("find_attr(): File is corrupt. Run chkdsk.");
return FALSE;
}
@@ -316,11 +211,11 @@
#ifdef DEBUG
if (!ctx || !ctx->mrec) {
- fprintf(stderr, "find_first_attr() received NULL pointer!\n");
+ Dputs("find_first_attr() received NULL pointer!");
return FALSE;
}
if (ctx->attr)
- fprintf(stderr, "find_first_attr(): received non-NULL "
- "attribute pointer.\nThis will be overwritten "
- "resulting in possible memory leakage.\n");
+ Dprintf("find_first_attr(): received non-NULL attribute "
+ "pointer.\nThis will be overwritten resulting "
+ "in possible memory leakage.\n");
#endif
m = ctx->mrec;
@@ -331,7 +226,5 @@
return find_attr(type, name, name_len, ic, upcase, upcase_len,
val, val_len, ctx);
-#ifdef DEBUG
- fprintf(stderr, "find_first_attr(): file is corrupt.");
-#endif
+ Dputs("find_first_attr(): file is corrupt.");
return FALSE;
}
@@ -848,4 +741,87 @@
errno = ENOENT;
return 0;
+}
+
+/**
+ * init_attr_search_ctx - initialize an attribute search context
+ * @ctx: attribute search context to initialize
+ * @ni: ntfs inode with which to initialize the search context
+ * @mrec: mft record with which to initialize the search context
+ *
+ * Initialize the attribute search context @ctx with @ni and @mrec.
+ */
+static __inline__ void init_attr_search_ctx(attr_search_context *ctx,
+ ntfs_inode *ni, MFT_RECORD *mrec)
+{
+ ctx->mrec = mrec;
+ /* Sanity checks are performed elsewhere. */
+ ctx->attr = (ATTR_RECORD*)((char*)mrec +
+ le16_to_cpu(mrec->attrs_offset));
+ ctx->is_first = TRUE;
+ ctx->ntfs_ino = ni;
+ ctx->al_entry = NULL;
+ ctx->base_ntfs_ino = NULL;
+ ctx->base_mrec = NULL;
+ ctx->base_attr = NULL;
+}
+
+/**
+ * reinit_attr_search_ctx - reinitialize an attribute search context
+ * @ctx: attribute search context to reinitialize
+ *
+ * Reinitialize the attribute search context @ctx, unmapping an associated
+ * extent mft record if present, and initialize the search context again.
+ *
+ * This is used when a search for a new attribute is being started to reset
+ * the search context to the beginning.
+ */
+void reinit_attr_search_ctx(attr_search_context *ctx)
+{
+ if (!ctx->base_ntfs_ino) {
+ /* No attribute list. */
+ ctx->is_first = TRUE;
+ /* Sanity checks are performed elsewhere. */
+ ctx->attr = (ATTR_RECORD*)((char*)ctx->mrec +
+ le16_to_cpu(ctx->mrec->attrs_offset));
+ return;
+ } /* Attribute list. */
+ if (ctx->ntfs_ino != ctx->base_ntfs_ino)
+ fprintf(stderr, __FUNCTION__ "(): EEEEEK!\n");
+ // unmap_mft_record(READ, ctx->ntfs_ino);
+ init_attr_search_ctx(ctx, ctx->base_ntfs_ino, ctx->base_mrec);
+ return;
+}
+
+/**
+ * get_attr_search_ctx - allocate and initialize a new attribute search context
+ * @ctx: address of pointer in which to return the new search context
+ * @ni: ntfs inode with which to initialize the search context
+ * @mrec: mft record with which to initialize the search context
+ *
+ * Allocate a new attribute search context, initialize it with @ni and @mrec,
+ * and return it. Return NULL on error with errno set to ENOMEM.
+ */
+attr_search_context *get_attr_search_ctx(ntfs_inode *ni, MFT_RECORD *mrec)
+{
+ attr_search_context *ctx = malloc(sizeof(attr_search_context));
+ if (ctx)
+ init_attr_search_ctx(ctx, ni, mrec);
+ return ctx;
+}
+
+/**
+ * put_attr_search_ctx - release an attribute search context
+ * @ctx: attribute search context to free
+ *
+ * Release the attribute search context @ctx, unmapping an associated extent
+ * mft record if present.
+ */
+void put_attr_search_ctx(attr_search_context *ctx)
+{
+ if (ctx->base_ntfs_ino && ctx->ntfs_ino != ctx->base_ntfs_ino)
+ fprintf(stderr, __FUNCTION__ "(): EEEEEK!\n");
+ //unmap_mft_record(READ, ctx->ntfs_ino);
+ free(ctx);
+ return;
}
Index: disk_io.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/disk_io.c,v
retrieving revision 1.14
retrieving revision 1.15
diff -U2 -r1.14 -r1.15
--- disk_io.c 1 Jun 2001 02:07:26 -0000 1.14
+++ disk_io.c 14 Apr 2002 14:08:30 -0000 1.15
@@ -4,5 +4,5 @@
* disk_io.c - Disk io functions. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
Index: mft.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/mft.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -U2 -r1.12 -r1.13
--- mft.c 14 Apr 2002 13:34:49 -0000 1.12
+++ mft.c 14 Apr 2002 14:08:30 -0000 1.13
@@ -4,5 +4,5 @@
* mft.c - Mft record handling code. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
Index: mst.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/mst.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -U2 -r1.1 -r1.2
--- mst.c 14 Apr 2002 13:28:19 -0000 1.1
+++ mst.c 14 Apr 2002 14:08:30 -0000 1.2
@@ -2,7 +2,7 @@
* $Id$
*
- * ntfs_rec.c - NTFS record handling code. Part of the Linux-NTFS project.
+ * mst.c - Multi sector fixup handling code. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
Index: unistr.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/unistr.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -U2 -r1.7 -r1.8
--- unistr.c 9 Jun 2001 16:31:13 -0000 1.7
+++ unistr.c 14 Apr 2002 14:08:30 -0000 1.8
@@ -4,5 +4,5 @@
* unistr.c - Unicode string handling. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
@@ -26,4 +26,5 @@
#include "types.h"
#include "unistr.h"
+#include "debug.h"
/*
@@ -108,5 +109,5 @@
#ifdef DEBUG
if (!name1 || !name2 || ic && !upcase && upcase_len) {
- fprintf(stderr, "ntfs_collate_names received NULL pointer!\n");
+ Dputs("ntfs_collate_names received NULL pointer!");
exit(1);
}
@@ -161,5 +162,5 @@
#ifdef DEBUG
if (!s1 || !s2) {
- fprintf(stderr, "ntfs_wcsncmp() received NULL pointer!\n");
+ Dputs("ntfs_wcsncmp() received NULL pointer!");
exit(1);
}
@@ -204,5 +205,5 @@
#ifdef DEBUG
if (!s1 || !s2 || !upcase) {
- fprintf(stderr, "ntfs_wcsncasecmp() received NULL pointer!\n");
+ Dputs("ntfs_wcsncasecmp() received NULL pointer!");
exit(1);
}
Index: volume.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/libntfs/volume.c,v
retrieving revision 1.20
retrieving revision 1.21
diff -U2 -r1.20 -r1.21
--- volume.c 12 Apr 2002 15:23:47 -0000 1.20
+++ volume.c 14 Apr 2002 14:08:30 -0000 1.21
@@ -4,5 +4,5 @@
* volume.c - NTFS volume handling code. Part of the Linux-NTFS project.
*
- * Copyright (c) 2000,2001 Anton Altaparmakov.
+ * Copyright (c) 2000-2002 Anton Altaparmakov.
*
* This program/include file is free software; you can redistribute it and/or
@@ -30,5 +30,4 @@
#include "types.h"
-#include "list.h"
#include "volume.h"
#include "support.h"
@@ -40,49 +39,13 @@
#include "debug.h"
-/**
- * ntfs_sync_volume - sync a mounted ntfs volume to physical storage
- * @vol: ntfs volume to sync
- *
- * Sync a mounted ntfs volumes to physical storage.
- *
- * Return zero on success and -1 if one or more mft records and/or
- * non-resident attributes were busy, and could not be committed to disk.
- */
-int ntfs_sync_volume(ntfs_volume *vol)
-{
- struct list_head *tmp;
- int s = 0;
-
- list_for_each(tmp, &vol->dirty_attrs) {
- if (!ntfs_flush_attr(list_entry(tmp, attr, a_dirty_list)) || s)
- continue;
- s = -1;
- }
- list_for_each(tmp, &vol->dirty_mft_entries) {
- if (!ntfs_flush_mft_entry(list_entry(tmp, mft_entry,
- m_dirty_list)) || s)
- continue;
- s = -1;
- }
- return s;
-}
-
-static __inline__ ntfs_volume *__allocate_ntfs_volume()
+static ntfs_volume *__allocate_ntfs_volume(void)
{
- ntfs_volume *v = (ntfs_volume *)malloc(sizeof(ntfs_volume));
- if (!v)
- return NULL;
- memset(v, 0, sizeof(ntfs_volume));
- INIT_LIST_HEAD(&v->open_files);
- INIT_LIST_HEAD(&v->mft_entries);
- INIT_LIST_HEAD(&v->dirty_mft_entries);
- INIT_LIST_HEAD(&v->dirty_attrs);
- return v;
+ return (ntfs_volume*)calloc(1, sizeof(ntfs_volume));
}
-static __inline__ int __free_ntfs_volume(ntfs_volume *v)
+static void __release_ntfs_volume(ntfs_volume *v)
{
- if (v->nr_open_files || v->nr_mft_entries || v->nr_dirty_attrs)
- return -1;
+ if (v->fd)
+ close(v->fd);
if (v->dev_name)
free(v->dev_name);
@@ -98,35 +61,34 @@
free(v->upcase);
free(v);
- return 0;
}
/**
- * __init_ntfs_volume - initialize an ntfs_volume
- * @v: ntfs_volume to initialize
+ * ntfs_mount - open ntfs volume
+ * @name: name of device/file to open
+ * @rwflag: optional mount flags
+ *
+ * This function mounts an ntfs volume. @name should contain the name of the
+ * device/file to mount as the ntfs volume.
+ *
+ * @rwflags is an optional second parameter. The same flags are used as for
+ * the mount system call (man 2 mount). Currently only the following flag
+ * is implemented:
+ * MS_RDONLY - mount volume read-only
+ *
+ * The function opens the device or file @name and verifies that it contains a
+ * valid bootsector. Then, it allocates an ntfs_volume structure and initializes
+ * some of the values inside the structure from the information stored in the
+ * bootsector. It proceeds to load the necessary system files and completes
+ * setting up the structure.
*
- * Before we can use any of the libntfs higher level functions to open files,
- * load mft records and such like, we need to load the system files but these
- * are files. Catch 22!
- *
- * So we have to cheat, i.e. we setup a minumum set of fields in @v to more or
- * less faked values, just to allow us to use the library functions to open the
- * system files. Perhaps not the most beautiful solution but IMO the most
- * elegant one. Otherwise we would have to keep around special functions to work
- * without all the information required or we would need to do everything
- * manually (as it used to be in the early days of Linux-NTFS).
- *
- * Using a fake-it approach means we still use the same code for everything,
- * even for meta data, which is way cool. It does mean we have some uglyness in
- * the mount code path but hey, it's just the mount... All the real fun comes
- * after mounting anyway.
+ * ntfs_mount() returns a pointer to the allocated ntfs_volume structure.
+ * On error, the return value is NULL and errno is set appropriately.
*
- * Once we have opened the system files we do the proper initialisation of @v,
- * disposing off the faked info as we go along.
+ * Note, that a copy is made of @name, and hence it can be discarded as
+ * soon as the function returns.
+ *
+ * FIXME: Should document all error codes that can be returned and what each
+ * means.
*/
-int __init_ntfs_volume(ntfs_volume *v)
-{
- return 0;
-}
-
ntfs_volume *ntfs_mount(const char *name, unsigned long rwflag)
{
@@ -136,4 +98,5 @@
NTFS_BOOT_SECTOR *bs = NULL;
MFT_RECORD *mb = NULL;
+ attr_search_context *ctx = NULL;
ATTR_RECORD *a;
VOLUME_INFORMATION *vinf;
@@ -145,7 +108,11 @@
__u8 sectors_per_cluster, bits;
__s8 c;
- attr_search_context ctx;
MFT_REF mref;
- int err, ro = rwflag & MS_RDONLY;
+ int err, eo, ro = rwflag & MS_RDONLY;
+#ifdef DEBUG
+ BOOL debug = 1;
+#else
+ BOOL debug = 0;
+#endif
if (!name) {
@@ -155,28 +122,16 @@
/* Allocate the volume structure. */
vol = __allocate_ntfs_volume();
- if (!vol) {
- perror("Error allocating memory for ntfs volume structure");
- errno = ENOMEM;
+ if (!vol)
goto error_exit;
- }
/* Make a copy of the partition name. */
- if (!(vol->dev_name = strdup(name))) {
- perror("Error allocating memory for partition name");
- errno = ENOMEM;
+ if (!(vol->dev_name = strdup(name)))
goto error_exit;
- }
/* Allocate the boot sector structure. */
- if (!(bs = (NTFS_BOOT_SECTOR *)malloc(sizeof(NTFS_BOOT_SECTOR)))) {
- Vputs(FAILED);
- perror("Error allocating memory for bootsector");
- errno = ENOMEM;
+ if (!(bs = (NTFS_BOOT_SECTOR *)malloc(sizeof(NTFS_BOOT_SECTOR))))
goto error_exit;
- }
- Vprintf("Reading bootsector... ");
+ Dprintf("Reading bootsector... ");
if ((vol->fd = open(name, ro ? O_RDONLY: O_RDWR)) == -1) {
- int eo = errno;
- Vputs(FAILED);
- perror("Error opening partition file");
- errno = eo;
+ Dputs(FAILED);
+ Dperror("Error opening partition file");
goto error_exit;
}
@@ -184,42 +139,30 @@
br = ntfs_pread(vol->fd, bs, sizeof(NTFS_BOOT_SECTOR), 1, 0);
if (br != 1) {
- int eo = errno;
- Vputs(FAILED);
-#define ESTR "Error reading bootsector"
- if (br == -1) {
- perror(ESTR);
- errno = eo;
- } else if (!br) {
- fprintf(stderr, "Error: partition is smaller than " \
- "bootsector size. Weird!\n");
- errno = EINVAL;
- } else {
- fprintf(stderr, ESTR ": unknown error\n");
+ Dputs(FAILED);
+ if (br != -1)
errno = EINVAL;
- }
-#undef ESTR
+ if (!br)
+ Dputs("Error: partition is smaller than bootsector "
+ "size. Weird!");
+ else
+ Dperror("Error reading bootsector");
goto error_exit;
}
- Vputs(OK);
-#ifdef DEBUG
- if (!is_boot_sector_ntfs(bs, 0)) {
-#else
- if (!is_boot_sector_ntfs(bs, 1)) {
-#endif
- fprintf(stderr, "Error: %s is not a valid NTFS partition!\n",
- name);
+ Dputs(OK);
+ if (!is_boot_sector_ntfs(bs, !debug)) {
+ Dprintf("Error: %s is not a valid NTFS partition!\n", name);
errno = EINVAL;
goto error_exit;
}
- /* The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
+ /*
+ * The bounds checks on mft_lcn and mft_mirr_lcn (i.e. them being
* below or equal the number_of_clusters) really belong in the
- * is_boot_sector_ntfs but in this way we can just do this once. */
+ * is_boot_sector_ntfs but in this way we can just do this once.
+ */
sectors_per_cluster = bs->bpb.sectors_per_cluster;
-#ifdef DEBUG
- printf("NumberOfSectors = %Li\n", sle64_to_cpu(bs->number_of_sectors));
- printf("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
-#endif
+ Dprintf("NumberOfSectors = %Li\n", sle64_to_cpu(bs->number_of_sectors));
+ Dprintf("SectorsPerCluster = 0x%x\n", sectors_per_cluster);
if (sectors_per_cluster & sectors_per_cluster - 1) {
- fprintf(stderr, "Error: %s is not a valid NTFS partition! "
+ Dprintf("Error: %s is not a valid NTFS partition! "
"sectors_per_cluster is not a power of 2.\n",
name);
@@ -228,17 +171,15 @@
}
vol->number_of_clusters = sle64_to_cpu(bs->number_of_sectors) >>
- ffs(sectors_per_cluster) - 1;
+ ffs(sectors_per_cluster) - 1;
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn);
-#ifdef DEBUG
- printf("MFT LCN = %Li\n", vol->mft_lcn);
- printf("MFTMirr LCN = 0x%Li\n", vol->mftmirr_lcn);
-#endif
- if ((vol->mft_lcn > vol->number_of_clusters) ||
- (vol->mftmirr_lcn > vol->number_of_clusters)) {
- fprintf(stderr, "Error: %s is not a valid NTFS partition! "
- "($Mft LCN or\n$MftMirr LCN is greater than "
- "the number of clusters!\n", name);
+ Dprintf("MFT LCN = %Li\n", vol->mft_lcn);
+ Dprintf("MFTMirr LCN = 0x%Li\n", vol->mftmirr_lcn);
+ if (vol->mft_lcn > vol->number_of_clusters ||
+ vol->mftmirr_lcn > vol->number_of_clusters) {
+ Dprintf("Error: %s is not a valid NTFS partition! ($Mft LCN "
+ "or\n$MftMirr LCN is greater than the number "
+ "of clusters!\n", name);
errno = EINVAL;
goto error_exit;
@@ -247,5 +188,5 @@
le16_to_cpu(bs->bpb.bytes_per_sector);
if (vol->cluster_size & vol->cluster_size - 1) {
- fprintf(stderr, "Error: %s is not a valid NTFS partition! "
+ Dprintf("Error: %s is not a valid NTFS partition! "
"cluster_size is not a power of 2.\n", name);
errno = EINVAL;
@@ -259,9 +200,7 @@
*/
c = bs->clusters_per_mft_record;
-#ifdef DEBUG
- printf("ClusterSize = 0x%x\n", vol->cluster_size);
- printf("ClusterSizeBits = %u\n", vol->cluster_size_bits);
- printf("ClustersPerMftRecord = 0x%x\n", c);
-#endif
+ Dprintf("ClusterSize = 0x%x\n", vol->cluster_size);
+ Dprintf("ClusterSizeBits = %u\n", vol->cluster_size_bits);
+ Dprintf("ClustersPerMftRecord = 0x%x\n", c);
/*
* When clusters_per_mft_record is negative, it means that it is to
@@ -275,5 +214,5 @@
vol->mft_record_size = vol->cluster_size * c;
if (vol->mft_record_size & vol->mft_record_size - 1) {
- fprintf(stderr, "Error: %s is not a valid NTFS partition! "
+ Dprintf("Error: %s is not a valid NTFS partition! "
"mft_record_size is not a power of 2.\n", name);
errno = EINVAL;
@@ -281,75 +220,66 @@
}
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
- vol->max_open_files = 10000;
-#ifdef DEBUG
- printf("MftRecordSize = 0x%x\n", vol->mft_record_size);
- printf("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
- printf("max_open_files set to %u\n", vol->max_open_files);
-#endif
+ Dprintf("MftRecordSize = 0x%x\n", vol->mft_record_size);
+ Dprintf("MftRecordSizeBits = %u\n", vol->mft_record_size_bits);
/* Start with $Mft. */
- Vprintf("Loading $Mft... ");
- if (!(mb = (MFT_RECORD *)malloc(vol->mft_record_size))) {
- Vputs(FAILED);
- perror("Error allocating memory for $Mft");
- errno = ENOMEM;
+ Dprintf("Loading $Mft... ");
+ if (!(mb = (MFT_RECORD*)malloc(vol->mft_record_size))) {
+ Dputs(FAILED);
+ Dperror("Error allocating memory for $Mft");
goto error_exit;
}
/* Can't use any of the higher level functions yet! */
- br = mst_pread(vol->fd, (char *)mb, vol->mft_record_size, 1,
+ br = mst_pread(vol->fd, (char*)mb, vol->mft_record_size, 1,
vol->mft_lcn << vol->cluster_size_bits);
if (br != 1) {
- Vputs(FAILED);
-#define ESTR "Error reading $Mft"
+ Dputs(FAILED);
if (br == -1)
- perror(ESTR);
+ Dperror("Error reading $Mft");
else if (br < 4)
- fprintf(stderr, "Error: $Mft LCN is outside of "
- "the partition?!?\n");
+ Dputs("Error: $Mft is outside of the partition?!?");
else
- fprintf(stderr, ESTR ": unknown error\n");
-#undef ESTR
+ Dputs("Error reading $Mft.");
errno = EIO;
goto error_exit;
}
- if (is_baad_record(mb)) {
- Vputs(FAILED);
- fprintf(stderr, "Error: Incomplete multi sector "
- "transfer detected in $Mft.\nCannot "
- "handle this yet. )-:\n");
+ if (is_baad_recordp(mb)) {
+ Dputs(FAILED);
+ Dputs("Error: Incomplete multi sector transfer detected in "
+ "$Mft.");
errno = EIO;
goto error_exit;
}
if (!is_mft_recordp(mb)) {
- Vputs(FAILED);
- fprintf(stderr, "Error: Invalid mft record for $Mft.\n"
- "Cannot handle this yet. )-:\n");
+ Dputs(FAILED);
+ Dputs("Error: Invalid mft record for $Mft.");
errno = EIO;
goto error_exit;
}
/* Find the bitmap attribute. */
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
- ctx.attr = (ATTR_RECORD*)((char*)mb + le16_to_cpu(mb->attrs_offset));
- if (p2n(ctx.attr) < p2n(mb) ||
- (char*)ctx.attr > (char*)mb + vol->mft_record_size) {
- Vputs(FAILED);
- fprintf(stderr, "Error: corrupt mft record for $Mft.\n"
- "Cannot handle this yet. )-:\n");
+ ctx = get_attr_search_ctx(NULL, mb);
+ if (!ctx) {
+ Dputs(FAILED);
+ Dperror("Failed to allocate attribute search context");
+ goto error_exit;
+ }
+ if (p2n(ctx->attr) < p2n(mb) ||
+ (char*)ctx->attr > (char*)mb + vol->mft_record_size) {
+ Dputs(FAILED);
+ Dputs("Error: corrupt mft record for $Mft.");
errno = EIO;
goto error_exit;
}
- ctx.is_first = TRUE;
- if (!find_attr($BITMAP, NULL, 0, 0, NULL, 0, NULL, 0, &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "$bitmap attribute not found in $Mft?!?\n");
+ if (!find_attr($BITMAP, NULL, 0, 0, NULL, 0, NULL, 0, ctx)) {
+ Dputs(FAILED);
+ Dputs("$bitmap attribute not found in $Mft?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Get attribute value size and allocate a big enough buffer. */
l = get_attribute_value_length(a);
if (!l) {
- Vputs(OK);
- puts("Error: $bitmap in $Mft has zero length! T'is weird!");
+ Dputs(OK);
+ Dputs("Error: $bitmap in $Mft has zero length?!?");
errno = EIO;
goto error_exit;
@@ -357,18 +287,18 @@
vol->mft_bitmap = (__u8*)malloc(l);
if (!vol->mft_bitmap) {
- Vputs(FAILED);
- puts("Not enough memory to load bitmap attribute from $Mft.");
- errno = ENOMEM;
+ Dputs(FAILED);
+ Dputs("Not enough memory to load bitmap attribute from $Mft.");
goto error_exit;
}
/* Read in the bitmap attribute value into the buffer. */
if (l != get_attribute_value(vol, mb, a, vol->mft_bitmap)) {
- Vputs(FAILED);
- puts("Amount of data read does not correspond to expected "
- "length!");
+ Dputs(FAILED);
+ Dputs("Amount of data read does not correspond to expected "
+ "length!");
errno = EIO;
goto error_exit;
}
-#ifdef DEBUG
+#if 0
+ // Output the mft bitmap. Can be useful when debugging write code.
{ int _i_;
printf("$MFT $BITMAP =\n");
@@ -380,21 +310,18 @@
#endif
/* Find the $DATA attribute in $Mft. */
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
- ctx.attr = (ATTR_RECORD*)((char*)mb + le16_to_cpu(mb->attrs_offset));
- ctx.is_first = TRUE;
- if (!find_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "$DATA attribute not found in $Mft?!?\n");
+ reinit_attr_search_ctx(ctx);
+ if (!find_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, ctx)) {
+ Dputs(FAILED);
+ Dputs("$DATA attribute not found in $Mft?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Determine the number of mft records in $Mft. */
vol->number_of_mft_records = a->data_size >> vol->mft_record_size_bits;
/* The $DATA attribute of the $Mft has to be non-resident. */
if (!a->non_resident) {
- Vputs(FAILED);
- fprintf(stderr, "$Mft $DATA attribute is resident!?!\n");
+ Dputs(FAILED);
+ Dputs("$Mft $DATA attribute is resident!?!");
errno = EINVAL;
goto error_exit;
@@ -403,37 +330,43 @@
vol->mft_runlist = decompress_run_list(a);
if (!vol->mft_runlist) {
- Vputs(FAILED);
- fprintf(stderr, "Error decompressing run list from $Mft $DATA"
- " attribute.\n");
+ Dputs(FAILED);
+ Dputs("Error decompressing run list from $Mft $DATA "
+ "attribute.");
errno = EINVAL;
goto error_exit;
}
- Vputs(OK);
+ Dputs(OK);
/* Done with the $Mft mft record. */
+ put_attr_search_ctx(ctx);
+ ctx = NULL;
free(mb);
mb = NULL;
/* Now load the bitmap from $Bitmap. */
- Vprintf("Loading $Bitmap... ");
+ Dprintf("Loading $Bitmap... ");
mref = (MFT_REF)FILE_$Bitmap;
- if (err = __read_file_record(vol, &mref, &mb, NULL)) {
- Vputs(FAILED);
+ if ((err = __read_file_record(vol, &mref, &mb, NULL))) {
+ Dputs(FAILED);
errno = -err;
goto error_exit;
}
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
+ ctx = get_attr_search_ctx(NULL, mb);
+ if (!ctx) {
+ Dputs(FAILED);
+ Dperror("Failed to allocate attribute search context");
+ goto error_exit;
+ }
/* Find the bitmap (it is in the $DATA attribute). */
- if (!find_first_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "bitmap attribute not found in $Bitmap?!?\n");
+ if (!find_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, ctx)) {
+ Dputs(FAILED);
+ Dputs("bitmap attribute not found in $Bitmap?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Get attribute value size and allocate a big enough buffer.*/
l = get_attribute_value_length(a);
if (!l) {
- Vputs(OK);
- puts("Error: bitmap in $Bitmap has zero length! T'is weird!");
+ Dputs(OK);
+ Dputs("Error: bitmap in $Bitmap has zero length?!?");
errno = EIO;
goto error_exit;
@@ -441,6 +374,6 @@
vol->lcn_bitmap = (__u8*)malloc(l);
if (!vol->lcn_bitmap) {
- Vputs(FAILED);
- puts("Not enough memory to load $Bitmap.");
+ Dputs(FAILED);
+ Dputs("Not enough memory to load $Bitmap.");
errno = ENOMEM;
goto error_exit;
@@ -448,47 +381,55 @@
/* Read in the bitmap attribute value into the buffer. */
if (l != get_attribute_value(vol, mb, a, vol->lcn_bitmap)) {
- Vputs(FAILED);
- puts("Amount of data read does not correspond to expected "
- "length!");
+ Dputs(FAILED);
+ Dputs("Amount of data read does not correspond to expected "
+ "length!");
errno = EIO;
goto error_exit;
}
/* Done with the $BitMap mft record. */
- Vputs(OK);
+ Dputs(OK);
+ put_attr_search_ctx(ctx);
+ ctx = NULL;
free(mb);
mb = NULL;
/* Now load the upcase table from $UpCase. */
- Vprintf("Loading $UpCase... ");
+ Dprintf("Loading $UpCase... ");
mref = (MFT_REF)FILE_$UpCase;
if (err = __read_file_record(vol, &mref, &mb, NULL)) {
- Vputs(FAILED);
+ Dputs(FAILED);
errno = -err;
goto error_exit;
}
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
+ ctx = get_attr_search_ctx(NULL, mb);
+ if (!ctx) {
+ Dputs(FAILED);
+ Dperror("Failed to allocate attribute search context");
+ goto error_exit;
+ }
/* Find the bitmap (it is in the $DATA attribute). */
- if (!find_first_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "$DATA attribute not found in $UpCase?!?\n");
+ if (!find_attr($DATA, NULL, 0, 0, NULL, 0, NULL, 0, ctx)) {
+ Dputs(FAILED);
+ Dputs("$DATA attribute not found in $UpCase?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Get attribute value size and allocate a big enough buffer.*/
l = get_attribute_value_length(a);
if (!l) {
- Vputs(FAILED);
- puts("Error: $DATA in $UpCase has zero length! T'is weird!");
+ Dputs(FAILED);
+ Dputs("Error: $DATA in $UpCase has zero length! T'is weird!");
errno = EIO;
goto error_exit;
}
- /* Note: Normally, the upcase table has a length equal to 65536
+ /*
+ * Note: Normally, the upcase table has a length equal to 65536
* 2-byte Unicode characters but allow for different cases, so no
* checks done. Just check we don't overflow 32-bits worth of Unicode
- * characters. */
+ * characters.
+ */
if (l & ~0x1ffffffffULL) {
- Vputs(FAILED);
- puts("Error: Upcase table is too big (max 32-bit allowed).");
+ Dputs(FAILED);
+ Dputs("Error: Upcase table is too big (max 32-bit allowed).");
errno = EINVAL;
goto error_exit;
@@ -497,13 +438,12 @@
vol->upcase = (uchar_t*)malloc(l);
if (!vol->upcase) {
- Vputs(FAILED);
- puts("Not enough memory to load $UpCase.");
- errno = ENOMEM;
+ Dputs(FAILED);
+ Dputs("Not enough memory to load $UpCase.");
goto error_exit;
}
/* Read in the $DATA attribute value into the buffer. */
if (l != get_attribute_value(vol, mb, a, (__u8*)vol->upcase)) {
- Vputs(FAILED);
- puts("Amount of data read does not correspond to expected "
+ Dputs(FAILED);
+ Dputs("Amount of data read does not correspond to expected "
"length!");
errno = EIO;
@@ -511,32 +451,39 @@
}
/* Done with the $UpCase mft record. */
- Vputs(OK);
+ Dputs(OK);
+ put_attr_search_ctx(ctx);
+ ctx = NULL;
free(mb);
mb = NULL;
/* Now load $Volume and set the version information and flags in the
* vol structure accordingly. */
- Vprintf("Loading $Volume... ");
+ Dprintf("Loading $Volume... ");
mref = (MFT_REF)FILE_$Volume;
if (err = __read_file_record(vol, &mref, &mb, NULL)) {
- Vputs(FAILED);
+ Dputs(FAILED);
errno = -err;
goto error_exit;
}
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
+ ctx = get_attr_search_ctx(NULL, mb);
+ if (!ctx) {
+ Dputs(FAILED);
+ Dperror("Failed to allocate attribute search context");
+ goto error_exit;
+ }
/* Find the $VOLUME_INFORMATION attribute. */
- if (!find_first_attr($VOLUME_INFORMATION, NULL, 0, 0, NULL, 0, NULL, 0,
- &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "$VOLUME_INFORMATION attribute not found in "
- "$Volume?!?\n");
+ if (!find_attr($VOLUME_INFORMATION, NULL, 0, 0, NULL, 0, NULL, 0,
+ ctx)) {
+ Dputs(FAILED);
+ Dputs("$VOLUME_INFORMATION attribute not found in "
+ "$Volume?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Has to be resident. */
if (a->non_resident) {
- fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION must " \
- "be resident (and it isn't)!\n");
+ Dputs(FAILED);
+ Dputs("Error: Attribute $VOLUME_INFORMATION must be resident "
+ "(and it isn't)!");
errno = EIO;
goto error_exit;
@@ -546,10 +493,10 @@
/* Sanity checks. */
if ((char*)vinf + le32_to_cpu(a->value_length) >
- le16_to_cpu(mb->bytes_in_use) + (char*)mb ||
- le16_to_cpu(a->value_offset) +
- le32_to_cpu(a->value_length) >
- le32_to_cpu(a->length)) {
- fprintf(stderr, "Error: Attribute $VOLUME_INFORMATION in " \
- "$Volume is corrupt!\n");
+ le16_to_cpu(mb->bytes_in_use) + (char*)mb ||
+ le16_to_cpu(a->value_offset) +
+ le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) {
+ Dputs(FAILED);
+ Dputs("Error: Attribute $VOLUME_INFORMATION in $Volume is "
+ "corrupt!");
errno = EIO;
goto error_exit;
@@ -562,38 +509,38 @@
vol->flags = vinf->flags;
/* Find the $VOLUME_NAME attribute. */
- memset(&ctx, 0, sizeof(attr_search_context));
- ctx.mrec = mb;
- if (!find_first_attr($VOLUME_NAME, NULL, 0, 0, NULL, 0, NULL, 0,
- &ctx)) {
- Vputs(FAILED);
- fprintf(stderr, "$VOLUME_NAME attribute not found in "
- "$Volume?!?\n");
+ reinit_attr_search_ctx(ctx);
+ if (!find_attr($VOLUME_NAME, NULL, 0, 0, NULL, 0, NULL, 0, ctx)) {
+ Dputs(FAILED);
+ Dputs("$VOLUME_NAME attribute not found in $Volume?!?");
errno = EIO;
goto error_exit;
}
- a = ctx.attr;
+ a = ctx->attr;
/* Has to be resident. */
if (a->non_resident) {
- fprintf(stderr, "Error: Attribute $VOLUME_NAME must " \
- "be resident (and it isn't)!\n");
+ Dputs(FAILED);
+ Dputs("Error: Attribute $VOLUME_NAME must be resident!");
errno = EIO;
goto error_exit;
}
/* Get a pointer to the value of the attribute. */
- vol->vol_name = malloc(le32_to_cpu(a->value_length) / 2 + 1);
+ vname = (uchar_t*)(le16_to_cpu(a->value_offset) + (char*)a);
+ u = le32_to_cpu(a->value_length) / 2;
+ /* Convert the Unicode volume name to ASCII. */
+ // FIXME: We need proper locale support and Unicode -> current locale
+ // conversion! (AIA)
+ vol->vol_name = malloc(le32_to_cpu(a->value_length) / 2 + 1);
if (!vol->vol_name) {
- fprintf(stderr, "Error: Unable to allocate memory for volume "
- "name!\n");
- errno = ENOMEM;
+ Dputs(FAILED);
+ Dputs("Error: Unable to allocate memory for volume name!");
goto error_exit;
}
- vname = (uchar_t*)(le16_to_cpu(a->value_offset) + (char*)a);
- u = le32_to_cpu(a->value_length) / 2;
- for (j = 0; j < u; j++) {
+ for (j = 0; j < u; j++)
vol->vol_name[j] = le16_to_cpu(vname[j]);
- }
vol->vol_name[u] = '\0';
- Vputs(OK);
+ Dputs(OK);
+ put_attr_search_ctx(ctx);
+ ctx = NULL;
free(mb);
mb = NULL;
@@ -604,33 +551,43 @@
error_exit:
- {
- int eo = errno;
-
- if (bs)
- free(bs);
- if (mb)
- free(mb);
- if (vol) {
- if (vol->fd)
- close(vol->fd);
- if (vol->dev_name)
- free(vol->dev_name);
- if (vol->vol_name)
- free(vol->vol_name);
- if (vol->lcn_bitmap)
- free(vol->lcn_bitmap);
- if (vol->mft_bitmap)
- free(vol->mft_bitmap);
- if (vol->mft_runlist)
- free(vol->mft_runlist);
- if (vol->upcase)
- free(vol->upcase);
- free(vol);
- }
- errno = eo;
- }
+ eo = errno;
+ if (bs)
+ free(bs);
+ if (ctx)
+ put_attr_search_ctx(ctx);
+ if (mb)
+ free(mb);
+ if (vol)
+ __release_ntfs_volume(vol);
+ errno = eo;
return NULL;
}
+/**
+ * ntfs_umount - close ntfs volume
+ * @vol: address of ntfs_volume structure of volume to close
+ * @force: if true force close the volume even if it is busy
+ *
+ * Deallocate all structures (including @vol itself) associated with the ntfs
+ * volume @vol.
+ *
+ * Return true on success. On error return false with errno set appropriately
+ * (most likely to one of EAGAIN, EBUSY or EINVAL). The EAGAIN error means that
+ * an operation is in progress and if you try the close later the operation
+ * might be completed and the close succeed.
+ *
+ * If @force is true (i.e. not zero) this function will close the volume even
+ * if this means that data might be lost. In this case the function always
+ * returns true.
+ *
+ * @vol must have previously been returned by a call to ntfs_mount().
+ *
+ * @vol itself is deallocated and should no longer be dereferenced after this
+ * function returns success. If it returns an error then nothing has been done
+ * so it is safe to continue using @vol.
+ *
+ * FIXME: Should document all error codes that can be returned and what each
+ * means.
+ */
BOOL ntfs_umount(ntfs_volume *vol, const int force)
{
@@ -639,20 +596,5 @@
return FALSE;
}
- /* FIXME: Do the cleanup. */
- if (vol->fd)
- close(vol->fd);
- if (vol->dev_name)
- free(vol->dev_name);
- if (vol->vol_name)
- free(vol->vol_name);
- if (vol->lcn_bitmap)
- free(vol->lcn_bitmap);
- if (vol->mft_bitmap)
- free(vol->mft_bitmap);
- if (vol->mft_runlist)
- free(vol->mft_runlist);
- if (vol->upcase)
- free(vol->upcase);
- free(vol);
+ __release_ntfs_volume(vol);
return TRUE;
}
--- bitmap.c DELETED ---
|