- Update for newer autoconf/automake.
- Abstract low level device operations (include/device,h and
libntfs/device.c) and adapt utilities to changes.
+ - Fix bugs in dir.c::ntfs_readdir() where we try to close ia_na when
+ it is NULL.
+ - Return errno ENOTDIR from dir.c::ntfs_readdir() when called with a
+ file inode.
13/02/2003 - 1.7.1 - Urgent bug fixes.
- Urgent bug fixes in ntfsresize (Szabolcs Szakacsits):
AC_PREREQ(2.57)
-AC_INIT(ntfsprogs, 200307311516, linux-ntfs-dev@lists.sourceforge.net)
+AC_INIT(ntfsprogs, 200309071734, linux-ntfs-dev@lists.sourceforge.net)
AC_CANONICAL_TARGET([])
AC_CONFIG_SRCDIR([config.h.in])
AM_CONFIG_HEADER([config.h])
ntfsprogs/ntfsprogs.8
ntfsprogs/ntfsresize.8
ntfsprogs/ntfsundelete.8
+ ntfsprogs/ntfscluster.8
ntfsprogs.spec
])
AC_OUTPUT
*/
void ntfs_attr_close(ntfs_attr *na)
{
- if (!na)
- return;
if (NAttrNonResident(na) && na->rl)
free(na->rl);
/* Don't release if using an internal constant. */
return -1;
}
+/**
+ * ntfs_attr_make_resident -
+ */
static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
{
// FIXME: For now we cheat and assume there is no attribute list
/*
* dir.c - Directory handling code. Part of the Linux-NTFS project.
*
- * Copyright (c) 2002 Anton Altaparmakov
+ * Copyright (c) 2002-2003 Anton Altaparmakov
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
return -1;
}
+ if (!(dir_ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) {
+ errno = ENOTDIR;
+ return -1;
+ }
+
vol = dir_ni->vol;
Dprintf("Entering for inode 0x%Lx, *pos 0x%Lx.\n",
done:
if (bmp_na)
ntfs_attr_close(bmp_na);
- ntfs_attr_close(ia_na);
+ if (ia_na)
+ ntfs_attr_close(ia_na);
#ifdef DEBUG
if (!rc)
Dprintf("EOD, *pos 0x%Lx, returning 0.\n", (long long)*pos);
ntfs_attr_put_search_ctx(ctx);
if (bmp_na)
ntfs_attr_close(bmp_na);
- ntfs_attr_close(ia_na);
+ if (ia_na)
+ ntfs_attr_close(ia_na);
errno = eo;
return -1;
}
# Workaround to make REALLYSTATIC work with automake 1.5.
LINK=$(STATIC_LINK) $(LIBTOOL_LINK)
-bin_PROGRAMS = ntfsfix ntfsinfo
+bin_PROGRAMS = ntfsfix ntfsinfo ntfscluster
sbin_PROGRAMS = mkntfs ntfslabel ntfsundelete ntfsresize
-EXTRA_PROGRAMS = ntfsdump_logfile dumplog ntfswipe ntfstruncate ntfscluster
+EXTRA_PROGRAMS = ntfsdump_logfile dumplog ntfswipe ntfstruncate
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
- ntfsundelete.8 ntfsresize.8 ntfsprogs.8
+ ntfsundelete.8 ntfsresize.8 ntfscluster.8 ntfsprogs.8
EXTRA_MANS =
CLEANFILES = $(EXTRA_PROGRAMS)
ntfsresize_LDADD = $(AM_LIBS)
ntfsresize_LDFLAGS = $(AM_LFLAGS)
-# We don't distribute these
-
ntfscluster_SOURCES = ntfscluster.c ntfscluster.h utils.c utils.h
ntfscluster_LDADD = $(AM_LIBS)
ntfscluster_LDFLAGS = $(AM_LFLAGS)
+# We don't distribute these
+
ntfstruncate_SOURCES = attrdef.c ntfstruncate.c utils.c utils.h
ntfstruncate_LDADD = $(AM_LIBS)
ntfstruncate_LDFLAGS = $(AM_LFLAGS)
void usage (void)
{
printf ("\nUsage: %s [options] device\n"
- " -i --info Print information about the volume\n"
+ " -i --info Print information about the volume (default)\n"
" -c range --cluster range Look for objects in this range of clusters\n"
" -s range --sector range Look for objects in this range of sectors\n"
/* " -l --last Find the last file on the volume\n" */
}
if (opts.action == act_error) {
- Eprintf ("You may only specify one action: --info, --cluster, --sector or --last.\n");
+ //Eprintf ("You may only specify one action: --info, --cluster, --sector or --last.\n");
+ Eprintf ("You may only specify one action: --info, --cluster or --sector.\n");
err++;
} else if (opts.range_begin > opts.range_end) {
Eprintf ("The range must be in ascending order.\n");
return (!err && !help && !ver);
}
+
+/**
+ * free_space - Calculate the amount of space which isn't in use
+ */
+u64 free_space (ntfs_volume *vol)
+{
+ return 0;
+}
+
+/**
+ * user_space - Calculate the amount of space of the user's files
+ */
+u64 user_space (ntfs_volume *vol)
+{
+ return 0;
+}
+
+/**
+ * meta_space - Calculate the amount of space used by the filesystem structures
+ */
+u64 meta_space (ntfs_volume *vol)
+{
+ return 0;
+}
+
+/**
+ * info - Display information about the volume
+ */
+int info (ntfs_volume *vol)
+{
+ u64 a, b, c, d, e, f, g, h, i, j, k, l, m, n;
+ int cps;
+ u64 fs, us, ms;
+
+ cps = vol->cluster_size_bits - vol->sector_size_bits;
+ fs = free_space (vol);
+ ms = meta_space (vol);
+ us = user_space (vol);
+
+ a = vol->sector_size;
+ b = vol->cluster_size;
+ c = 1 << cps;
+ d = vol->nr_clusters >> cps;
+ e = vol->nr_clusters;
+ f = fs / a;
+ g = fs / b;
+ h = fs * 100 / a / d;
+ i = us / a;
+ j = us / b;
+ k = us * 100 / a / d;
+ l = ms / a;
+ m = ms / b;
+ n = ms * 100 / a / d;
+
+ printf ("bytes per sector : %lld\n", a);
+ printf ("bytes per cluster : %lld\n", b);
+ printf ("sectors per cluster : %lld\n", c);
+ printf ("sectors per volume : %lld\n", d);
+ printf ("clusters per volume : %lld\n", e);
+ printf ("sectors of free space : %lld\n", f);
+ printf ("clusters of free space : %lld\n", g);
+ printf ("percentage free space : %lld\n", h);
+ printf ("sectors of user data : %lld\n", i);
+ printf ("clusters of user data : %lld\n", j);
+ printf ("percentage user data : %lld\n", k);
+ printf ("sectors of metadata : %lld\n", l);
+ printf ("clusters of metadata : %lld\n", m);
+ printf ("percentage metadata : %lld\n", n);
+
+ return 0;
+}
+
+
/**
* cluster_find
*/
if (!in_use) {
if (s_begin == s_end)
- printf ("clusters isn't in use\n");
+ printf ("cluster isn't in use\n");
else
printf ("clusters aren't in use\n");
- return 0;
+ result = 0;
+ goto free;
}
// first, is the cluster in use in $Bitmap?
ntfs_attr_search_ctx *ctx;
if (!utils_mftrec_in_use (vol, i)) {
- //printf ("%d skipped\n", i);
+ //printf ("%lld skipped\n", i);
continue;
}
printf ("inode %lld %s", i, buffer);
utils_attr_get_name (vol, ctx->attr, buffer, sizeof (buffer));
printf ("%c%s\n", PATH_SEP, buffer);
- //printf ("\n");
}
- break;
+ break; // XXX if verbose, we should list all matching runs
}
}
return result;
}
+
/**
* main - Begin here
*
else
Qprintf ("Searching for sector range %lld-%lld\n", opts.range_begin, opts.range_end);
/* Convert to clusters */
- opts.range_begin <<= (vol->cluster_size_bits - vol->sector_size_bits);
- opts.range_end <<= (vol->cluster_size_bits - vol->sector_size_bits);
+ opts.range_begin >>= (vol->cluster_size_bits - vol->sector_size_bits);
+ opts.range_end >>= (vol->cluster_size_bits - vol->sector_size_bits);
result = cluster_find (vol, opts.range_begin, opts.range_end);
break;
case act_cluster:
*/
case act_info:
default:
- printf ("Info\n");
+ info (vol);
break;
}
.BR \-\-destination ,
and
.BR \-\-byte .
+.sp
+When the file is recovered it will be given its original name, unless the
+.B "\-\-output"
+option is used.
.TP
.B \-v
.br
}
}
+ if (opts.fillbyte == -1)
+ opts.fillbyte = 0;
+
if (ver)
version();
if (help || err)
if (f->flags & FILE_ATTR_REPARSE_POINT) Qprintf ("Reparse ");
if (f->flags & FILE_ATTR_COMPRESSED) Qprintf ("Compressed ");
if (f->flags & FILE_ATTR_ENCRYPTED) Qprintf ("Encrypted ");
- if (!(f->flags & (FILE_ATTR_SYSTEM || FILE_ATTR_DIRECTORY ||
- FILE_ATTR_SPARSE_FILE || FILE_ATTR_REPARSE_POINT ||
- FILE_ATTR_COMPRESSED || FILE_ATTR_ENCRYPTED))) {
+ if (!(f->flags & (FILE_ATTR_SYSTEM | FILE_ATTR_DIRECTORY |
+ FILE_ATTR_SPARSE_FILE | FILE_ATTR_REPARSE_POINT |
+ FILE_ATTR_COMPRESSED | FILE_ATTR_ENCRYPTED))) {
Qprintf (NONE);
}
Qprintf ("\n");
ntfs_volume *vol;
ntfs_attr_search_ctx *ctx;
ATTR_RECORD *rec;
+ ATTR_RECORD *oldrec;
FILE_NAME_ATTR *attr;
int name_space;
MFT_REF parent = FILE_root;
//printf ("i = %d, inode = %p (%lld)\n", i, inode, inode->mft_no);
name_space = 4;
+ oldrec = NULL;
while ((rec = find_attribute (AT_FILE_NAME, ctx))) {
+ if (rec == oldrec)
+ break;
+ oldrec = rec;
/* We know this will always be resident. */
attr = (FILE_NAME_ATTR *) ((char *) rec + le16_to_cpu (rec->value_offset));
- if (attr->file_name_type >= name_space) { //XXX find the ...
+ if (attr->file_name_type > name_space) { //XXX find the ...
continue;
}
*/
int utils_attr_get_name (ntfs_volume *vol, ATTR_RECORD *attr, char *buffer, int bufsize)
{
- int len, namelen, offset = 0;
- char *name = NULL;
+ int len, namelen;
+ char *name;
ATTR_DEF *attrdef;
// flags: attr, name, or both
attrdef = ntfs_attr_find_in_attrdef (vol, attr->type);
if (attrdef) {
+ name = NULL;
namelen = ntfs_ucsnlen (attrdef->name, sizeof (attrdef->name));
if (ntfs_ucstombs (attrdef->name, namelen, &name, namelen) < 0) {
Eprintf ("Couldn't translate attribute type to current locale.\n");
return 0;
}
- offset += len;
-
if (!attr->name_length) {
return 0;
}
+ buffer += len;
+ bufsize -= len;
+
+ name = NULL;
namelen = attr->name_length;
if (ntfs_ucstombs ((uchar_t *)((char *)attr + attr->name_offset),
namelen, &name, namelen) < 0) {
Eprintf ("Couldn't translate attribute name to current locale.\n");
// <UNKNOWN>?
+ len = snprintf (buffer, bufsize, "<UNKNOWN>");
return 0;
}
- len = snprintf (buffer + offset, bufsize - offset, "(%s)", name);
+ len = snprintf (buffer, bufsize, "(%s)", name);
free (name);
- if ((len + offset) >= bufsize) {
+ if (len >= bufsize) {
Eprintf ("Attribute name was truncated.\n");
return 0;
}