Fix bugs and limitations in NTFS utilities encountered with deep paths (over 20 levels)

This affects ntfscluster and ntfsmove.

* Don't output the path if utils_inode_get_name() returns an error, which
  previously would output an uninitialized string for deep paths, producing
  random garbage.

* If the path depth limit is encountered, utils_inode_get_name() now returns
  a partial path beginning with ".../" instead of an error code.

* Increase utils_inode_get_name()'s path depth limit from 20 to 40.

* Always free temporary memory, previously lost for deep paths.
pull/9/head
Tim Eliseo 2021-10-05 06:01:10 -07:00
parent 92b9fbc6fe
commit 00a4329bc0
3 changed files with 24 additions and 22 deletions

View File

@ -392,9 +392,8 @@ static int dump_file(ntfs_volume *vol, ntfs_inode *ino)
int i;
runlist *runs;
utils_inode_get_name(ino, buffer, sizeof(buffer));
ntfs_log_info("Dump: %s\n", buffer);
if (utils_inode_get_name(ino, buffer, sizeof(buffer)))
ntfs_log_info("Dump: %s\n", buffer);
ctx = ntfs_attr_get_search_ctx(ino, NULL);
@ -440,8 +439,8 @@ static int print_match(ntfs_inode *ino, ATTR_RECORD *attr,
return 1;
}
utils_inode_get_name(ino, buffer, MAX_PATH);
ntfs_log_info("Inode %llu %s", (unsigned long long)ino->mft_no, buffer);
if (utils_inode_get_name(ino, buffer, MAX_PATH))
ntfs_log_info("Inode %llu %s", (unsigned long long)ino->mft_no, buffer);
utils_attr_get_name(ino->vol, attr, buffer, MAX_PATH);
ntfs_log_info("/%s\n", buffer);

View File

@ -816,7 +816,8 @@ static s64 move_file(ntfs_volume *vol, ntfs_inode *ino, u64 loc, int flags)
return -1;
}
utils_inode_get_name(ino, buffer, MAX_PATH);
if (!utils_inode_get_name(ino, buffer, MAX_PATH))
return -1;
if (dont_move(ino)) {
ntfs_log_error("can't move\n");

View File

@ -521,7 +521,7 @@ ATTR_RECORD * find_first_attribute(const ATTR_TYPES type, MFT_RECORD *mft)
* if parent is 5 (/) stop
* get inode of parent
*/
#define max_path 20
#define max_path 40
int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
{
// XXX option: names = posix/win32 or dos
@ -535,7 +535,7 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
int name_space;
MFT_REF parent = FILE_root;
char *names[max_path + 1];// XXX ntfs_malloc? and make max bigger?
int i, len, offset = 0;
int i, ir, len, offset = 0;
if (!inode || !buffer) {
errno = EINVAL;
@ -611,26 +611,28 @@ int utils_inode_get_name(ntfs_inode *inode, char *buffer, int bufsize)
if (i >= max_path) {
/* If we get into an infinite loop, we'll end up here. */
ntfs_log_error("The directory structure is too deep (over %d) nested directories.\n", max_path);
return 0;
offset = snprintf(buffer, bufsize, "...");
}
/* Assemble the names in the correct order. */
for (i = max_path; i >= 0; i--) {
if (!names[i])
continue;
if (bufsize > offset) {
/* Assemble the names in the correct order. */
for (ir = max_path; ir >= 0; ir--) {
if (!names[ir])
continue;
len = snprintf(buffer + offset, bufsize - offset, "%c%s", PATH_SEP, names[i]);
if (len >= (bufsize - offset)) {
ntfs_log_error("Pathname was truncated.\n");
break;
}
len = snprintf(buffer + offset, bufsize - offset, "%c%s", PATH_SEP, names[ir]);
if (len >= (bufsize - offset)) {
ntfs_log_error("Pathname was truncated.\n");
break;
}
offset += len;
}
offset += len;
}
}
/* Free all the allocated memory */
for (i = 0; i < max_path; i++)
free(names[i]);
for (ir = 0; ir <= i; ir++)
free(names[ir]);
ntfs_log_debug("Pathname: %s\n", buffer);