From db5af00af6c47fe8850b8ac73a7d5f15bb8a554d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Pierre=20Andr=C3=A9?= Date: Fri, 6 Jul 2012 09:48:05 +0200 Subject: [PATCH] Processed junctions and symlinks whose target references another one When the target of a junction or a Windows-type symlink references another junction or symlink, the search for the full path on the current partition and its translation for case-sensitive access is interrupted. The target can now be dereferenced, provided the end of the path needed no translation. --- libntfs-3g/reparse.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/libntfs-3g/reparse.c b/libntfs-3g/reparse.c index c5226aa6..13b73f20 100644 --- a/libntfs-3g/reparse.c +++ b/libntfs-3g/reparse.c @@ -3,7 +3,7 @@ * * This module is part of ntfs-3g library * - * Copyright (c) 2008-2009 Jean-Pierre Andre + * Copyright (c) 2008-2012 Jean-Pierre Andre * * 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 @@ -236,6 +236,17 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path, 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) @@ -253,9 +264,11 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path, } } 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->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); @@ -289,12 +302,25 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) int pos; int lth; BOOL ok; + BOOL morelinks; int max = 32; /* safety */ pos = 0; ok = TRUE; + morelinks = FALSE; curni = ntfs_dir_parent_inode(ni); - while (curni && ok && (pos < (count - 1)) && --max) { + /* + * 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('\\'))) { @@ -332,12 +358,18 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) 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 ((ni->mrec->flags ^ curni->mrec->flags) + if (!morelinks + && (ni->mrec->flags ^ curni->mrec->flags) & MFT_RECORD_IS_DIRECTORY) ok = FALSE; if (ntfs_inode_close(curni))