1N/A * dir.c - Directory handling code. Part of the Linux-NTFS project. 1N/A * Copyright (c) 2002-2005 Anton Altaparmakov 1N/A * Copyright (c) 2005-2007 Yura Pakhuchiy 1N/A * Copyright (c) 2004-2005 Richard Russon 1N/A * modify it under the terms of the GNU General Public License as published 1N/A * by the Free Software Foundation; either version 2 of the License, or 1N/A * (at your option) any later version. 1N/A * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 1N/A * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1N/A * GNU General Public License for more details. 1N/A * You should have received a copy of the GNU General Public License 1N/A * along with this program (in the main directory of the Linux-NTFS 1N/A * distribution in the file COPYING); if not, write to the Free Software 1N/A * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1N/A * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O" 1N/A * and "$Q" as global constants. 1N/A * ntfs_inode_lookup_by_name - find an inode in a directory given its name 1N/A * @dir_ni: ntfs inode of the directory in which to search for the name 1N/A * @uname: Unicode name for which to search in the directory 1N/A * @uname_len: length of the name @uname in Unicode characters 1N/A * Look for an inode with name @uname in the directory with inode @dir_ni. 1N/A * ntfs_inode_lookup_by_name() walks the contents of the directory looking for 1N/A * the Unicode name. If the name is found in the directory, the corresponding 1N/A * inode number (>= 0) is returned as a mft reference in cpu format, i.e. it 1N/A * is a 64-bit number containing the sequence number. 1N/A * On error, return -1 with errno set to the error code. If the inode is is not 1N/A * found errno is ENOENT. 1N/A * Note, @uname_len does not include the (optional) terminating NULL character. 1N/A * Note, we look for a case sensitive match first but we also look for a case 1N/A * insensitive match at the same time. If we find a case insensitive match, we 1N/A * save that for the case that we don't find an exact match, where we return 1N/A * the mft reference of the case insensitive match. 1N/A * If the volume is mounted with the case sensitive flag set, then we only 1N/A * allow exact matches. 1N/A /* Find the index root attribute in the mft record. */ 1N/A /* Get to the index root value. */ 1N/A /* The first index entry. */ 1N/A * Loop until we exceed valid memory (corruption case) or until we 1N/A * reach the last entry. 1N/A /* Bounds checks. */ 1N/A * The last entry cannot contain a name. It can however contain 1N/A * a pointer to a child node in the B+tree so we just break out. 1N/A * We perform a case sensitive comparison and if that matches 1N/A * we are done and return the mft reference of the inode (i.e. 1N/A * the inode number together with the sequence number for 1N/A * consistency checking). We convert it to cpu format before 1N/A * We have a perfect match, so we don't need to care 1N/A * about having matched imperfectly before. 1N/A * For a case insensitive mount, we also perform a case 1N/A * insensitive comparison. If the comparison matches, we cache 1N/A * the mft reference in mref. Use first case insensitive match 1N/A * in case if no name matches case sensitive, but several names 1N/A * matches case insensitive. 1N/A * Not a perfect match, need to do full blown collation so we 1N/A * know which way in the B+tree we have to go. 1N/A * If uname collates before the name of the current entry, there 1N/A * is definitely no such name in this index but we might need to 1N/A * descend into the B+tree so we just break out of the loop. 1N/A /* The names are not equal, continue the search. */ 1N/A * Names match with case insensitive comparison, now try the 1N/A * case sensitive comparison, which is required for proper 1N/A * Perfect match, this will never happen as the 1N/A * ntfs_are_names_equal() call will have gotten a match but we 1N/A * still treat it correctly. 1N/A * We have finished with this index without success. Check for the 1N/A * presence of a child node and if not present return error code 1N/A * ENOENT, unless we have got the mft reference of a matching name 1N/A * cached in mref in which case return mref. 1N/A }
/* Child node present, descend into it. */ 1N/A /* Open the index allocation attribute. */ 1N/A "Directory inode 0x%llx is corrupt or driver " 1N/A /* Allocate a buffer for the current index block. */ 1N/A /* Determine the size of a vcn in the directory index. */ 1N/A /* Get the starting vcn of the index_block holding the child node. */ 1N/A /* Read the index block starting at vcn. */ 1N/A "different from expected VCN (0x%llx).\n",
1N/A "0x%llx has a size (%u) differing from the " 1N/A "directory specified size (%u).\n",
1N/A "inode 0x%llx exceeds maximum size.\n",
1N/A /* The first index entry. */ 1N/A * Iterate similar to above big loop but applied to index buffer, thus 1N/A * loop until we exceed valid memory (corruption case) or until we 1N/A * reach the last entry. 1N/A * The last entry cannot contain a name. It can however contain 1N/A * a pointer to a child node in the B+tree so we just break out. 1N/A * We perform a case sensitive comparison and if that matches 1N/A * we are done and return the mft reference of the inode (i.e. 1N/A * the inode number together with the sequence number for 1N/A * consistency checking). We convert it to cpu format before 1N/A * We have a perfect match, so we don't need to care 1N/A * about having matched imperfectly before. 1N/A * For a case insensitive mount, we also perform a case 1N/A * insensitive comparison. If the comparison matches, we cache 1N/A * the mft reference in mref. Use first case insensitive match 1N/A * in case if no name matches case sensitive, but several names 1N/A * matches case insensitive. 1N/A * Not a perfect match, need to do full blown collation so we 1N/A * know which way in the B+tree we have to go. 1N/A * If uname collates before the name of the current entry, there 1N/A * is definitely no such name in this index but we might need to 1N/A * descend into the B+tree so we just break out of the loop. 1N/A /* The names are not equal, continue the search. */ 1N/A * Names match with case insensitive comparison, now try the 1N/A * case sensitive comparison, which is required for proper 1N/A * Perfect match, this will never happen as the 1N/A * ntfs_are_names_equal() call will have gotten a match but we 1N/A * still treat it correctly. 1N/A * We have finished with this index buffer without success. Check for 1N/A * the presence of a child node. 1N/A "leaf node in directory inode " 1N/A /* Child node present, descend into it. */ 1N/A * No child node present, return error code ENOENT, unless we have got 1N/A * the mft reference of a matching name cached in mref in which case 1N/A * ntfs_pathname_to_inode_num - find the inode number which represents the 1N/A * @vol: An ntfs volume obtained from ntfs_mount 1N/A * @parent: A directory inode to begin the search (may be NULL) 1N/A * @pathname: Pathname to be located 1N/A * Take an ASCII pathname and find the inode that represents it. The function 1N/A * splits the path and then descends the directory tree. If @parent is NULL, 1N/A * then the root directory '.' will be used as the base for the search. 1N/A * Return: -1 Error, the pathname was invalid, or some other error occurred 1N/A * else Success, the pathname was valid 1N/A /* Remove leading /'s. */ 1N/A /* Find the end of the first token. */ 1N/A * ntfs_pathname_to_inode - Find the inode which represents the given pathname 1N/A * @vol: An ntfs volume obtained from ntfs_mount 1N/A * @parent: A directory inode to begin the search (may be NULL) 1N/A * @pathname: Pathname to be located 1N/A * Take an ASCII pathname and find the inode that represents it. The function 1N/A * splits the path and then descends the directory tree. If @parent is NULL, 1N/A * then the root directory '.' will be used as the base for the search. 1N/A * Return: inode Success, the pathname was valid 1N/A * NULL Error, the pathname was invalid, or some other error occurred 1N/A * The little endian Unicode string ".." for ntfs_readdir(). 1N/A * ntfs_filldir - ntfs specific filldir method 1N/A * @vol: ntfs volume with wjich we are working 1N/A * @pos: current position in directory 1N/A * @ie: current index entry 1N/A * @dirent: context for filldir callback supplied by the caller 1N/A * @filldir: filldir callback supplied by the caller 1N/A * Pass information specifying the current directory entry @ie to the @filldir 1N/A /* Skip root directory self reference entry. */ 1N/A * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode 1N/A * @ni: ntfs inode whose parent directory to find 1N/A * Find the parent directory of the ntfs inode @ni. To do this, find the first 1N/A * file name attribute in the mft record of @ni and return the parent mft 1N/A * reference from that. 1N/A * Note this only makes sense for directories, since files can be hard linked 1N/A * from multiple directories and there is no way for us to tell which one is 1N/A * Technically directories can have hard links, too, but we consider that as 1N/A * illegal as Linux/UNIX do not support directory hard links. 1N/A * Return the mft reference of the parent directory on success or -1 on error 1N/A * with errno set to the error code. 1N/A "Corrupt inode 0x%llx.\n",
1N/A * ntfs_readdir - read the contents of an ntfs directory 1N/A * @dir_ni: ntfs inode of current directory 1N/A * @pos: current position in directory 1N/A * @dirent: context for filldir callback supplied by the caller 1N/A * @filldir: filldir callback supplied by the caller 1N/A * Parse the index root and the index blocks that are marked in use in the 1N/A * index bitmap and hand each found directory entry to the @filldir callback 1N/A * supplied by the caller. 1N/A * Return 0 on success or -1 on error with errno set to the error code. 1N/A * Note: Index blocks are parsed in ascending vcn order, from which follows 1N/A * that the directory entries are not returned sorted. 1N/A /* Open the index allocation attribute. */ 1N/A "attribute. Directory inode 0x%llx is " 1N/A "corrupt or bug", (
unsigned long long)
1N/A /* Are we at end of dir yet? */ 1N/A /* Emulate . and .. for all directories. */ 1N/A /* Get the offset into the index root attribute. */ 1N/A /* Find the index root attribute in the mft record. */ 1N/A "inode 0x%llx.\n", (
unsigned long long)
dir_ni->
1N/A /* Get to the index root value. */ 1N/A /* Determine the size of a vcn in the directory index. */ 1N/A /* Are we jumping straight into the index allocation attribute? */ 1N/A /* The first index entry. */ 1N/A * Loop until we exceed valid memory (corruption case) or until we 1N/A * reach the last entry or until filldir tells us it has had enough 1N/A * or signals an error (both covered by the rc test). 1N/A /* Bounds checks. */ 1N/A /* The last entry cannot contain a name. */ 1N/A /* Skip index root entry if continuing previous readdir. */ 1N/A /* Advance the position even if going to skip the entry. */ 1N/A * Submit the directory entry to ntfs_filldir(), which will 1N/A * invoke the filldir() callback as appropriate. 1N/A /* If there is no index allocation attribute we are finished. */ 1N/A /* Advance *pos to the beginning of the index allocation. */ 1N/A /* Allocate a buffer for the current index block. */ 1N/A /* Get the offset into the index allocation attribute. */ 1N/A /* If the index block is not in use find the next one that is. */ 1N/A /* If we have reached the end of the bitmap, we are done. */ 1N/A /* Read next chunk from the index bitmap. */ 1N/A /* Read the index block starting at bmp_pos. */ 1N/A "different from expected VCN (0x%llx) in " 1N/A "0x%llx has a size (%u) differing from the " 1N/A "directory specified size (%u).\n",
1N/A "inode 0x%llx exceeds maximum size.\n",
1N/A /* The first index entry. */ 1N/A * Loop until we exceed valid memory (corruption case) or until we 1N/A * reach the last entry or until ntfs_filldir tells us it has had 1N/A * enough or signals an error (both covered by the rc test). 1N/A /* Bounds checks. */ 1N/A "inode 0x%llx.\n", (
unsigned long long)
1N/A /* The last entry cannot contain a name. */ 1N/A /* Skip index entry if continuing previous readdir. */ 1N/A /* Advance the position even if going to skip the entry. */ 1N/A * Submit the directory entry to ntfs_filldir(), which will 1N/A * invoke the filldir() callback as appropriate. 1N/A /* We are finished, set *pos to EOD. */ 1N/A * __ntfs_create - create object on ntfs volume 1N/A * @dir_ni: ntfs inode for directory in which create new object 1N/A * @name: unicode name of new object 1N/A * @name_len: length of the name in unicode characters 1N/A * @type: type of the object to create 1N/A * @dev: major and minor device numbers (obtained from makedev()) 1N/A * @target: target in unicode (only for symlinks) 1N/A * @target_len: length of target in unicode characters 1N/A * Internal, use ntfs_create{,_device,_symlink} wrappers instead. 1N/A * S_IFREG to create regular file 1N/A * S_IFDIR to create directory 1N/A * S_IFBLK to create block device 1N/A * S_IFCHR to create character device 1N/A * S_IFLNK to create symbolic link 1N/A * S_IFIFO to create FIFO 1N/A * S_IFSOCK to create socket 1N/A * other values are invalid. 1N/A * @dev is used only if @type is S_IFBLK or S_IFCHR, in other cases its value 1N/A * @target and @target_len are used only if @type is S_IFLNK, in other cases 1N/A * their value ignored. 1N/A * Return opened ntfs inode that describes created object on success or NULL 1N/A * on error with errno set to the error code. 1N/A /* Sanity checks. */ 1N/A /* FIXME: Reparse points requires special handling. */ 1N/A /* Allocate MFT record for new file. */ 1N/A * Create STANDARD_INFORMATION attribute. Write STANDARD_INFORMATION 1N/A * version 1.2, windows will upgrade it to version 3 if needed. 1N/A /* Add STANDARD_INFORMATION to inode. */ 1N/A /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ 1N/A * Calculate security descriptor length. We have 2 sub-authorities in 1N/A * owner and group SIDs, but structure SID contain only one, so add 1N/A * 4 bytes to every SID. 1N/A /* Add SECURITY_DESCRIPTOR attribute to inode. */ 1N/A /* Create INDEX_ROOT attribute. */ 1N/A /* Add INDEX_ROOT attribute to inode. */ 1N/A default:
/* FIFO or regular file. */ 1N/A /* Add DATA attribute to inode. */ 1N/A /* Create FILE_NAME attribute. */ 1N/A /* Add FILE_NAME attribute to inode. */ 1N/A /* Add FILE_NAME attribute to index. */ 1N/A /* Set hard links count and directory flag. */ 1N/A " inode 0x%llx. Run chkdsk.\n",
1N/A "of inode 0x%llx. Run chkdsk.\n",
1N/A " inode 0x%llx. Run chkdsk.\n",
1N/A "inode 0x%llx. Run chkdsk.\n",
1N/A * Free extent MFT records (should not exist any with current 1N/A * ntfs_create implementation, but for any case if something will be 1N/A * changed in the future). 1N/A "Leaving inconsistent metadata.\n");
1N/A "Leaving inconsistent metadata. Run chkdsk.\n");
1N/A * Some wrappers around __ntfs_create() ... 1N/A * ntfs_delete - delete file or directory from ntfs volume 1N/A * @pni: ntfs inode for object to delete 1N/A * @dir_ni: ntfs inode for directory in which delete object 1N/A * @name: unicode name of the object to delete 1N/A * @name_len: length of the name in unicode characters 1N/A * @pni is pointer to pointer to ntfs_inode structure. Upon successful 1N/A * completion and if inode is really deleted (there are no more links left to 1N/A * it) this function will close @*pni and set it to NULL, in the other cases 1N/A * @*pni will stay opened. 1N/A * Return 0 on success or -1 on error with errno set to the error code. 1N/A * Search for FILE_NAME attribute with such name. If it's in POSIX or 1N/A * WIN32_AND_DOS namespace, then simply remove it from index and inode. 1N/A * If filename in DOS or in WIN32 namespace, then remove DOS name first, 1N/A * only then remove WIN32 name. Mark WIN32 name as POSIX name to prevent 1N/A * chkdsk to complain about DOS name absence in case if DOS name had 1N/A * been successfully deleted, but WIN32 name remove failed. 1N/A "Looking for DOS name.\n");
1N/A * If case sensitive search failed and volume mounted case 1N/A * insensitive, then try once again ignoring case. 1N/A "attributes that belong to this inode.\n");
1N/A /* If deleting directory check it to be empty. */ 1N/A * Do not allow non-empty directory deletion if hard links count 1N/A * is 1 (always) or 2 (in case if filename in DOS namespace, 1N/A * because we delete it first in file which have both WIN32 and 1N/A /* One more sanity check. */ 1N/A /* Search for such FILE_NAME in index. */ 1N/A /* Set namespace to POSIX for WIN32 name. */ 1N/A /* Do not support reparse point deletion yet. */ 1N/A /* Remove FILE_NAME from index. */ 1N/A /* Remove FILE_NAME from inode. */ 1N/A /* Decrement hard link count. */ 1N/A "Now search for WIN32 name.\n");
1N/A /* TODO: Update object id, quota and security indexes if required. */ 1N/A * If hard link count is not equal to zero then we are done. In other 1N/A * case there are no reference to this inode left, so we should free all 1N/A * non-resident attributes and mark all MFT record as not in use. 1N/A "Leaving inconsistent " 1N/A "Leaving inconsistent " 1N/A "Probably leaving inconsistent metadata.\n");
1N/A /* All extents should be attached after attribute walk. */ 1N/A "Leaving inconsistent metadata.\n");
1N/A "Leaving inconsistent metadata.\n");
1N/A * ntfs_link - create hard link for file or directory 1N/A * @ni: ntfs inode for object to create hard link 1N/A * @dir_ni: ntfs inode for directory in which new link should be placed 1N/A * @name: unicode name of the new link 1N/A * @name_len: length of the name in unicode characters 1N/A * NOTE: At present we allow creating hard links to directories, we use them 1N/A * in a temporary state during rename. But it's definitely bad idea to have 1N/A * hard links to directories as a result of operation. 1N/A * FIXME: Create internal __ntfs_link that allows hard links to a directories 1N/A * and external ntfs_link that do not. Write ntfs_rename that uses __ntfs_link. 1N/A * Return 0 on success or -1 on error with errno set to the error code. 1N/A /* FIXME: Reparse points requires special handling. */ 1N/A /* Create FILE_NAME attribute. */ 1N/A /* Add FILE_NAME attribute to index. */ 1N/A /* Add FILE_NAME attribute to inode. */ 1N/A /* Try to remove just added attribute from index. */ 1N/A /* Increment hard links count. */