Changes by: antona
Update of /cvsroot/linux-ntfs/linux-ntfs/ntfstools
In directory usw-pr-cvs1:/tmp/cvs-serv4109/ntfstools
Modified Files:
ntfsdump_logfile.c ntfsfix.c ntfslabel.c
Log Message:
Loads of stuff. Improvements, start on attr pread and attr mst_pread. Write to follow. ntfslabel cleanup and extensions. libntfs cleanups, fixes, etc.
Index: ntfsdump_logfile.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/ntfsdump_logfile.c,v
retrieving revision 1.19
retrieving revision 1.20
diff -U2 -r1.19 -r1.20
--- ntfsdump_logfile.c 21 Apr 2002 01:26:39 -0000 1.19
+++ ntfsdump_logfile.c 29 Apr 2002 01:53:55 -0000 1.20
@@ -358,6 +358,6 @@
if (m)
free(m);
- if (vol)
- ntfs_umount(vol, 0);
+ if (vol && ntfs_umount(vol, 0))
+ ntfs_umount(vol, 1);
return i;
error_exit:
Index: ntfsfix.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/ntfsfix.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -U2 -r1.30 -r1.31
--- ntfsfix.c 27 Apr 2002 19:49:10 -0000 1.30
+++ ntfsfix.c 29 Apr 2002 01:53:55 -0000 1.31
@@ -433,6 +433,6 @@
if (b1)
free(b1);
- if (vol)
- ntfs_umount(vol, 0);
+ if (vol && ntfs_umount(vol, 0))
+ ntfs_umount(vol, 1);
return i;
error_exit:
Index: ntfslabel.c
===================================================================
RCS file: /cvsroot/linux-ntfs/linux-ntfs/ntfstools/ntfslabel.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -U2 -r1.12 -r1.13
--- ntfslabel.c 28 Apr 2002 21:20:27 -0000 1.12
+++ ntfslabel.c 29 Apr 2002 01:53:55 -0000 1.13
@@ -1,3 +1,2 @@
-
/*
* $Id$
@@ -33,231 +32,55 @@
#include <string.h>
#include <errno.h>
-#include <mntent.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <locale.h>
-#include "types.h"
-#include "volume.h"
#include "debug.h"
#include "mft.h"
-#include "attrib.h"
-#include "unistr.h"
-
-const char *EXEC_NAME = "ntfslabel";
-const char *AUTHOR = "Matthew Fanto";
-
-ntfs_volume *vol;
-
-void change_label(const char *dev, const char *label);
-
-int resize_resident_attribute_value(MFT_RECORD * m, ATTR_RECORD * a,
- const __u32 new_vsize);
-
-void print_label(const char *dev);
-
-int modify_resident_attr_in_mft_record(MFT_RECORD * m, const ATTR_TYPES type,
- const char *name, __u32 name_len,
- const IGNORE_CASE_BOOL ic,
- const ATTR_FLAGS flags,
- const RESIDENT_ATTR_FLAGS res_flags,
- const char *val, const __u32 val_len);
-
-int stoucs(uchar_t * dest, const char *src, int maxlen);
-
-
-
-int main(int argc, char **argv)
-{
- char *locale;
-
- locale = setlocale(LC_ALL, "");
- if (!locale) {
- char *locale;
-
- locale = setlocale(LC_ALL, NULL);
- Dprintf("Failed to set locale, using default (%s).\n", locale);
- } else
- Dprintf("Set locale to %s.\n", locale);
- Dprintf("MB_CUR_MAX = %i\n", MB_CUR_MAX);
- if (argc && *argv)
- EXEC_NAME = *argv;
- if (argc == 2)
- print_label(argv[1]);
- else if (argc == 3)
- change_label(argv[1],argv[2]);
- else {
- fprintf(stderr, "%s v%s - %s\n", EXEC_NAME, VERSION, AUTHOR);
- fprintf(stderr, "Usage: ntfslabel device [newlabel]\n");
- exit(1);
- }
- return 0;
-}
-
-
-/**
- * print_label - display the current label on a device
- * @dev: the device to read label
- *
- * print_label will first verify the device is a valid block
- * device, and will exit with error INVALID_BLOCK_DEVICE if
- * it is not.
- **/
-void print_label(const char *dev)
+/*
+ * print_label - display the current label of a mounted ntfs partition.
+ * @dev: device to read the label from
+ * @mnt_flags: mount flags of the device or 0 if not mounted
+ * @mnt_point: mount point of the device or NULL
+ *
+ * Print the label of the device @dev to stdout.
+ */
+void print_label(const char *dev, const unsigned long mnt_flags,
+ const char *mnt_point)
{
+ ntfs_volume *vol;
- int err;
- unsigned long mnt_flags;
-
- /* We should first make sure it is a valid block device */
- err = ntfs_check_if_mounted(dev, &mnt_flags);
- if (err) {
- if (errno == ENODEV) {
- printf("Error: %s is not a valid block device!\n", dev);
- exit(1);
- }
+ if (mnt_point) {
+ // Try ioctl and finish if present.
+ // goto finished;
+ }
+ if ((mnt_flags & (NTFS_MF_MOUNTED | NTFS_MF_READONLY)) ==
+ NTFS_MF_MOUNTED) {
+ fprintf(stderr, "%s is mounted read-write, results may be "
+ "unreliable.\n", dev);
}
-
vol = ntfs_mount(dev, MS_RDONLY);
-
if (!vol) {
- printf("ntfs_mount() on device %s failed!\n", dev);
+ fprintf(stderr, "ntfs_mount() on device %s failed: %s\n", dev,
+ strerror(errno));
exit(1);
}
-
+//finished:
printf("%s\n", vol->vol_name);
- ntfs_umount(vol, 0);
+ if (ntfs_umount(vol, 0))
+ ntfs_umount(vol, 1);
}
-
-
-/**
- * change_label - change the current label on a device
- * @dev: the device to read label
- * @label: the new label
+/*
+ * resize_resident_attribute_value - resize a resident attribute
+ * @m: mft record containing attribute to resize
+ * @a: attribute record (inside @m) which to resize
+ * @new_vsize: the new attribute value size to resize the attribute to
*
- * change_label will first verify the device is a valid block
- * device, and will exit with error INVALID_BLOCK_DEVICE if
- * it is not. it will also verify the device is not currently
- * mounted and exit with error NTFS_MF_MOUNTED if it is
+ * Return 0 on success and -1 with errno = ENOSPC if not enough space in the
+ * mft record.
*/
-void change_label(const char *dev, const char *label)
+int resize_resident_attribute_value(MFT_RECORD *m, ATTR_RECORD *a,
+ const __u32 new_vsize)
{
-
- MFT_RECORD *mrec = NULL;
- MFT_REF mref;
- ATTR_RECORD *a;
- ntfs_attr_search_ctx *ctx = NULL;
- int err;
- unsigned long mnt_flags;
- uchar_t *new_label;
- int label_len;
-
-
- /*First we need to make sure the device is not mounted */
- err = ntfs_check_if_mounted(dev, &mnt_flags);
-
- if (err) {
- if (errno == ENODEV) {
- printf("Error: %s is not a valid block device!\n", dev);
- }
- exit(1);
- }
-
- if(mnt_flags == NTFS_MF_MOUNTED)
- {
- printf("Error: Device already mounted!!\n");
- exit(1);
- }
-
-
- vol = ntfs_mount(dev, 0);
- if (!vol) {
- printf("ntfs_mount() failed!\n");
- exit(1);
- }
-
- label_len = strlen(label);
-
- mref = (MFT_REF) FILE_Volume;
-
- if ((err = ntfs_read_file_record(vol, mref, &mrec, NULL))) {
- printf("Error reading file record\n");
- exit(1);
- }
-
-
-
- ctx = ntfs_get_attr_search_ctx(NULL, mrec);
-
- if (!ctx) {
- printf("Failed to allocate attribute search context!\n");
- exit(1);
- }
-
-
-
- if (ntfs_lookup_attr(AT_VOLUME_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
- printf("$VOLUME_NAME attribute not found?!?\n");
- exit(1);
- }
-
- a = ctx->attr;
-
- if (a->non_resident) {
- printf("Error: Attribute $VOLUME_NAME must be resident!\n");
- exit(1);
- }
-
- new_label = malloc((label_len + 1 ) * sizeof(uchar_t));
- label_len = ntfs_mbstoucs(label,(label_len + 1) *
- sizeof(char), &new_label,(label_len + 1) * sizeof(uchar_t));
-
- if (label_len == -1)
- {
- printf("Unable to convert string to Unicode!\n");
-
- if(errno == EINVAL)
- printf("Invalid argument!\n");
- else if (errno == EILSEQ)
- printf("Input string cannot be represented as Unicode!\n");
- else if (errno == ENAMETOOLONG)
- printf("Destination buffer is too small!");
- else if (errno == ENOMEM)
- printf("Not enough memory to allocate destination buffer!\n");
-
- exit(1);
-
- }
-
- label_len = label_len * sizeof(uchar_t);
-
- if (resize_resident_attribute_value(mrec, a, label_len)) {
- printf("Error: Cannot resize resident attribute!\n");
- exit(1);
- }
-
- memcpy((char*)a + le16_to_cpu(a->value_offset), new_label,
- min(le32_to_cpu(a->value_length), label_len));
-
-
- if (ntfs_write_mft_record(vol, mref, mrec)) {
- printf("Error: Cannot write MFT Record to disk!\n");
- exit(1);
- }
-}
-
-
-
-
-
-
-/* Return 0 on success and -errno on error. */
-int resize_resident_attribute_value(MFT_RECORD * m, ATTR_RECORD * a,
- const __u32 new_vsize)
-{
-
int new_alen, new_muse;
@@ -265,15 +88,14 @@
new_alen = (le16_to_cpu(a->value_offset) + new_vsize + 7) & ~7;
new_muse = le32_to_cpu(m->bytes_in_use) - le32_to_cpu(a->length) +
- new_alen;
+ new_alen;
/* Check for sufficient space. */
if (new_muse > le32_to_cpu(m->bytes_allocated)) {
- // Aarrgghh! Need to make space. Probably want generic function
- // for this as we need to call it from other places, too.
- return -ENOTSUP;
+ errno = ENOSPC;
+ return -1;
}
/* Move attributes behind @a to their new location. */
- memmove((char *) a + new_alen, (char *) a + le32_to_cpu(a->length),
- le32_to_cpu(m->bytes_in_use) - ((char *) a - (char *) m) -
- le32_to_cpu(a->length));
+ memmove((char*)a + new_alen, (char*)a + le32_to_cpu(a->length),
+ le32_to_cpu(m->bytes_in_use) - ((char*)a - (char*)m) -
+ le32_to_cpu(a->length));
/* Adjust @m to reflect change in used space. */
m->bytes_in_use = cpu_to_le32(new_muse);
@@ -284,6 +106,135 @@
}
+/*
+ * change_label - change the current label on a device
+ * @dev: device to change the label on
+ * @mnt_flags: mount flags of the device or 0 if not mounted
+ * @mnt_point: mount point of the device or NULL
+ * @label: the new label
+ *
+ * Change the label on the device @dev to @label.
+ */
+void change_label(const char *dev, const unsigned long mnt_flags,
+ const char *mnt_point, char *label, BOOL force)
+{
+ ntfs_attr_search_ctx *ctx = NULL;
+ uchar_t *new_label = NULL;
+ MFT_RECORD *mrec = NULL;
+ ATTR_RECORD *a;
+ ntfs_volume *vol;
+ int label_len, err = 1;
+
+ if (mnt_point) {
+ // Try ioctl and return if present.
+ // return;
+ }
+ if (mnt_flags & NTFS_MF_MOUNTED) {
+ /* If not the root fs or mounted read/write, refuse change. */
+ if (!(mnt_flags & NTFS_MF_ISROOT) ||
+ !(mnt_flags & NTFS_MF_READONLY)) {
+ if (!force) {
+ fprintf(stderr, "Refusing to change label on "
+ "read-%s mounted device %s.\n",
+ mnt_flags & NTFS_MF_READONLY ?
+ "only" : "write", dev);
+ return;
+ }
+ }
+ }
+ vol = ntfs_mount(dev, 0);
+ if (!vol) {
+ fprintf(stderr, "ntfs_mount() on device %s failed: %s\n", dev,
+ strerror(errno));
+ exit(1);
+ }
+ if (ntfs_read_file_record(vol, (MFT_REF)FILE_Volume, &mrec, NULL)) {
+ perror("Error reading file record");
+ goto err_out;
+ }
+ ctx = ntfs_get_attr_search_ctx(NULL, mrec);
+ if (!ctx) {
+ perror("Failed to get attribute search context");
+ goto err_out;
+ }
+ if (ntfs_lookup_attr(AT_VOLUME_NAME, NULL, 0, 0, 0, NULL, 0, ctx)) {
+ perror("Lookup of $VOLUME_NAME attribute failed");
+ goto err_out;
+ }
+ a = ctx->attr;
+ if (a->non_resident) {
+ fprintf(stderr, "Error: Attribute $VOLUME_NAME must be "
+ "resident.\n");
+ goto err_out;
+ }
+ label_len = ntfs_mbstoucs(label, &new_label, 0);
+ if (label_len == -1) {
+ perror("Unable to convert label string to Unicode");
+ goto err_out;
+ }
+ label_len *= sizeof(uchar_t);
+ if (label_len > 0x100) {
+ fprintf(stderr, "New label is too long. Maximum %i characters "
+ "allowed. Truncating excess characters.\n",
+ 0x100 / sizeof(uchar_t));
+ label_len = 0x100;
+ new_label[label_len / sizeof(uchar_t)] = cpu_to_le16(L'\0');
+ }
+ if (resize_resident_attribute_value(mrec, a, label_len)) {
+ perror("Error resizing resident attribute");
+ goto err_out;
+ }
+ memcpy((char*)a + le16_to_cpu(a->value_offset), new_label, label_len);
+ if (ntfs_write_mft_record(vol, (MFT_REF)FILE_Volume, mrec)) {
+ perror("Error writing MFT Record to disk");
+ goto err_out;
+ }
+ err = 0;
+err_out:
+ if (new_label)
+ free(new_label);
+ if (ntfs_umount(vol, 0))
+ ntfs_umount(vol, 1);
+ if (err)
+ exit(1);
+}
+int main(int argc, char **argv)
+{
+ const char *AUTHOR = "Matthew Fanto";
+ char *EXEC_NAME = "ntfslabel";
+ char *locale, *mnt_point = NULL;
+ unsigned long mnt_flags;
+ int err;
+ // FIXME:Implement option -F meaning force the change.
+ BOOL force = 0;
+ locale = setlocale(LC_ALL, "");
+ if (!locale) {
+ char *locale;
+ locale = setlocale(LC_ALL, NULL);
+ Dprintf("Failed to set locale, using default (%s).\n", locale);
+ } else
+ Dprintf("Using locale %s.\n", locale);
+ if (argc && *argv)
+ EXEC_NAME = *argv;
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "%s v%s - %s\n", EXEC_NAME, VERSION, AUTHOR);
+ fprintf(stderr, "Usage: ntfslabel device [newlabel]\n");
+ exit(1);
+ }
+ err = ntfs_check_if_mounted(argv[1], &mnt_flags);
+ if (err)
+ fprintf(stderr, "Failed to determine whether %s is mounted: "
+ "%s\n", argv[1], strerror(errno));
+ else if (mnt_flags & NTFS_MF_MOUNTED) {
+ // Not implemented yet. Will be used for ioctl interface to driver.
+ // mnt_point = ntfs_get_mount_point(argv[1]);
+ }
+ if (argc == 2)
+ print_label(argv[1], mnt_flags, mnt_point);
+ else
+ change_label(argv[1], mnt_flags, mnt_point, argv[2], force);
+ return 0;
+}
|