mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-16 00:15:08 +01:00
0f17471b27
*Added sources of the custom libs to the branches *Fixed crash when switching from list layout to grid/carousel layout *Removed 1:1 copy option because its meaningless and almost the same as installing all partitions *Fixed install partition selection. This option needs a reset. Go to settings and reselect your option for this. *Fixed schinese and tchinese language modes (filename bugs. has to be schinese.lang and tchinese.lang like on SVN) *Fixed bug in sound buffer circle *Fixed incorrect behaviour of x-flip when selecting system like (thx Cyan for the patch) *Accept ios revision 65535 for Waninkokos IOSes (thx to PPSainity for pointing it out) *Merged the new theming style branch into trunk. Just as a reminder: ALL old themes will not work until the themers did port it to the new style! *Removed old theme style completely Theme example: The example file of the theme is the Default.them file. It can be found in the SVN trunk. Change in loading of themes: When selecting a theme now a list of all .them files in a folder is displayed. The image folder of that theme has to be in the same folder as the .them file. The image path is defined in the head of the .them file in the line with "Image-Folder: Example\n".
315 lines
8.8 KiB
C
315 lines
8.8 KiB
C
/**
|
|
* attrlist.c - Attribute list attribute handling code. Originated from the Linux-NTFS
|
|
* project.
|
|
*
|
|
* Copyright (c) 2004-2005 Anton Altaparmakov
|
|
* Copyright (c) 2004-2005 Yura Pakhuchiy
|
|
* Copyright (c) 2006 Szabolcs Szakacsits
|
|
*
|
|
* 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
|
|
* (at your option) any later version.
|
|
*
|
|
* This program/include file is distributed in the hope that it will be
|
|
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program (in the main directory of the NTFS-3G
|
|
* distribution in the file COPYING); if not, write to the Free Software
|
|
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
|
|
#include "types.h"
|
|
#include "layout.h"
|
|
#include "attrib.h"
|
|
#include "attrlist.h"
|
|
#include "debug.h"
|
|
#include "unistr.h"
|
|
#include "logging.h"
|
|
#include "misc.h"
|
|
|
|
/**
|
|
* ntfs_attrlist_need - check whether inode need attribute list
|
|
* @ni: opened ntfs inode for which perform check
|
|
*
|
|
* Check whether all are attributes belong to one MFT record, in that case
|
|
* attribute list is not needed.
|
|
*
|
|
* Return 1 if inode need attribute list, 0 if not, -1 on error with errno set
|
|
* to the error code. If function succeed errno set to 0. The following error
|
|
* codes are defined:
|
|
* EINVAL - Invalid arguments passed to function or attribute haven't got
|
|
* attribute list.
|
|
*/
|
|
int ntfs_attrlist_need(ntfs_inode *ni)
|
|
{
|
|
ATTR_LIST_ENTRY *ale;
|
|
|
|
if (!ni) {
|
|
ntfs_log_trace("Invalid arguments.\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
ntfs_log_trace("Entering for inode 0x%llx.\n", (long long) ni->mft_no);
|
|
|
|
if (!NInoAttrList(ni)) {
|
|
ntfs_log_trace("Inode haven't got attribute list.\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (!ni->attr_list) {
|
|
ntfs_log_trace("Corrupt in-memory struct.\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
errno = 0;
|
|
ale = (ATTR_LIST_ENTRY *)ni->attr_list;
|
|
while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
|
|
if (MREF_LE(ale->mft_reference) != ni->mft_no)
|
|
return 1;
|
|
ale = (ATTR_LIST_ENTRY *)((u8*)ale + le16_to_cpu(ale->length));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* ntfs_attrlist_entry_add - add an attribute list attribute entry
|
|
* @ni: opened ntfs inode, which contains that attribute
|
|
* @attr: attribute record to add to attribute list
|
|
*
|
|
* Return 0 on success and -1 on error with errno set to the error code. The
|
|
* following error codes are defined:
|
|
* EINVAL - Invalid arguments passed to function.
|
|
* ENOMEM - Not enough memory to allocate necessary buffers.
|
|
* EIO - I/O error occurred or damaged filesystem.
|
|
* EEXIST - Such attribute already present in attribute list.
|
|
*/
|
|
int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
|
|
{
|
|
ATTR_LIST_ENTRY *ale;
|
|
MFT_REF mref;
|
|
ntfs_attr *na = NULL;
|
|
ntfs_attr_search_ctx *ctx;
|
|
u8 *new_al;
|
|
int entry_len, entry_offset, err;
|
|
|
|
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
|
|
(long long) ni->mft_no,
|
|
(unsigned) le32_to_cpu(attr->type));
|
|
|
|
if (!ni || !attr) {
|
|
ntfs_log_trace("Invalid arguments.\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
mref = MK_LE_MREF(ni->mft_no, le16_to_cpu(ni->mrec->sequence_number));
|
|
|
|
if (ni->nr_extents == -1)
|
|
ni = ni->base_ni;
|
|
|
|
if (!NInoAttrList(ni)) {
|
|
ntfs_log_trace("Attribute list isn't present.\n");
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
|
|
/* Determine size and allocate memory for new attribute list. */
|
|
entry_len = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
|
|
attr->name_length + 7) & ~7;
|
|
new_al = ntfs_calloc(ni->attr_list_size + entry_len);
|
|
if (!new_al)
|
|
return -1;
|
|
|
|
/* Find place for the new entry. */
|
|
ctx = ntfs_attr_get_search_ctx(ni, NULL);
|
|
if (!ctx) {
|
|
err = errno;
|
|
goto err_out;
|
|
}
|
|
if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*)
|
|
((u8*)attr + le16_to_cpu(attr->name_offset)) :
|
|
AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
|
|
(attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) :
|
|
0, (attr->non_resident) ? NULL : ((u8*)attr +
|
|
le16_to_cpu(attr->value_offset)), (attr->non_resident) ?
|
|
0 : le32_to_cpu(attr->value_length), ctx)) {
|
|
/* Found some extent, check it to be before new extent. */
|
|
if (ctx->al_entry->lowest_vcn == attr->lowest_vcn) {
|
|
err = EEXIST;
|
|
ntfs_log_trace("Such attribute already present in the "
|
|
"attribute list.\n");
|
|
ntfs_attr_put_search_ctx(ctx);
|
|
goto err_out;
|
|
}
|
|
/* Add new entry after this extent. */
|
|
ale = (ATTR_LIST_ENTRY*)((u8*)ctx->al_entry +
|
|
le16_to_cpu(ctx->al_entry->length));
|
|
} else {
|
|
/* Check for real errors. */
|
|
if (errno != ENOENT) {
|
|
err = errno;
|
|
ntfs_log_trace("Attribute lookup failed.\n");
|
|
ntfs_attr_put_search_ctx(ctx);
|
|
goto err_out;
|
|
}
|
|
/* No previous extents found. */
|
|
ale = ctx->al_entry;
|
|
}
|
|
/* Don't need it anymore, @ctx->al_entry points to @ni->attr_list. */
|
|
ntfs_attr_put_search_ctx(ctx);
|
|
|
|
/* Determine new entry offset. */
|
|
entry_offset = ((u8 *)ale - ni->attr_list);
|
|
/* Set pointer to new entry. */
|
|
ale = (ATTR_LIST_ENTRY *)(new_al + entry_offset);
|
|
/* Zero it to fix valgrind warning. */
|
|
memset(ale, 0, entry_len);
|
|
/* Form new entry. */
|
|
ale->type = attr->type;
|
|
ale->length = cpu_to_le16(entry_len);
|
|
ale->name_length = attr->name_length;
|
|
ale->name_offset = offsetof(ATTR_LIST_ENTRY, name);
|
|
if (attr->non_resident)
|
|
ale->lowest_vcn = attr->lowest_vcn;
|
|
else
|
|
ale->lowest_vcn = 0;
|
|
ale->mft_reference = mref;
|
|
ale->instance = attr->instance;
|
|
memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset),
|
|
attr->name_length * sizeof(ntfschar));
|
|
|
|
/* Resize $ATTRIBUTE_LIST to new length. */
|
|
na = ntfs_attr_open(ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
|
|
if (!na) {
|
|
err = errno;
|
|
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
|
|
goto err_out;
|
|
}
|
|
if (ntfs_attr_truncate(na, ni->attr_list_size + entry_len)) {
|
|
err = errno;
|
|
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
|
|
goto err_out;
|
|
}
|
|
|
|
/* Copy entries from old attribute list to new. */
|
|
memcpy(new_al, ni->attr_list, entry_offset);
|
|
memcpy(new_al + entry_offset + entry_len, ni->attr_list +
|
|
entry_offset, ni->attr_list_size - entry_offset);
|
|
|
|
/* Set new runlist. */
|
|
free(ni->attr_list);
|
|
ni->attr_list = new_al;
|
|
ni->attr_list_size = ni->attr_list_size + entry_len;
|
|
NInoAttrListSetDirty(ni);
|
|
/* Done! */
|
|
ntfs_attr_close(na);
|
|
return 0;
|
|
err_out:
|
|
if (na)
|
|
ntfs_attr_close(na);
|
|
free(new_al);
|
|
errno = err;
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* ntfs_attrlist_entry_rm - remove an attribute list attribute entry
|
|
* @ctx: attribute search context describing the attribute list entry
|
|
*
|
|
* Remove the attribute list entry @ctx->al_entry from the attribute list.
|
|
*
|
|
* Return 0 on success and -1 on error with errno set to the error code.
|
|
*/
|
|
int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
|
|
{
|
|
u8 *new_al;
|
|
int new_al_len;
|
|
ntfs_inode *base_ni;
|
|
ntfs_attr *na;
|
|
ATTR_LIST_ENTRY *ale;
|
|
int err;
|
|
|
|
if (!ctx || !ctx->ntfs_ino || !ctx->al_entry) {
|
|
ntfs_log_trace("Invalid arguments.\n");
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (ctx->base_ntfs_ino)
|
|
base_ni = ctx->base_ntfs_ino;
|
|
else
|
|
base_ni = ctx->ntfs_ino;
|
|
ale = ctx->al_entry;
|
|
|
|
ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld.\n",
|
|
(long long) ctx->ntfs_ino->mft_no,
|
|
(unsigned) le32_to_cpu(ctx->al_entry->type),
|
|
(long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
|
|
|
|
if (!NInoAttrList(base_ni)) {
|
|
ntfs_log_trace("Attribute list isn't present.\n");
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
|
|
/* Allocate memory for new attribute list. */
|
|
new_al_len = base_ni->attr_list_size - le16_to_cpu(ale->length);
|
|
new_al = ntfs_calloc(new_al_len);
|
|
if (!new_al)
|
|
return -1;
|
|
|
|
/* Reisze $ATTRIBUTE_LIST to new length. */
|
|
na = ntfs_attr_open(base_ni, AT_ATTRIBUTE_LIST, AT_UNNAMED, 0);
|
|
if (!na) {
|
|
err = errno;
|
|
ntfs_log_trace("Failed to open $ATTRIBUTE_LIST attribute.\n");
|
|
goto err_out;
|
|
}
|
|
if (ntfs_attr_truncate(na, new_al_len)) {
|
|
err = errno;
|
|
ntfs_log_trace("$ATTRIBUTE_LIST resize failed.\n");
|
|
goto err_out;
|
|
}
|
|
|
|
/* Copy entries from old attribute list to new. */
|
|
memcpy(new_al, base_ni->attr_list, (u8*)ale - base_ni->attr_list);
|
|
memcpy(new_al + ((u8*)ale - base_ni->attr_list), (u8*)ale + le16_to_cpu(
|
|
ale->length), new_al_len - ((u8*)ale - base_ni->attr_list));
|
|
|
|
/* Set new runlist. */
|
|
free(base_ni->attr_list);
|
|
base_ni->attr_list = new_al;
|
|
base_ni->attr_list_size = new_al_len;
|
|
NInoAttrListSetDirty(base_ni);
|
|
/* Done! */
|
|
ntfs_attr_close(na);
|
|
return 0;
|
|
err_out:
|
|
if (na)
|
|
ntfs_attr_close(na);
|
|
free(new_al);
|
|
errno = err;
|
|
return -1;
|
|
}
|