From 3994181361657c8938e8938d55dacbf21f3af0d9 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Fri, 24 Jun 2011 19:37:01 +0000 Subject: [PATCH] *fix for loading games of NTFS partitions with sector size > 512 (thx oggzee for pointing it out) --- libcustomntfs/attrib_frag.c | 2 +- libcustomntfs/ntfsfile_frag.c | 491 ++-------------------------------- 2 files changed, 17 insertions(+), 476 deletions(-) diff --git a/libcustomntfs/attrib_frag.c b/libcustomntfs/attrib_frag.c index 491e8fe5..68b886cc 100644 --- a/libcustomntfs/attrib_frag.c +++ b/libcustomntfs/attrib_frag.c @@ -62,7 +62,7 @@ #include "ntfs.h" #include "ntfsfile_frag.h" -static u8 size_to_shift(u32 size) +static inline u8 size_to_shift(u32 size) { u8 ret = 0; while (size) diff --git a/libcustomntfs/ntfsfile_frag.c b/libcustomntfs/ntfsfile_frag.c index a9eb572c..8771b931 100644 --- a/libcustomntfs/ntfsfile_frag.c +++ b/libcustomntfs/ntfsfile_frag.c @@ -6,7 +6,7 @@ * * 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 - * by the Free Software Foundation; either version 2 of the License, or + * by the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program/include file is distributed in the hope that it will be @@ -44,300 +44,20 @@ #include "ntfs.h" #include "ntfsfile_frag.h" -#define STATE(x) ((ntfs_file_state*)x) - -// for easier comparision of ntfsfile.c against ntfsfile_frag.c -// everything is included but ifdef-ed out - -#if 0 - -void ntfsCloseFile (ntfs_file_state *file) -{ - // Sanity check - if (!file || !file->vd) - return; - - // Special case fix ups for compressed and/or encrypted files - if (file->compressed) - ntfs_attr_pclose(file->data_na); -#ifdef HAVE_SETXATTR - if (file->encrypted) - ntfs_efs_fixup_attribute(NULL, file->data_na); -#endif - // Close the file data attribute (if open) - if (file->data_na) - ntfs_attr_close(file->data_na); - - // Sync the file (and its attributes) to disc - if(file->write) - { - ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME | NTFS_UPDATE_CTIME); - ntfsSync(file->vd, file->ni); - } - - if (file->read) - ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); - - // Close the file (if open) - if (file->ni) - ntfsCloseEntry(file->vd, file->ni); - - // Reset the file state - file->ni = NULL; - file->data_na = NULL; - file->flags = 0; - file->read = false; - file->write = false; - file->append = false; - file->pos = 0; - file->len = 0; - - return; -} - -int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) -{ - ntfs_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode); - - ntfs_file_state* file = STATE(fileStruct); - - // Get the volume descriptor for this path - file->vd = ntfsGetVolume(path); - if (!file->vd) { - r->_errno = ENODEV; - return -1; - } - - // Lock - ntfsLock(file->vd); - - // Determine which mode the file is opened for - file->flags = flags; - if ((flags & 0x03) == O_RDONLY) { - file->read = true; - file->write = false; - file->append = false; - } else if ((flags & 0x03) == O_WRONLY) { - file->read = false; - file->write = true; - file->append = (flags & O_APPEND); - } else if ((flags & 0x03) == O_RDWR) { - file->read = true; - file->write = true; - file->append = (flags & O_APPEND); - } else { - r->_errno = EACCES; - ntfsUnlock(file->vd); - return -1; - } - - // Try and find the file and (if found) ensure that it is not a directory - file->ni = ntfsOpenEntry(file->vd, path); - if (file->ni && (file->ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) { - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - r->_errno = EISDIR; - return -1; - } - - // Are we creating this file? - if (flags & O_CREAT) { - - // The file SHOULD NOT already exist - if (file->ni) { - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - r->_errno = EEXIST; - return -1; - } - - // Create the file - file->ni = ntfsCreate(file->vd, path, S_IFREG, NULL); - if (!file->ni) { - ntfsUnlock(file->vd); - return -1; - } - - } - - // Sanity check, the file should be open by now - if (!file->ni) { - ntfsUnlock(file->vd); - r->_errno = ENOENT; - return -1; - } - - // Open the files data attribute - file->data_na = ntfs_attr_open(file->ni, AT_DATA, AT_UNNAMED, 0); - if(!file->data_na) { - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - return -1; - } - - // Determine if this files data is compressed and/or encrypted - file->compressed = NAttrCompressed(file->data_na) || (file->ni->flags & FILE_ATTR_COMPRESSED); - file->encrypted = NAttrEncrypted(file->data_na) || (file->ni->flags & FILE_ATTR_ENCRYPTED); - - // We cannot read/write encrypted files - if (file->encrypted) { - ntfs_attr_close(file->data_na); - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - r->_errno = EACCES; - return -1; - } - - // Make sure we aren't trying to write to a read-only file - if ((file->ni->flags & FILE_ATTR_READONLY) && file->write) { - ntfs_attr_close(file->data_na); - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - r->_errno = EROFS; - return -1; - } - - // Truncate the file if requested - if ((flags & O_TRUNC) && file->write) { - if (ntfs_attr_truncate(file->data_na, 0)) { - ntfs_attr_close(file->data_na); - ntfsCloseEntry(file->vd, file->ni); - ntfsUnlock(file->vd); - r->_errno = errno; - return -1; - } - } - - // Set the files current position and length - file->pos = 0; - file->len = file->data_na->data_size; - - ntfs_log_trace("file->len %d\n", file->len); - - // Update file times - ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); - - // Insert the file into the double-linked FILO list of open files - if (file->vd->firstOpenFile) { - file->nextOpenFile = file->vd->firstOpenFile; - file->vd->firstOpenFile->prevOpenFile = file; - } else { - file->nextOpenFile = NULL; - } - file->prevOpenFile = NULL; - file->vd->firstOpenFile = file; - file->vd->openFileCount++; - - // Unlock - ntfsUnlock(file->vd); - - return (int)fileStruct; -} - -int ntfs_close_r (struct _reent *r, int fd) -{ - ntfs_log_trace("fd %p\n", fd); - - ntfs_file_state* file = STATE(fd); - - // Sanity check - if (!file || !file->vd) { - r->_errno = EBADF; - return -1; - } - - // Lock - ntfsLock(file->vd); - - // Close the file - ntfsCloseFile(file); - - // Remove the file from the double-linked FILO list of open files - file->vd->openFileCount--; - if (file->nextOpenFile) - file->nextOpenFile->prevOpenFile = file->prevOpenFile; - if (file->prevOpenFile) - file->prevOpenFile->nextOpenFile = file->nextOpenFile; - else - file->vd->firstOpenFile = file->nextOpenFile; - - // Unlock - ntfsUnlock(file->vd); - - return 0; -} - -ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len) -{ - ntfs_log_trace("fd %p, ptr %p, len %Li\n", fd, ptr, len); - - ntfs_file_state* file = STATE(fd); - ssize_t written = 0; - off_t old_pos = 0; - - // Sanity check - if (!file || !file->vd || !file->ni || !file->data_na) { - r->_errno = EINVAL; - return -1; - } - - // Short circuit cases where we don't actually have to do anything - if (!ptr || len <= 0) { - return 0; - } - - // Lock - ntfsLock(file->vd); - - // Check that we are allowed to write to this file - if (!file->write) { - ntfsUnlock(file->vd); - r->_errno = EACCES; - return -1; - } - - // If we are in append mode, backup the current position and move to the end of the file - if (file->append) { - old_pos = file->pos; - file->pos = file->len; - } - - // Write to the files data atrribute - while (len) { - ssize_t ret = ntfs_attr_pwrite(file->data_na, file->pos, len, ptr); - if (ret <= 0) { - ntfsUnlock(file->vd); - r->_errno = errno; - return -1; - } - len -= ret; - file->pos += ret; - written += ret; - } - - // If we are in append mode, restore the current position to were it was prior to this write - if (file->append) { - file->pos = old_pos; - } - - // Mark the file for archiving (if we actually wrote something) - if (written) - file->ni->flags |= FILE_ATTR_ARCHIVE; - - // Update the files data length - file->len = file->data_na->data_size; - - // Unlock - ntfsUnlock(file->vd); - - return written; -} - -#endif - s64 ntfs_attr_getfragments(ntfs_attr *na, const s64 pos, s64 count, u64 offset, _ntfs_frag_append_t append_fragment, void *callback_data); +static inline u8 size_to_shift(u32 size) +{ + u8 ret = 0; + while (size) + { + ret++; + size >>= 1; + } + return ret - 1; +} + int _NTFS_get_fragments (const char *path, _ntfs_frag_append_t append_fragment, void *callback_data) { @@ -352,39 +72,15 @@ int _NTFS_get_fragments (const char *path, if (fd != (int)file) return -12; - - - // Sanity check if (!file || !file->vd || !file->ni || !file->data_na) { //r->_errno = EINVAL; return -13; } - /* - // Short circuit cases where we don't actually have to do anything - if (!ptr || len <= 0) { - return 0; - } - */ - + // Lock ntfsLock(file->vd); - /* - // Check that we are allowed to read from this file - if (!file->read) { - ntfsUnlock(file->vd); - r->_errno = EACCES; - return -1; - } - - // Don't read past the end of file - if (file->pos + len > file->len) { - r->_errno = EOVERFLOW; - len = file->len - file->pos; - ntfs_log_trace("EOVERFLOW"); - } - */ u64 offset = 0; u64 len = file->len; @@ -406,17 +102,13 @@ int _NTFS_get_fragments (const char *path, read += ret; } + u32 shift = size_to_shift(file->ni->vol->sector_size); + // set file size - append_fragment(callback_data, file->len >> 9, 0, 0); + append_fragment(callback_data, file->len >> shift, 0, 0); // success ret_val = 0; - /* - //ntfs_log_trace("file->pos: %d \n", (u32)file->pos); - // Update file times (if we actually read something) - if (read) - ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); - */ out: // Unlock @@ -427,154 +119,3 @@ out: return ret_val; } -#if 0 - -off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir) -{ - ntfs_log_trace("fd %p, pos %Li, dir %i\n", fd, pos, dir); - - ntfs_file_state* file = STATE(fd); - off_t position = 0; - - // Sanity check - if (!file || !file->vd || !file->ni || !file->data_na) { - r->_errno = EINVAL; - return -1; - } - - // Lock - ntfsLock(file->vd); - - // Set the files current position - switch(dir) { - case SEEK_SET: position = file->pos = MIN(MAX(pos, 0), file->len); break; - case SEEK_CUR: position = file->pos = MIN(MAX(file->pos + pos, 0), file->len); break; - case SEEK_END: position = file->pos = MIN(MAX(file->len + pos, 0), file->len); break; - } - - // Unlock - ntfsUnlock(file->vd); - - return position; -} -int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st) -{ - ntfs_log_trace("fd %p\n", fd); - - ntfs_file_state* file = STATE(fd); - int ret = 0; - - // Sanity check - if (!file || !file->vd || !file->ni || !file->data_na) { - r->_errno = EINVAL; - return -1; - } - - // Short circuit cases were we don't actually have to do anything - if (!st) - return 0; - - // Get the file stats - ret = ntfsStat(file->vd, file->ni, st); - if (ret) - r->_errno = errno; - - return ret; -} - -int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len) -{ - ntfs_log_trace("fd %p, len %Li\n", fd, len); - - ntfs_file_state* file = STATE(fd); - - // Sanity check - if (!file || !file->vd || !file->ni || !file->data_na) { - r->_errno = EINVAL; - return -1; - } - - // Lock - ntfsLock(file->vd); - - // Check that we are allowed to write to this file - if (!file->write) { - ntfsUnlock(file->vd); - r->_errno = EACCES; - return -1; - } - - // For compressed files, only deleting and expanding contents are implemented - if (file->compressed && - len > 0 && - len < file->data_na->initialized_size) { - ntfsUnlock(file->vd); - r->_errno = EOPNOTSUPP; - return -1; - } - - // Resize the files data attribute, either by expanding or truncating - if (file->compressed && len > file->data_na->initialized_size) { - char zero = 0; - if (ntfs_attr_pwrite(file->data_na, len - 1, 1, &zero) <= 0) { - ntfsUnlock(file->vd); - r->_errno = errno; - return -1; - } - } else { - if (ntfs_attr_truncate(file->data_na, len)) { - ntfsUnlock(file->vd); - r->_errno = errno; - return -1; - } - } - - // Mark the file for archiving (if we actually changed something) - if (file->len != file->data_na->data_size) - file->ni->flags |= FILE_ATTR_ARCHIVE; - - // Update file times (if we actually changed something) - if (file->len != file->data_na->data_size) - ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_AMCTIME); - - // Update the files data length - file->len = file->data_na->data_size; - - // Sync the file (and its attributes) to disc - ntfsSync(file->vd, file->ni); - - // Unlock - ntfsUnlock(file->vd); - - return 0; -} - -int ntfs_fsync_r (struct _reent *r, int fd) -{ - ntfs_log_trace("fd %p\n", fd); - - ntfs_file_state* file = STATE(fd); - int ret = 0; - - // Sanity check - if (!file || !file->vd || !file->ni || !file->data_na) { - r->_errno = EINVAL; - return -1; - } - - // Lock - ntfsLock(file->vd); - - // Sync the file (and its attributes) to disc - ret = ntfsSync(file->vd, file->ni); - if (ret) - r->_errno = errno; - - // Unlock - ntfsUnlock(file->vd); - - return ret; -} - -#endif -