Support the case where $Volume does not have a $VOLUME_NAME
attribute in ntfs_device_mount() and let ntfslabel create the attribute when it is not present. (Logical change 1.339)edge.strict_endians
parent
93acd345a7
commit
ae7789dcd0
|
@ -764,7 +764,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long rwflag)
|
|||
Dperror("Failed to open inode");
|
||||
goto error_exit;
|
||||
}
|
||||
/* Get an ntfs attribute for $UpCase/$DATA. */
|
||||
/* Get a search context for the $Volume/$VOLUME_INFORMATION lookup. */
|
||||
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
||||
if (!ctx) {
|
||||
Dputs(FAILED);
|
||||
|
@ -807,46 +807,70 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long rwflag)
|
|||
/* Do not use le16_to_cpu() macro here as our VOLUME_FLAGS are
|
||||
defined using cpu_to_le16() macro and hence are consistent. */
|
||||
vol->flags = vinf->flags;
|
||||
/* Find the $VOLUME_NAME attribute. */
|
||||
/*
|
||||
* Reinitialize the search context for the $Volume/$VOLUME_NAME lookup.
|
||||
*/
|
||||
ntfs_attr_reinit_search_ctx(ctx);
|
||||
if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
|
||||
ctx)) {
|
||||
Dputs(FAILED);
|
||||
Dputs("$VOLUME_NAME attribute not found in $Volume?!?");
|
||||
goto error_exit;
|
||||
}
|
||||
a = ctx->attr;
|
||||
/* Has to be resident. */
|
||||
if (a->non_resident) {
|
||||
Dputs(FAILED);
|
||||
Dputs("Error: Attribute $VOLUME_NAME must be resident!");
|
||||
errno = EIO;
|
||||
goto error_exit;
|
||||
}
|
||||
/* Get a pointer to the value of the attribute. */
|
||||
vname = (uchar_t*)(le16_to_cpu(a->value_offset) + (char*)a);
|
||||
u = le32_to_cpu(a->value_length) / 2;
|
||||
/* Convert Unicode volume name to current locale multibyte format. */
|
||||
vol->vol_name = NULL;
|
||||
if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
|
||||
Dperror("Error: Volume name could not be converted to "
|
||||
"current locale");
|
||||
Dputs("Forcing name into ASCII by replacing non-ASCII "
|
||||
"characters with underscores.");
|
||||
vol->vol_name = malloc(u + 1);
|
||||
if (errno != ENOENT) {
|
||||
Dputs(FAILED);
|
||||
Dputs("Error: Lookup of $VOLUME_NAME attribute in "
|
||||
"$Volume failed. This probably means "
|
||||
"something is corrupt. Run chkdsk.");
|
||||
goto error_exit;
|
||||
}
|
||||
/*
|
||||
* Attribute not present. This has been seen in the field.
|
||||
* Treat this the same way as if the attribute was present but
|
||||
* had zero length.
|
||||
*/
|
||||
vol->vol_name = malloc(1);
|
||||
if (!vol->vol_name) {
|
||||
Dputs(FAILED);
|
||||
Dputs("Error: Unable to allocate memory for volume "
|
||||
"name!");
|
||||
goto error_exit;
|
||||
}
|
||||
for (j = 0; j < (s32)u; j++) {
|
||||
uchar_t uc = le16_to_cpu(vname[j]);
|
||||
if (uc > 0xff)
|
||||
uc = (uchar_t)'_';
|
||||
vol->vol_name[j] = (char)uc;
|
||||
vol->vol_name[0] = '\0';
|
||||
} else {
|
||||
a = ctx->attr;
|
||||
/* Has to be resident. */
|
||||
if (a->non_resident) {
|
||||
Dputs(FAILED);
|
||||
Dputs("Error: Attribute $VOLUME_NAME must be "
|
||||
"resident!");
|
||||
errno = EIO;
|
||||
goto error_exit;
|
||||
}
|
||||
/* Get a pointer to the value of the attribute. */
|
||||
vname = (uchar_t*)(le16_to_cpu(a->value_offset) + (char*)a);
|
||||
u = le32_to_cpu(a->value_length) / 2;
|
||||
/*
|
||||
* Convert Unicode volume name to current locale multibyte
|
||||
* format.
|
||||
*/
|
||||
vol->vol_name = NULL;
|
||||
if (ntfs_ucstombs(vname, u, &vol->vol_name, 0) == -1) {
|
||||
Dperror("Error: Volume name could not be converted to "
|
||||
"current locale");
|
||||
Dputs("Forcing name into ASCII by replacing non-ASCII "
|
||||
"characters with underscores.");
|
||||
vol->vol_name = malloc(u + 1);
|
||||
if (!vol->vol_name) {
|
||||
Dputs(FAILED);
|
||||
Dputs("Error: Unable to allocate memory for "
|
||||
"volume name!");
|
||||
goto error_exit;
|
||||
}
|
||||
for (j = 0; j < (s32)u; j++) {
|
||||
uchar_t uc = le16_to_cpu(vname[j]);
|
||||
if (uc > 0xff)
|
||||
uc = (uchar_t)'_';
|
||||
vol->vol_name[j] = (char)uc;
|
||||
}
|
||||
vol->vol_name[u] = '\0';
|
||||
}
|
||||
vol->vol_name[u] = '\0';
|
||||
}
|
||||
Dputs(OK);
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
|
|
|
@ -517,29 +517,28 @@ void ntfs_dump_object_id_attr(ntfs_inode *inode)
|
|||
*/
|
||||
void ntfs_dump_volume_name_attr(ntfs_inode *inode)
|
||||
{
|
||||
VOLUME_NAME *vol_name = NULL;
|
||||
ATTR_RECORD *attr = NULL;
|
||||
ntfs_attr_search_ctx *ctx = NULL;
|
||||
VOLUME_NAME *vol_name = NULL;
|
||||
ATTR_RECORD *attr = NULL;
|
||||
ntfs_attr_search_ctx *ctx = NULL;
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx(inode, NULL);
|
||||
|
||||
if(ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
||||
if (errno != ENOENT)
|
||||
fprintf(stderr, "ntfsinfo error: cannot look up attribute AT_VOLUME_NAME: %s\n",
|
||||
strerror(errno));
|
||||
ctx = ntfs_attr_get_search_ctx(inode, NULL);
|
||||
if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
|
||||
ctx)) {
|
||||
if (errno != ENOENT)
|
||||
fprintf(stderr, "ntfsinfo error: cannot look up "
|
||||
"attribute AT_VOLUME_NAME: %s\n",
|
||||
strerror(errno));
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return;
|
||||
}
|
||||
attr = ctx->attr;
|
||||
vol_name = (VOLUME_NAME*)((char *)attr +
|
||||
le16_to_cpu(attr->value_offset));
|
||||
printf("Dumping $VOLUME_NAME (0x60)\n");
|
||||
// FIXME: convert the name to current locale multibyte sequence
|
||||
// then output the converted name.
|
||||
//printf("\tVolume Name: \t\t\t %s\n", vol_name->name);
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
attr = ctx->attr;
|
||||
|
||||
vol_name = (VOLUME_NAME*)((char *)attr + le16_to_cpu(attr->value_offset));
|
||||
|
||||
printf("Dumping $VOLUME_NAME (0x60)\n");
|
||||
|
||||
//printf("\tVolume Name: \t\t\t %s\n", vol_name->name);
|
||||
|
||||
ntfs_attr_put_search_ctx(ctx);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* ntfslabel - Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2002 Matthew J. Fanto
|
||||
* Copyright (c) 2002 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2003 Richard Russon
|
||||
*
|
||||
* This utility will display/change the label on an NTFS partition.
|
||||
|
@ -64,7 +64,7 @@ void version (void)
|
|||
EXEC_NAME, VERSION);
|
||||
printf ("Copyright (c)\n");
|
||||
printf (" 2002 Matthew J. Fanto\n");
|
||||
printf (" 2002 Anton Altaparmakov\n");
|
||||
printf (" 2002-2004 Anton Altaparmakov\n");
|
||||
printf (" 2002-2003 Richard Russon\n");
|
||||
printf ("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
|
||||
}
|
||||
|
@ -164,7 +164,8 @@ int parse_options (int argc, char *argv[])
|
|||
}
|
||||
|
||||
if (opts.quiet && opts.verbose) {
|
||||
Eprintf ("You may not use --quiet and --verbose at the same time.\n");
|
||||
Eprintf ("You may not use --quiet and --verbose at "
|
||||
"the same time.\n");
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
@ -283,15 +284,21 @@ int change_label(ntfs_volume *vol, unsigned long mnt_flags, char *label, BOOL fo
|
|||
perror("Failed to get attribute search context");
|
||||
goto err_out;
|
||||
}
|
||||
if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 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;
|
||||
if (ntfs_attr_lookup(AT_VOLUME_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
|
||||
ctx)) {
|
||||
if (errno != ENOENT) {
|
||||
perror("Lookup of $VOLUME_NAME attribute failed");
|
||||
goto err_out;
|
||||
}
|
||||
/* The volume name attribute does not exist. Need to add it. */
|
||||
a = NULL;
|
||||
} else {
|
||||
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) {
|
||||
|
@ -306,11 +313,38 @@ int change_label(ntfs_volume *vol, unsigned long mnt_flags, char *label, BOOL fo
|
|||
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;
|
||||
if (a) {
|
||||
if (resize_resident_attribute_value(mrec, a, label_len)) {
|
||||
perror("Error resizing resident attribute");
|
||||
goto err_out;
|
||||
}
|
||||
} else {
|
||||
/* sizeof(resident attribute record header) == 24 */
|
||||
int asize = (24 + label_len + 7) & ~7;
|
||||
u32 biu = le32_to_cpu(mrec->bytes_in_use);
|
||||
if (biu + asize > le32_to_cpu(mrec->bytes_allocated)) {
|
||||
errno = ENOSPC;
|
||||
perror("Error adding resident attribute");
|
||||
goto err_out;
|
||||
}
|
||||
a = ctx->attr;
|
||||
memmove((u8*)a + asize, a, biu - ((u8*)a - (u8*)mrec));
|
||||
mrec->bytes_in_use = cpu_to_le32(biu + asize);
|
||||
a->type = AT_VOLUME_NAME;
|
||||
a->length = cpu_to_le32(asize);
|
||||
a->non_resident = 0;
|
||||
a->name_length = 0;
|
||||
a->name_offset = cpu_to_le16(24);
|
||||
a->flags = cpu_to_le16(0);
|
||||
a->instance = mrec->next_attr_instance;
|
||||
mrec->next_attr_instance = cpu_to_le16((le16_to_cpu(
|
||||
mrec->next_attr_instance) + 1) & 0xffff);
|
||||
a->value_length = cpu_to_le32(label_len);
|
||||
a->value_offset = a->name_offset;
|
||||
a->resident_flags = 0;
|
||||
a->reservedR = 0;
|
||||
}
|
||||
memcpy((char*)a + le16_to_cpu(a->value_offset), new_label, label_len);
|
||||
memcpy((u8*)a + le16_to_cpu(a->value_offset), new_label, label_len);
|
||||
if (ntfs_mft_record_write(vol, (MFT_REF)FILE_Volume, mrec)) {
|
||||
perror("Error writing MFT Record to disk");
|
||||
goto err_out;
|
||||
|
|
Loading…
Reference in New Issue