static char *search_absolute(ntfs_volume *vol, ntfschar *path, int count, BOOL isdir) { ntfs_inode *ni; u64 inum; char *target; int start; int len; target = (char*)NULL; /* default return */ ni = ntfs_inode_open(vol, (MFT_REF)FILE_root); if (ni) { start = 0; /* * Examine and translate the path, until we reach either * - the end, * - an unknown item * - a non-directory * - another reparse point, * A reparse point is not dereferenced, it will be * examined later when the translated path is dereferenced, * however the final part of the path will not be adjusted * to correct case. */ do { len = 0; while (((start + len) < count) && (path[start + len] != const_cpu_to_le16('\\'))) len++; inum = ntfs_fix_file_name(ni, &path[start], len); ntfs_inode_close(ni); ni = (ntfs_inode*)NULL; if (inum != (u64)-1) { inum = MREF(inum); ni = ntfs_inode_open(vol, inum); start += len; if (start < count) path[start++] = const_cpu_to_le16('/'); } } while (ni && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) && !(ni->flags & FILE_ATTR_REPARSE_POINT) && (start < count)); if (ni && ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir) || (ni->flags & FILE_ATTR_REPARSE_POINT))) if (ntfs_ucstombs(path, count, &target, 0) < 0) { if (target) { free(target); target = (char*)NULL; } } if (ni) ntfs_inode_close(ni); } return (target); }
static char *search_absolute(ntfs_volume *vol, ntfschar *path, int count, BOOL isdir) { ntfs_inode *ni; u64 inum; char *target; int start; int len; target = (char*)NULL; /* default return */ ni = ntfs_inode_open(vol, (MFT_REF)FILE_root); if (ni) { start = 0; do { len = 0; while (((start + len) < count) && (path[start + len] != const_cpu_to_le16('\\'))) len++; inum = ntfs_fix_file_name(ni, &path[start], len); ntfs_inode_close(ni); ni = (ntfs_inode*)NULL; if (inum != (u64)-1) { inum = MREF(inum); ni = ntfs_inode_open(vol, inum); start += len; if (start < count) path[start++] = const_cpu_to_le16('/'); } } while (ni && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) && (start < count)); if (ni && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)) if (ntfs_ucstombs(path, count, &target, 0) < 0) { if (target) { free(target); target = (char*)NULL; } } if (ni) ntfs_inode_close(ni); } return (target); }
static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) { char *target = (char*)NULL; ntfs_inode *curni; ntfs_inode *newni; u64 inum; int pos; int lth; BOOL ok; BOOL morelinks; int max = 32; /* safety */ pos = 0; ok = TRUE; morelinks = FALSE; curni = ntfs_dir_parent_inode(ni); /* * Examine and translate the path, until we reach either * - the end, * - an unknown item * - a non-directory * - another reparse point, * A reparse point is not dereferenced, it will be * examined later when the translated path is dereferenced, * however the final part of the path will not be adjusted * to correct case. */ while (curni && ok && !morelinks && (pos < (count - 1)) && --max) { if ((count >= (pos + 2)) && (path[pos] == const_cpu_to_le16('.')) && (path[pos+1] == const_cpu_to_le16('\\'))) { path[1] = const_cpu_to_le16('/'); pos += 2; } else { if ((count >= (pos + 3)) && (path[pos] == const_cpu_to_le16('.')) &&(path[pos+1] == const_cpu_to_le16('.')) && (path[pos+2] == const_cpu_to_le16('\\'))) { path[2] = const_cpu_to_le16('/'); pos += 3; newni = ntfs_dir_parent_inode(curni); if (curni != ni) ntfs_inode_close(curni); curni = newni; if (!curni) ok = FALSE; } else { lth = 0; while (((pos + lth) < count) && (path[pos + lth] != const_cpu_to_le16('\\'))) lth++; if (lth > 0) inum = ntfs_fix_file_name(curni,&path[pos],lth); else inum = (u64)-1; if (!lth || ((curni != ni) && ntfs_inode_close(curni)) || (inum == (u64)-1)) ok = FALSE; else { curni = ntfs_inode_open(ni->vol, MREF(inum)); if (!curni) ok = FALSE; else { if (curni->flags & FILE_ATTR_REPARSE_POINT) morelinks = TRUE; if (ok && ((pos + lth) < count)) { path[pos + lth] = const_cpu_to_le16('/'); pos += lth + 1; if (morelinks && ntfs_inode_close(curni)) ok = FALSE; } else { pos += lth; if (!morelinks && (ni->mrec->flags ^ curni->mrec->flags) & MFT_RECORD_IS_DIRECTORY) ok = FALSE; if (ntfs_inode_close(curni)) ok = FALSE; } } } } } } if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) { free(target); // needed ? target = (char*)NULL; } return (target); }
static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) { char *target = (char*)NULL; ntfs_inode *curni; ntfs_inode *newni; u64 inum; int pos; int lth; BOOL ok; int max = 32; /* safety */ pos = 0; ok = TRUE; curni = ntfs_dir_parent_inode(ni); while (curni && ok && (pos < (count - 1)) && --max) { if ((count >= (pos + 2)) && (path[pos] == const_cpu_to_le16('.')) && (path[pos+1] == const_cpu_to_le16('\\'))) { path[1] = const_cpu_to_le16('/'); pos += 2; } else { if ((count >= (pos + 3)) && (path[pos] == const_cpu_to_le16('.')) &&(path[pos+1] == const_cpu_to_le16('.')) && (path[pos+2] == const_cpu_to_le16('\\'))) { path[2] = const_cpu_to_le16('/'); pos += 3; newni = ntfs_dir_parent_inode(curni); if (curni != ni) ntfs_inode_close(curni); curni = newni; if (!curni) ok = FALSE; } else { lth = 0; while (((pos + lth) < count) && (path[pos + lth] != const_cpu_to_le16('\\'))) lth++; if (lth > 0) inum = ntfs_fix_file_name(curni,&path[pos],lth); else inum = (u64)-1; if (!lth || ((curni != ni) && ntfs_inode_close(curni)) || (inum == (u64)-1)) ok = FALSE; else { curni = ntfs_inode_open(ni->vol, MREF(inum)); if (!curni) ok = FALSE; else { if (ok && ((pos + lth) < count)) { path[pos + lth] = const_cpu_to_le16('/'); pos += lth + 1; } else { pos += lth; if ((ni->mrec->flags ^ curni->mrec->flags) & MFT_RECORD_IS_DIRECTORY) ok = FALSE; if (ntfs_inode_close(curni)) ok = FALSE; } } } } } } if (ok && (ntfs_ucstombs(path, count, &target, 0) < 0)) { free(target); // needed ? target = (char*)NULL; } return (target); }