Changes by: flatcap
Update of /cvsroot/linux-ntfs/linux-ntfs/ntfstools
In directory usw-pr-cvs1:/tmp/cvs-serv31369/ntfstools
Modified Files:
Makefile.am Makefile.in ntfsundelete.c ntfsundelete.h
Log Message:
lots of comments
Index: Makefile.am
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -U2 -r1.21 -r1.22
--- Makefile.am 30 Jun 2002 22:46:50 -0000 1.21
+++ Makefile.am 1 Jul 2002 13:30:28 -0000 1.22
@@ -6,6 +6,6 @@
endif
-bin_PROGRAMS = ntfsfix ntfsinfo # ntfsundelete ntfsdump_logfile dumplog
-sbin_PROGRAMS = mkntfs ntfslabel
+bin_PROGRAMS = ntfsfix ntfsinfo # ntfsdump_logfile dumplog
+sbin_PROGRAMS = mkntfs ntfslabel # ntfsundelete
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 ntfsundelete.8
Index: Makefile.in
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/Makefile.in,v
retrieving revision 1.27
retrieving revision 1.28
diff -U2 -r1.27 -r1.28
--- Makefile.in 30 Jun 2002 22:46:51 -0000 1.27
+++ Makefile.in 1 Jul 2002 13:30:28 -0000 1.28
@@ -92,6 +92,6 @@
@DEBUG_FALSE@AM_CFLAGS = @DEBUG_FALSE@-D_FILE_OFFSET_BITS=64
-bin_PROGRAMS = ntfsfix ntfsinfo # ntfsundelete ntfsdump_logfile dumplog
-sbin_PROGRAMS = mkntfs ntfslabel
+bin_PROGRAMS = ntfsfix ntfsinfo # ntfsdump_logfile dumplog
+sbin_PROGRAMS = mkntfs ntfslabel # ntfsundelete
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 ntfsundelete.8
@@ -126,5 +126,5 @@
CONFIG_CLEAN_FILES = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 ntfsundelete.8
bin_PROGRAMS = ntfsfix$(EXEEXT) ntfsinfo$(EXEEXT)
-sbin_PROGRAMS = mkntfs$(EXEEXT) ntfslabel$(EXEEXT) ntfsundelete$(EXEEXT)
+sbin_PROGRAMS = mkntfs$(EXEEXT) ntfslabel$(EXEEXT) # ntfsundelete$(EXEEXT)
PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS)
Index: ntfsundelete.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/ntfsundelete.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -U2 -r1.1 -r1.2
--- ntfsundelete.c 30 Jun 2002 22:46:51 -0000 1.1
+++ ntfsundelete.c 1 Jul 2002 13:30:28 -0000 1.2
@@ -47,9 +47,12 @@
static const char *AUTHOR = "Richard Russon (FlatCap)";
static const char *EXEC_NAME = "ntfsundelete";
-
static struct options opts;
/**
- * version
+ * version - Print version information about the program
+ *
+ * Print a copyright statement and a brief description of the program.
+ *
+ * Return: none
*/
void version (void)
@@ -66,5 +69,9 @@
/**
- * usage
+ * usage - Print a list of the parameters to the program
+ *
+ * Print a list of the parameters and options for the program.
+ *
+ * Return: none
*/
void usage (void)
@@ -95,5 +102,10 @@
/**
- * parse_options
+ * parse_options - Read and validate the programs command line
+ *
+ * Read the command line, verify the syntax and parse the options.
+ *
+ * Return: 0 Success
+ * 1 Error, one or more problems
*/
int parse_options (int argc, char *argv[])
@@ -210,5 +222,11 @@
/**
- * ntfs2utc
+ * ntfs2utc - Convert an NTFS time to Unix time
+ * @time: An NTFS time in 100ns units since 1601
+ *
+ * NTFS stores times as the number of 100ns intervals since January 1st 1601 at
+ * 00:00 UTC. This system will not suffer from Y2K problems until ~57000AD.
+ *
+ * Return: n A Unix time (number of seconds since 1970)
*/
time_t ntfs2utc (long long time)
@@ -218,5 +236,15 @@
/**
- * find_attribute
+ * 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.
+ *
+ * XXX it won't overflow the buffer as long as the context doesn't include an inode.
+ *
+ * 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)
@@ -226,5 +254,5 @@
if (ntfs_lookup_attr (type, NULL, 0, 0, 0, NULL, 0, ctx) != 0)
- return NULL; /* None of / no more of that type */
+ return NULL; /* None / no more of that type */
return ctx->attr;
@@ -232,15 +260,23 @@
/**
- * find_first_attribute
+ * 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.
+ *
+ * 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 *buffer)
+ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft)
{
ntfs_attr_search_ctx *ctx;
ATTR_RECORD *rec;
- if (!buffer)
+ if (!mft)
return NULL;
- ctx = ntfs_get_attr_search_ctx (NULL, buffer);
+ ctx = ntfs_get_attr_search_ctx (NULL, mft);
if (!ctx)
return NULL;
@@ -252,5 +288,11 @@
/**
- * free_file
+ * free_file - Release the resources used by a file object
+ * @file: The unwanted file object
+ *
+ * This will free up the memory used by a file object and iterate through the
+ * object's children, freeing their resources too.
+ *
+ * Return: none
*/
void free_file (struct ufile *file)
@@ -263,5 +305,5 @@
free (file->mft);
- list_for_each_safe (item, tmp, &file->name) {
+ list_for_each_safe (item, tmp, &file->name) { /* List of filenames */
struct filename *f = list_entry (item, struct filename, list);
free (f->name);
@@ -269,5 +311,5 @@
}
- list_for_each_safe (item, tmp, &file->data) {
+ list_for_each_safe (item, tmp, &file->data) { /* List of data streams */
struct data *d = list_entry (item, struct data, list);
free (d->run_list);
@@ -278,5 +320,18 @@
/**
- * cluster_in_use
+ * 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 of 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 The cluster is in use
+ * 0 The cluster is free space
*/
int cluster_in_use (ntfs_volume *vol, long long lcn)
@@ -291,4 +346,5 @@
return -1;
+ /* Does lcn lie in the section of $Bitmap we already have cached? */
if ((lcn < bmplcn) || (lcn >= (bmplcn + (sizeof (buffer) << 3)))) {
attr = ntfs_attr_open (vol->lcnbmp_ni, AT_DATA, NULL, 0);
@@ -298,6 +354,7 @@
}
+ /* Mark the buffer as in use, in case the read is shorter. */
+ memset (buffer, 0xFF, sizeof (buffer));
bmplcn = lcn & (~((sizeof (buffer) << 3) - 1));
- memset (buffer, 0xFF, sizeof (buffer)); // mark as in use
if (ntfs_attr_pread (attr, (bmplcn>>3), sizeof (buffer), buffer) < 0) {
@@ -318,5 +375,18 @@
/**
- * get_filenames
+ * get_filenames - Read the MFT Record's $FILENAME attributes
+ * @file: The file object to work with
+ *
+ * A single file may have more than one filename. This is quite common.
+ * Windows creates a short DOS name for each long name, e.g. LONGFI~1.XYZ,
+ * LongFiLeName.xyZ.
+ *
+ * The filenames that are found are put in filename objects and added to a
+ * linked list of filenames in the file object. For convenience, the unicode
+ * filename is converted into the current locale and stored in the filename
+ * object.
+ *
+ * Return: n The number of $FILENAME attributes found
+ * -1 Error
*/
int get_filenames (struct ufile *file)
@@ -365,5 +435,17 @@
/**
- * get_data
+ * get_data - Read the MFT Record's $DATA attributes
+ * @file: The file object to work with
+ * @vol: An ntfs volume obtained from ntfs_mount
+ *
+ * A file may have more than one data stream. All files will have an unnamed
+ * data stream which contains the file's data. Some Windows applications store
+ * extra information in a separate stream.
+ *
+ * The streams that are found are put in data objects and added to a linked
+ * list of data streams in the file object.
+ *
+ * Return: n The number of $FILENAME attributes found
+ * -1 Error
*/
int get_data (struct ufile *file, ntfs_volume *vol)
@@ -382,5 +464,4 @@
while ((rec = find_attribute (AT_DATA, ctx))) {
-
data = malloc (sizeof (*data));
if (!data) {
@@ -429,5 +510,13 @@
/**
- * read_record
+ * read_record - Read an MFT record into memory
+ * @vol: An ntfs volume obtained from ntfs_mount
+ * @record: The record number to read
+ *
+ * Read the specified MFT record and gather as much information about it as
+ * possible.
+ *
+ * Return: Pointer A ufile object containing the results
+ * NULL Error
*/
struct ufile * read_record (ntfs_volume *vol, long long record)
@@ -494,5 +583,24 @@
/**
- * calc_percentage
+ * calc_percentage - Calculate how much of the file is recoverable
+ * @file: The file object to work with
+ * @vol: An ntfs volume obtained from ntfs_mount
+ *
+ * Read through all the $DATA streams and determine if each cluster in each
+ * stream is still free disk space. This is just measuring the potential for
+ * recovery. The data may have still been overwritten by a another file which
+ * was then deleted.
+ *
+ * Files with a resident $DATA stream will have a 100% potential.
+ *
+ * N.B. If $DATA attribute spans more than one MFT record (i.e. badly
+ * fragmented) then only the data in this segment will be used for the
+ * calculation.
+ *
+ * N.B. Currently, compressed and encrypted files cannot be recovered, so they
+ * will return 0%.
+ *
+ * Return: n The percentage of the file that _could_ be recovered
+ * -1 Error
*/
int calc_percentage (struct ufile *file, ntfs_volume *vol)
@@ -507,5 +615,5 @@
if (!file || !vol)
- return 0;
+ return -1;
if (file->directory) {
@@ -590,9 +698,22 @@
/**
- * dump_record
+ * dump_record - Print everything we know about an MFT record
+ * @file: The file to work with
+ *
+ * Output the contents of the file object. This will print everything that has
+ * been read from the MFT record, or implied by various means.
+ *
+ * Because of the redundant nature of NTFS, there will be some duplication of
+ * information, though it will have been read from different sources.
+ *
+ * N.B. If the filename is missing, or couldn't be converted to the current
+ * locale, "<none>" will be displayed.
+ *
+ * Return: none
*/
void dump_record (struct ufile *file)
{
char buffer[20];
+ char *name;
struct list_head *item;
int i;
@@ -611,4 +732,10 @@
list_for_each (item, &file->name) {
struct filename *f = list_entry (item, struct filename, list);
+
+ if (f->name)
+ name = f->name;
+ else
+ name = "<none>";
+
printf ("Filename: (%d) %s\n", f->name_space, f->name);
printf ("File Flags: ");
@@ -663,7 +790,27 @@
/**
- * list_record
+ * list_record - Print a one-line summary of the file
+ * @file: The file to work with
+ *
+ * Print a one-line description of a file.
+ *
+ * Inode Flags %age Date Size Filename
+ *
+ * The output will contain the file's inode number (MFT Record), some flags,
+ * the percentage of the file that is recoverable, the last modification date,
+ * the size and the filename.
+ *
+ * The flags are F/D = File/Directory, N/R = Data is (Non-)Resident,
+ * C = Compressed, E = Encrypted, ! = Metadata may span multiple records.
+ *
+ * N.B. The file size is stored in many forms in several attributes. This
+ * display the largest it finds.
+ *
+ * N.B. If the filename is missing, or couldn't be converted to the current
+ * locale, "<none>" will be displayed.
+ *
+ * Return: none
*/
-int list_record (struct ufile *file)
+void list_record (struct ufile *file)
{
char buffer[20];
@@ -721,6 +868,4 @@
file->inode, flagd, flagr, flagc, flage, flagx,
percent, buffer, size, name);
-
- return 0;
}
@@ -731,5 +876,5 @@
int scan_disk (ntfs_volume *vol)
{
- char buffer[1024];
+ char *buffer;
int results = 0;
ntfs_attr *attr;
@@ -747,4 +892,10 @@
return -1;
+ buffer = malloc (vol->mft_record_size);
+ if (!buffer) {
+ ntfs_attr_close (attr);
+ return -1;
+ }
+
printf ("Inode Flags %%age Date Size Filename\n");
printf ("---------------------------------------------------------------\n");
@@ -786,4 +937,5 @@
printf ("\nFiles with potentially recoverable content: %d\n", results);
+ free (buffer);
ntfs_attr_close (attr);
return results;
@@ -832,5 +984,5 @@
int undelete_file (ntfs_volume *vol, long long inode)
{
- char buffer[1024];
+ char buffer[1024]; // XXX hard-coded to the size of an MFT record
struct ufile *file;
int i, j;
@@ -838,5 +990,5 @@
run_list_element *rl;
struct list_head *item;
- int fd = 0;
+ int fd = -1;
long long k;
@@ -893,6 +1045,8 @@
}
- close (fd);
- fd = 0;
+ if (close (fd) < 0) {
+ printf ("close failed\n");
+ }
+ fd = -1;
} else {
rl = d->run_list;
@@ -979,11 +1133,13 @@
}
printf ("\n");
+ if (close (fd) < 0) {
+ printf ("close failed\n");
+ }
+ fd = -1;
}
}
- close (fd);
free_file (file);
-
return 0;
}
@@ -1006,6 +1162,4 @@
locale = setlocale (LC_ALL, NULL);
printf ("Failed to set locale, using default '%s'.\n", locale);
- } else {
- //printf ("Using locale '%s'.\n", locale);
}
Index: ntfsundelete.h
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/ntfsundelete.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -U2 -r1.1 -r1.2
--- ntfsundelete.h 30 Jun 2002 22:46:51 -0000 1.1
+++ ntfsundelete.h 1 Jul 2002 13:30:28 -0000 1.2
@@ -1,7 +1,7 @@
-#ifndef _UNDELETE_H_
-#define _UNDELETE_H_
+#ifndef _NTFSUNDELETE_H_
+#define _NTFSUNDELETE_H_
/**
- * undelete - Part of the Linux-NTFS project.
+ * ntfsundelete - Part of the Linux-NTFS project.
*
* Copyright (c) 2002 Richard Russon <nt...@fl...>
@@ -30,50 +30,50 @@
struct options {
- int scan;
- int uinode;
- int percent;
- int verbose;
- char *dest;
- char *device;
+ char *device; /* Device/File to work with */
+ int scan; /* Scan the disk */
+ int percent; /* Minimum recoverability */
+ int verbose; /* Extra output */
+ int uinode; /* Undelete this inode */
+ char *dest; /* Save file to this directory */
};
struct filename {
- struct list_head list;
- char *name;
+ struct list_head list; /* Previous/Next links */
+ char *name; /* Filename in current locale */
FILE_NAME_TYPE_FLAGS name_space;
- uchar_t *uname;
- int uname_len;
- long long size_alloc;
- long long size_data;
+ uchar_t *uname; /* Filename in unicode */
+ int uname_len; /* and its length */
+ long long size_alloc; /* Allocated size (multiple of cluster size) */
+ long long size_data; /* Actual size of data */
FILE_ATTR_FLAGS flags;
};
struct data {
- struct list_head list;
- char *name;
- uchar_t *uname;
- int uname_len;
- int resident;
- int compressed;
- int encrypted;
- long long size_alloc;
- long long size_data;
- long long size_init;
- long long size_vcn;
- run_list_element*run_list;
- int percent;
- void *data;
+ struct list_head list; /* Previous/Next links */
+ char *name; /* Stream name in current locale */
+ uchar_t *uname; /* Unicode stream name */
+ int uname_len; /* and its length */
+ int resident; /* Stream is resident */
+ int compressed; /* Stream is compressed */
+ int encrypted; /* Stream is encrypted */
+ long long size_alloc; /* Allocated size (multiple of cluster size) */
+ long long size_data; /* Actual size of data */
+ long long size_init; /* Initialised size, may be less than data size */
+ long long size_vcn; /* The highest VCN in the data runs */
+ run_list_element*run_list; /* Decoded data runs */
+ int percent; /* Amont potentially recoverable */
+ void *data; /* If resident, a pointer to the data */
};
struct ufile {
- long long inode;
- time_t date;
- struct list_head name;
- struct list_head data;
- int attr_list;
- int directory;
- MFT_RECORD *mft;
+ long long inode; /* MFT record number */
+ time_t date; /* Last modification date/time */
+ struct list_head name; /* A list of filenames */
+ struct list_head data; /* A list of data streams */
+ int attr_list; /* MFT record may be one of many */
+ int directory; /* MFT record represents a directory */
+ MFT_RECORD *mft; /* The raw MFT record */
};
-#endif /* _UNDELETE_H_ */
+#endif /* _NTFSUNDELETE_H_ */
|