mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-15 16:05:10 +01:00
Updated LibNTFS to 2013-01-13 version
https://code.google.com/p/libntfs-wii/ Added MEM2_alloc for Wii.
This commit is contained in:
parent
d90a6f0429
commit
f145fb1e91
@ -22,8 +22,13 @@ wii-release:
|
|||||||
clean:
|
clean:
|
||||||
$(MAKE) -C source clean
|
$(MAKE) -C source clean
|
||||||
|
|
||||||
install: cube-release wii-release
|
cube-install: cube-release
|
||||||
$(MAKE) -C source install
|
$(MAKE) -C source cube-install PLATFORM=cube
|
||||||
|
|
||||||
|
wii-install: wii-release
|
||||||
|
$(MAKE) -C source wii-install PLATFORM=wii
|
||||||
|
|
||||||
|
install: wii-install
|
||||||
|
|
||||||
run: install
|
run: install
|
||||||
$(MAKE) -C example
|
$(MAKE) -C example
|
||||||
|
@ -28,7 +28,7 @@ LIBDIR := ../lib
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
CFLAGS = -O2 -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
|
CFLAGS = -Os -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
|
||||||
CXXFLAGS = $(CFLAGS)
|
CXXFLAGS = $(CFLAGS)
|
||||||
ASFLAGS := -g
|
ASFLAGS := -g
|
||||||
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
|
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
|
||||||
@ -97,14 +97,13 @@ clean:
|
|||||||
|
|
||||||
all: $(NTFSBIN)
|
all: $(NTFSBIN)
|
||||||
|
|
||||||
install:
|
cube-install:
|
||||||
cp ../include/ntfs.h $(DEVKITPRO)/libogc/include
|
cp ../include/ntfs.h $(DEVKITPRO)/libogc/include
|
||||||
cp ../lib/wii/libntfs.a $(DEVKITPRO)/libogc/lib/wii
|
|
||||||
cp ../lib/cube/libntfs.a $(DEVKITPRO)/libogc/lib/cube
|
cp ../lib/cube/libntfs.a $(DEVKITPRO)/libogc/lib/cube
|
||||||
|
|
||||||
wii-install:
|
wii-install:
|
||||||
cp ../include/ntfs.h $(DEVKITPRO)/libogc/include
|
cp ../include/ntfs.h $(PORTLIBS)/include
|
||||||
cp ../lib/wii/libntfs.a $(DEVKITPRO)/libogc/lib/wii
|
cp ../lib/wii/libntfs.a $(PORTLIBS)/lib
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
else
|
else
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* This module is part of ntfs-3g library, but may also be
|
* This module is part of ntfs-3g library, but may also be
|
||||||
* integrated in tools running over Linux or Windows
|
* integrated in tools running over Linux or Windows
|
||||||
*
|
*
|
||||||
* Copyright (c) 2007-2010 Jean-Pierre Andre
|
* Copyright (c) 2007-2012 Jean-Pierre Andre
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License as published
|
||||||
@ -136,6 +136,19 @@ static const char worldsidbytes[] = {
|
|||||||
0, 0, 0, 0 /* 1st level */
|
0, 0, 0, 0 /* 1st level */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SID for authenticated user (S-1-5-11)
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const char authsidbytes[] = {
|
||||||
|
1, /* revision */
|
||||||
|
1, /* auth count */
|
||||||
|
0, 0, 0, 0, 0, 5, /* base */
|
||||||
|
11, 0, 0, 0 /* 1st level */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SID *authsid = (const SID*)authsidbytes;
|
||||||
|
|
||||||
const SID *worldsid = (const SID*)worldsidbytes;
|
const SID *worldsid = (const SID*)worldsidbytes;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -235,6 +248,12 @@ static int is_world_sid(const SID * usid)
|
|||||||
&& (usid->identifier_authority.low_part == const_cpu_to_be32(5))
|
&& (usid->identifier_authority.low_part == const_cpu_to_be32(5))
|
||||||
&& (usid->sub_authority[0] == const_cpu_to_le32(32))
|
&& (usid->sub_authority[0] == const_cpu_to_le32(32))
|
||||||
&& (usid->sub_authority[1] == const_cpu_to_le32(545)))
|
&& (usid->sub_authority[1] == const_cpu_to_le32(545)))
|
||||||
|
|
||||||
|
/* check whether S-1-5-11 : authenticated user */
|
||||||
|
|| ((usid->sub_authority_count == 1)
|
||||||
|
&& (usid->identifier_authority.high_part == const_cpu_to_be16(0))
|
||||||
|
&& (usid->identifier_authority.low_part == const_cpu_to_be32(5))
|
||||||
|
&& (usid->sub_authority[0] == const_cpu_to_le32(11)))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,7 +642,7 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz)
|
|||||||
&& (offdacl+sizeof(ACL) < attrsz)))
|
&& (offdacl+sizeof(ACL) < attrsz)))
|
||||||
&& (!offsacl
|
&& (!offsacl
|
||||||
|| ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
|
|| ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
|
||||||
&& (offsacl+sizeof(ACL) < attrsz)))
|
&& (offsacl+sizeof(ACL) <= attrsz)))
|
||||||
&& !(phead->owner & const_cpu_to_le32(3))
|
&& !(phead->owner & const_cpu_to_le32(3))
|
||||||
&& !(phead->group & const_cpu_to_le32(3))
|
&& !(phead->group & const_cpu_to_le32(3))
|
||||||
&& !(phead->dacl & const_cpu_to_le32(3))
|
&& !(phead->dacl & const_cpu_to_le32(3))
|
||||||
@ -664,7 +683,8 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
||||||
const SID *usid, const SID *gsid, BOOL fordir)
|
const SID *usid, const SID *gsid, BOOL fordir,
|
||||||
|
le16 inherited)
|
||||||
{
|
{
|
||||||
unsigned int src;
|
unsigned int src;
|
||||||
unsigned int dst;
|
unsigned int dst;
|
||||||
@ -677,7 +697,9 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
|||||||
int gsidsz;
|
int gsidsz;
|
||||||
const ACCESS_ALLOWED_ACE *poldace;
|
const ACCESS_ALLOWED_ACE *poldace;
|
||||||
ACCESS_ALLOWED_ACE *pnewace;
|
ACCESS_ALLOWED_ACE *pnewace;
|
||||||
|
ACCESS_ALLOWED_ACE *pauthace;
|
||||||
|
|
||||||
|
pauthace = (ACCESS_ALLOWED_ACE*)NULL;
|
||||||
usidsz = ntfs_sid_size(usid);
|
usidsz = ntfs_sid_size(usid);
|
||||||
gsidsz = ntfs_sid_size(gsid);
|
gsidsz = ntfs_sid_size(gsid);
|
||||||
|
|
||||||
@ -694,25 +716,19 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
|||||||
for (nace = 0; nace < oldcnt; nace++) {
|
for (nace = 0; nace < oldcnt; nace++) {
|
||||||
poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src);
|
poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src);
|
||||||
acesz = le16_to_cpu(poldace->size);
|
acesz = le16_to_cpu(poldace->size);
|
||||||
/* inheritance for access */
|
src += acesz;
|
||||||
if (poldace->flags & selection) {
|
/*
|
||||||
|
* Inheritance for access, unless this is inheriting
|
||||||
|
* an inherited ACL to a directory.
|
||||||
|
*/
|
||||||
|
if ((poldace->flags & selection)
|
||||||
|
&& !(fordir && inherited)
|
||||||
|
&& !ntfs_same_sid(&poldace->sid, ownersid)
|
||||||
|
&& !ntfs_same_sid(&poldace->sid, groupsid)) {
|
||||||
pnewace = (ACCESS_ALLOWED_ACE*)
|
pnewace = (ACCESS_ALLOWED_ACE*)
|
||||||
((char*)newacl + dst);
|
((char*)newacl + dst);
|
||||||
memcpy(pnewace,poldace,acesz);
|
memcpy(pnewace,poldace,acesz);
|
||||||
/*
|
/* reencode GENERIC_ALL */
|
||||||
* Replace generic creator-owner and
|
|
||||||
* creator-group by owner and group
|
|
||||||
*/
|
|
||||||
if (ntfs_same_sid(&pnewace->sid, ownersid)) {
|
|
||||||
memcpy(&pnewace->sid, usid, usidsz);
|
|
||||||
acesz = usidsz + 8;
|
|
||||||
pnewace->size = cpu_to_le16(acesz);
|
|
||||||
}
|
|
||||||
if (ntfs_same_sid(&pnewace->sid, groupsid)) {
|
|
||||||
memcpy(&pnewace->sid, gsid, gsidsz);
|
|
||||||
acesz = gsidsz + 8;
|
|
||||||
pnewace->size = cpu_to_le16(acesz);
|
|
||||||
}
|
|
||||||
if (pnewace->mask & GENERIC_ALL) {
|
if (pnewace->mask & GENERIC_ALL) {
|
||||||
pnewace->mask &= ~GENERIC_ALL;
|
pnewace->mask &= ~GENERIC_ALL;
|
||||||
if (fordir)
|
if (fordir)
|
||||||
@ -730,17 +746,71 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
|||||||
| FILE_WRITE
|
| FILE_WRITE
|
||||||
| FILE_EXEC
|
| FILE_EXEC
|
||||||
| cpu_to_le32(0x40);
|
| cpu_to_le32(0x40);
|
||||||
|
}
|
||||||
|
/* reencode GENERIC_READ (+ EXECUTE) */
|
||||||
|
if (pnewace->mask & GENERIC_READ) {
|
||||||
|
if (fordir)
|
||||||
|
pnewace->mask |= OWNER_RIGHTS
|
||||||
|
| DIR_READ
|
||||||
|
| DIR_EXEC;
|
||||||
|
else
|
||||||
|
pnewace->mask |= OWNER_RIGHTS
|
||||||
|
| FILE_READ
|
||||||
|
| FILE_EXEC;
|
||||||
|
pnewace->mask &= ~(GENERIC_READ
|
||||||
|
| GENERIC_EXECUTE
|
||||||
|
| WRITE_DAC
|
||||||
|
| WRITE_OWNER
|
||||||
|
| DELETE | FILE_WRITE_EA
|
||||||
|
| FILE_WRITE_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
/* reencode GENERIC_WRITE */
|
||||||
|
if (pnewace->mask & GENERIC_WRITE) {
|
||||||
|
if (fordir)
|
||||||
|
pnewace->mask |= OWNER_RIGHTS
|
||||||
|
| DIR_WRITE;
|
||||||
|
else
|
||||||
|
pnewace->mask |= OWNER_RIGHTS
|
||||||
|
| FILE_WRITE;
|
||||||
|
pnewace->mask &= ~(GENERIC_WRITE
|
||||||
|
| WRITE_DAC
|
||||||
|
| WRITE_OWNER
|
||||||
|
| FILE_DELETE_CHILD);
|
||||||
}
|
}
|
||||||
/* remove inheritance flags */
|
/* remove inheritance flags */
|
||||||
pnewace->flags &= ~(OBJECT_INHERIT_ACE
|
pnewace->flags &= ~(OBJECT_INHERIT_ACE
|
||||||
| CONTAINER_INHERIT_ACE
|
| CONTAINER_INHERIT_ACE
|
||||||
| INHERIT_ONLY_ACE);
|
| INHERIT_ONLY_ACE);
|
||||||
dst += acesz;
|
/*
|
||||||
newcnt++;
|
* Group similar ACE for authenticated users
|
||||||
|
* (should probably be done for other SIDs)
|
||||||
|
*/
|
||||||
|
if (!fordir
|
||||||
|
&& (poldace->type == ACCESS_ALLOWED_ACE_TYPE)
|
||||||
|
&& ntfs_same_sid(&poldace->sid, authsid)) {
|
||||||
|
if (pauthace) {
|
||||||
|
pauthace->flags |= pnewace->flags;
|
||||||
|
pauthace->mask |= pnewace->mask;
|
||||||
|
} else {
|
||||||
|
pauthace = pnewace;
|
||||||
|
if (inherited)
|
||||||
|
pnewace->flags |= INHERITED_ACE;
|
||||||
|
dst += acesz;
|
||||||
|
newcnt++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (inherited)
|
||||||
|
pnewace->flags |= INHERITED_ACE;
|
||||||
|
dst += acesz;
|
||||||
|
newcnt++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* inheritance for further inheritance */
|
/*
|
||||||
if (fordir
|
* Inheritance for access, specific to
|
||||||
&& (poldace->flags
|
* creator-owner (and creator-group)
|
||||||
|
*/
|
||||||
|
if (fordir || !inherited
|
||||||
|
|| (poldace->flags
|
||||||
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
|
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
|
||||||
pnewace = (ACCESS_ALLOWED_ACE*)
|
pnewace = (ACCESS_ALLOWED_ACE*)
|
||||||
((char*)newacl + dst);
|
((char*)newacl + dst);
|
||||||
@ -748,19 +818,46 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
|||||||
/*
|
/*
|
||||||
* Replace generic creator-owner and
|
* Replace generic creator-owner and
|
||||||
* creator-group by owner and group
|
* creator-group by owner and group
|
||||||
|
* (but keep for further inheritance)
|
||||||
*/
|
*/
|
||||||
if (ntfs_same_sid(&pnewace->sid, ownersid)) {
|
if (ntfs_same_sid(&pnewace->sid, ownersid)) {
|
||||||
memcpy(&pnewace->sid, usid, usidsz);
|
memcpy(&pnewace->sid, usid, usidsz);
|
||||||
acesz = usidsz + 8;
|
pnewace->size = cpu_to_le16(usidsz + 8);
|
||||||
|
/* remove inheritance flags */
|
||||||
|
pnewace->flags &= ~(OBJECT_INHERIT_ACE
|
||||||
|
| CONTAINER_INHERIT_ACE
|
||||||
|
| INHERIT_ONLY_ACE);
|
||||||
|
if (inherited)
|
||||||
|
pnewace->flags |= INHERITED_ACE;
|
||||||
|
dst += usidsz + 8;
|
||||||
|
newcnt++;
|
||||||
}
|
}
|
||||||
if (ntfs_same_sid(&pnewace->sid, groupsid)) {
|
if (ntfs_same_sid(&pnewace->sid, groupsid)) {
|
||||||
memcpy(&pnewace->sid, gsid, gsidsz);
|
memcpy(&pnewace->sid, gsid, gsidsz);
|
||||||
acesz = gsidsz + 8;
|
pnewace->size = cpu_to_le16(gsidsz + 8);
|
||||||
|
/* remove inheritance flags */
|
||||||
|
pnewace->flags &= ~(OBJECT_INHERIT_ACE
|
||||||
|
| CONTAINER_INHERIT_ACE
|
||||||
|
| INHERIT_ONLY_ACE);
|
||||||
|
if (inherited)
|
||||||
|
pnewace->flags |= INHERITED_ACE;
|
||||||
|
dst += gsidsz + 8;
|
||||||
|
newcnt++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* inheritance for further inheritance */
|
||||||
|
if (fordir
|
||||||
|
&& (poldace->flags
|
||||||
|
& (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
|
||||||
|
pnewace = (ACCESS_ALLOWED_ACE*)
|
||||||
|
((char*)newacl + dst);
|
||||||
|
memcpy(pnewace,poldace,acesz);
|
||||||
|
if (inherited)
|
||||||
|
pnewace->flags |= INHERITED_ACE;
|
||||||
dst += acesz;
|
dst += acesz;
|
||||||
newcnt++;
|
newcnt++;
|
||||||
}
|
}
|
||||||
src += acesz;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Adjust header if something was inherited
|
* Adjust header if something was inherited
|
||||||
@ -1080,7 +1177,7 @@ struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
|
|||||||
else
|
else
|
||||||
newsize = sizeof(struct POSIX_SECURITY)
|
newsize = sizeof(struct POSIX_SECURITY)
|
||||||
+ (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE);
|
+ (oldpxdesc->defcnt + count)*sizeof(struct POSIX_ACE);
|
||||||
newpxdesc = (struct POSIX_SECURITY*)ntfs_malloc(newsize);
|
newpxdesc = (struct POSIX_SECURITY*)malloc(newsize);
|
||||||
if (newpxdesc) {
|
if (newpxdesc) {
|
||||||
if (deflt) {
|
if (deflt) {
|
||||||
offset = oldpxdesc->acccnt;
|
offset = oldpxdesc->acccnt;
|
||||||
@ -1145,7 +1242,7 @@ struct POSIX_SECURITY *ntfs_build_inherited_posix(
|
|||||||
count = pxdesc->defcnt + 3;
|
count = pxdesc->defcnt + 3;
|
||||||
} else
|
} else
|
||||||
count = 3;
|
count = 3;
|
||||||
pydesc = (struct POSIX_SECURITY*)ntfs_malloc(
|
pydesc = (struct POSIX_SECURITY*)malloc(
|
||||||
sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE));
|
sizeof(struct POSIX_SECURITY) + count*sizeof(struct POSIX_ACE));
|
||||||
if (pydesc) {
|
if (pydesc) {
|
||||||
/*
|
/*
|
||||||
@ -1328,7 +1425,7 @@ struct POSIX_SECURITY *ntfs_merge_descr_posix(const struct POSIX_SECURITY *first
|
|||||||
size = sizeof(struct POSIX_SECURITY)
|
size = sizeof(struct POSIX_SECURITY)
|
||||||
+ (first->acccnt + first->defcnt
|
+ (first->acccnt + first->defcnt
|
||||||
+ second->acccnt + second->defcnt)*sizeof(struct POSIX_ACE);
|
+ second->acccnt + second->defcnt)*sizeof(struct POSIX_ACE);
|
||||||
pxdesc = (struct POSIX_SECURITY*)ntfs_malloc(size);
|
pxdesc = (struct POSIX_SECURITY*)malloc(size);
|
||||||
if (pxdesc) {
|
if (pxdesc) {
|
||||||
/*
|
/*
|
||||||
* merge access ACEs
|
* merge access ACEs
|
||||||
@ -3059,6 +3156,7 @@ static int build_owngrp_permissions(const char *securattr,
|
|||||||
int nace;
|
int nace;
|
||||||
le32 special;
|
le32 special;
|
||||||
BOOL grppresent;
|
BOOL grppresent;
|
||||||
|
BOOL ownpresent;
|
||||||
le32 allowown, allowgrp, allowall;
|
le32 allowown, allowgrp, allowall;
|
||||||
le32 denyown, denygrp, denyall;
|
le32 denyown, denygrp, denyall;
|
||||||
|
|
||||||
@ -3068,21 +3166,26 @@ static int build_owngrp_permissions(const char *securattr,
|
|||||||
special = const_cpu_to_le32(0);
|
special = const_cpu_to_le32(0);
|
||||||
allowown = allowgrp = allowall = const_cpu_to_le32(0);
|
allowown = allowgrp = allowall = const_cpu_to_le32(0);
|
||||||
denyown = denygrp = denyall = const_cpu_to_le32(0);
|
denyown = denygrp = denyall = const_cpu_to_le32(0);
|
||||||
|
ownpresent = FALSE;
|
||||||
grppresent = FALSE;
|
grppresent = FALSE;
|
||||||
if (offdacl) {
|
if (offdacl) {
|
||||||
acecnt = le16_to_cpu(pacl->ace_count);
|
acecnt = le16_to_cpu(pacl->ace_count);
|
||||||
offace = offdacl + sizeof(ACL);
|
offace = offdacl + sizeof(ACL);
|
||||||
} else
|
} else {
|
||||||
acecnt = 0;
|
acecnt = 0;
|
||||||
|
offace = 0;
|
||||||
|
}
|
||||||
for (nace = 0; nace < acecnt; nace++) {
|
for (nace = 0; nace < acecnt; nace++) {
|
||||||
pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
|
pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
|
||||||
if (!(pace->flags & INHERIT_ONLY_ACE)) {
|
if (!(pace->flags & INHERIT_ONLY_ACE)) {
|
||||||
if ((ntfs_same_sid(usid, &pace->sid)
|
if ((ntfs_same_sid(usid, &pace->sid)
|
||||||
|| ntfs_same_sid(ownersid, &pace->sid))
|
|| ntfs_same_sid(ownersid, &pace->sid))
|
||||||
&& (pace->mask & WRITE_OWNER)) {
|
&& (pace->mask & WRITE_OWNER)) {
|
||||||
if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
|
if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
|
||||||
allowown |= pace->mask;
|
allowown |= pace->mask;
|
||||||
} else
|
ownpresent = TRUE;
|
||||||
|
}
|
||||||
|
} else
|
||||||
if (ntfs_same_sid(usid, &pace->sid)
|
if (ntfs_same_sid(usid, &pace->sid)
|
||||||
&& (!(pace->mask & WRITE_OWNER))) {
|
&& (!(pace->mask & WRITE_OWNER))) {
|
||||||
if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
|
if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
|
||||||
@ -3103,6 +3206,8 @@ static int build_owngrp_permissions(const char *securattr,
|
|||||||
}
|
}
|
||||||
offace += le16_to_cpu(pace->size);
|
offace += le16_to_cpu(pace->size);
|
||||||
}
|
}
|
||||||
|
if (!ownpresent)
|
||||||
|
allowown = allowall;
|
||||||
if (!grppresent)
|
if (!grppresent)
|
||||||
allowgrp = allowall;
|
allowgrp = allowall;
|
||||||
return (merge_permissions(isdir,
|
return (merge_permissions(isdir,
|
||||||
@ -3484,7 +3589,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
|
|||||||
* and 2 more for other
|
* and 2 more for other
|
||||||
*/
|
*/
|
||||||
alloccnt = acecnt + 6;
|
alloccnt = acecnt + 6;
|
||||||
pxdesc = (struct POSIX_SECURITY*)ntfs_malloc(
|
pxdesc = (struct POSIX_SECURITY*)malloc(
|
||||||
sizeof(struct POSIX_SECURITY)
|
sizeof(struct POSIX_SECURITY)
|
||||||
+ alloccnt*sizeof(struct POSIX_ACE));
|
+ alloccnt*sizeof(struct POSIX_ACE));
|
||||||
k = 0;
|
k = 0;
|
||||||
@ -3705,7 +3810,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
|
|||||||
pxace->perms |= POSIX_PERM_DENIAL;
|
pxace->perms |= POSIX_PERM_DENIAL;
|
||||||
else
|
else
|
||||||
if (pxace->tag == POSIX_ACL_OTHER)
|
if (pxace->tag == POSIX_ACL_OTHER)
|
||||||
pctx->permswrld = pxace->perms;
|
pctx->permswrld |= pxace->perms;
|
||||||
pctx->tagsset |= pxace->tag;
|
pctx->tagsset |= pxace->tag;
|
||||||
if (pace->flags & INHERIT_ONLY_ACE) {
|
if (pace->flags & INHERIT_ONLY_ACE) {
|
||||||
l--;
|
l--;
|
||||||
|
@ -185,7 +185,8 @@ char *ntfs_build_descr_posix(struct MAPPING* const mapping[],
|
|||||||
#endif /* POSIXACLS */
|
#endif /* POSIXACLS */
|
||||||
|
|
||||||
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
|
||||||
const SID *usid, const SID *gsid, BOOL fordir);
|
const SID *usid, const SID *gsid,
|
||||||
|
BOOL fordir, le16 inherited);
|
||||||
int ntfs_build_permissions(const char *securattr,
|
int ntfs_build_permissions(const char *securattr,
|
||||||
const SID *usid, const SID *gsid, BOOL isdir);
|
const SID *usid, const SID *gsid, BOOL isdir);
|
||||||
char *ntfs_build_descr(mode_t mode,
|
char *ntfs_build_descr(mode_t mode,
|
||||||
|
@ -1849,6 +1849,13 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
|
|||||||
ntfs_log_perror("Failed to enlarge attribute");
|
ntfs_log_perror("Failed to enlarge attribute");
|
||||||
goto errno_set;
|
goto errno_set;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* If we avoided updating the runlist, we must be sure
|
||||||
|
* to cancel the enlargement and put back the runlist to
|
||||||
|
* a clean state if we get into some error.
|
||||||
|
*/
|
||||||
|
if (NAttrDataAppending(na))
|
||||||
|
need_to.undo_data_size = 1;
|
||||||
#else
|
#else
|
||||||
if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
|
if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
|
||||||
ntfs_log_perror("Failed to enlarge attribute");
|
ntfs_log_perror("Failed to enlarge attribute");
|
||||||
@ -3732,8 +3739,8 @@ int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size)
|
|||||||
* EIO - I/O error occurred or damaged filesystem.
|
* EIO - I/O error occurred or damaged filesystem.
|
||||||
*/
|
*/
|
||||||
int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, u8 *val, u32 size,
|
const ntfschar *name, u8 name_len, const u8 *val,
|
||||||
ATTR_FLAGS data_flags)
|
u32 size, ATTR_FLAGS data_flags)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
u32 length;
|
u32 length;
|
||||||
@ -3864,7 +3871,7 @@ put_err_out:
|
|||||||
* EIO - I/O error occurred or damaged filesystem.
|
* EIO - I/O error occurred or damaged filesystem.
|
||||||
*/
|
*/
|
||||||
int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
|
const ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
|
||||||
ATTR_FLAGS flags)
|
ATTR_FLAGS flags)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
@ -4147,7 +4154,7 @@ int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx)
|
|||||||
* On success return 0. On error return -1 with errno set to the error code.
|
* On success return 0. On error return -1 with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
|
int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, u8 *val, s64 size)
|
ntfschar *name, u8 name_len, const u8 *val, s64 size)
|
||||||
{
|
{
|
||||||
u32 attr_rec_size;
|
u32 attr_rec_size;
|
||||||
int err, i, offset;
|
int err, i, offset;
|
||||||
@ -4342,8 +4349,8 @@ err_out:
|
|||||||
* Change an attribute flag
|
* Change an attribute flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
|
int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, const ntfschar *name,
|
||||||
ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
|
u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
int res;
|
int res;
|
||||||
@ -6232,10 +6239,18 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize,
|
|||||||
|
|
||||||
/* Prepare to mapping pairs update. */
|
/* Prepare to mapping pairs update. */
|
||||||
na->allocated_size = first_free_vcn << vol->cluster_size_bits;
|
na->allocated_size = first_free_vcn << vol->cluster_size_bits;
|
||||||
/* Write mapping pairs for new runlist. */
|
|
||||||
#if PARTIAL_RUNLIST_UPDATING
|
#if PARTIAL_RUNLIST_UPDATING
|
||||||
if (ntfs_attr_update_mapping_pairs_i(na, start_update, holes)) {
|
/*
|
||||||
|
* Write mapping pairs for new runlist, unless this is
|
||||||
|
* a temporary state before appending data.
|
||||||
|
* If the update is not done, we must be sure to do
|
||||||
|
* it later, and to get to a clean state even on errors.
|
||||||
|
*/
|
||||||
|
if ((holes != HOLES_DELAY)
|
||||||
|
&& ntfs_attr_update_mapping_pairs_i(na, start_update,
|
||||||
|
holes)) {
|
||||||
#else
|
#else
|
||||||
|
/* Write mapping pairs for new runlist. */
|
||||||
if (ntfs_attr_update_mapping_pairs(na, 0)) {
|
if (ntfs_attr_update_mapping_pairs(na, 0)) {
|
||||||
#endif
|
#endif
|
||||||
err = errno;
|
err = errno;
|
||||||
@ -6646,9 +6661,8 @@ exit:
|
|||||||
* Returns the amount of data written, negative if there was an error
|
* Returns the amount of data written, negative if there was an error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int ntfs_attr_data_write(ntfs_inode *ni,
|
int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name,
|
||||||
ntfschar *stream_name, int stream_name_len,
|
int stream_name_len, const char *buf, size_t size, off_t offset)
|
||||||
char *buf, size_t size, off_t offset)
|
|
||||||
{
|
{
|
||||||
ntfs_attr *na = NULL;
|
ntfs_attr *na = NULL;
|
||||||
int res, total = 0;
|
int res, total = 0;
|
||||||
@ -6680,7 +6694,7 @@ exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,
|
int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, const ntfschar *name,
|
||||||
u32 name_len)
|
u32 name_len)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
|
@ -320,17 +320,18 @@ int ntfs_attr_force_non_resident(ntfs_attr *na);
|
|||||||
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
|
extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
|
||||||
|
|
||||||
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, u8 *val, u32 size,
|
const ntfschar *name, u8 name_len, const u8 *val, u32 size,
|
||||||
ATTR_FLAGS flags);
|
ATTR_FLAGS flags);
|
||||||
extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
|
const ntfschar *name, u8 name_len, VCN lowest_vcn,
|
||||||
ATTR_FLAGS flags);
|
int dataruns_size, ATTR_FLAGS flags);
|
||||||
extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
|
extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
|
||||||
|
|
||||||
extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
|
extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, u8 *val, s64 size);
|
ntfschar *name, u8 name_len, const u8 *val, s64 size);
|
||||||
extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
|
extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
|
||||||
ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask);
|
const ntfschar *name, u8 name_len, ATTR_FLAGS flags,
|
||||||
|
ATTR_FLAGS mask);
|
||||||
extern int ntfs_attr_rm(ntfs_attr *na);
|
extern int ntfs_attr_rm(ntfs_attr *na);
|
||||||
|
|
||||||
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
|
extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
|
||||||
@ -379,7 +380,7 @@ extern s64 ntfs_get_attribute_value(const ntfs_volume *vol,
|
|||||||
extern void ntfs_attr_name_free(char **name);
|
extern void ntfs_attr_name_free(char **name);
|
||||||
extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
|
extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
|
||||||
extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
|
extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
|
||||||
ntfschar *name, u32 name_len);
|
const ntfschar *name, u32 name_len);
|
||||||
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
|
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
|
||||||
ntfschar *name, u32 name_len);
|
ntfschar *name, u32 name_len);
|
||||||
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
|
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
|
||||||
@ -388,7 +389,7 @@ extern int ntfs_attr_data_read(ntfs_inode *ni,
|
|||||||
char *buf, size_t size, off_t offset);
|
char *buf, size_t size, off_t offset);
|
||||||
extern int ntfs_attr_data_write(ntfs_inode *ni,
|
extern int ntfs_attr_data_write(ntfs_inode *ni,
|
||||||
ntfschar *stream_name, int stream_name_len,
|
ntfschar *stream_name, int stream_name_len,
|
||||||
char *buf, size_t size, off_t offset);
|
const char *buf, size_t size, off_t offset);
|
||||||
|
|
||||||
#endif /* defined _NTFS_ATTRIB_H */
|
#endif /* defined _NTFS_ATTRIB_H */
|
||||||
|
|
||||||
|
@ -215,8 +215,8 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
|
|||||||
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn);
|
vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn);
|
||||||
ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn);
|
ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn);
|
||||||
ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn);
|
ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn);
|
||||||
if (vol->mft_lcn > vol->nr_clusters ||
|
if ((vol->mft_lcn < 0 || vol->mft_lcn > vol->nr_clusters) ||
|
||||||
vol->mftmirr_lcn > vol->nr_clusters) {
|
(vol->mftmirr_lcn < 0 || vol->mftmirr_lcn > vol->nr_clusters)) {
|
||||||
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
|
ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is "
|
||||||
"greater than the number of clusters (%lld).\n",
|
"greater than the number of clusters (%lld).\n",
|
||||||
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn,
|
(long long)vol->mft_lcn, (long long)vol->mftmirr_lcn,
|
||||||
|
@ -280,7 +280,7 @@ struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
|
|||||||
cache->oldest_entry = current->previous;
|
cache->oldest_entry = current->previous;
|
||||||
if (item->varsize) {
|
if (item->varsize) {
|
||||||
if (current->varsize)
|
if (current->varsize)
|
||||||
current->variable = MEM2_realloc(
|
current->variable = realloc(
|
||||||
current->variable,
|
current->variable,
|
||||||
item->varsize);
|
item->varsize);
|
||||||
else
|
else
|
||||||
|
@ -31,6 +31,12 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <errno.h> /* ENODATA */
|
||||||
|
|
||||||
|
#ifndef ENODATA
|
||||||
|
#define ENODATA ENOENT
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PATH_MAX
|
#ifndef PATH_MAX
|
||||||
#define PATH_MAX 4096
|
#define PATH_MAX 4096
|
||||||
#endif
|
#endif
|
||||||
|
@ -107,8 +107,8 @@
|
|||||||
/* Define to 1 if you have the <machine/endian.h> header file. */
|
/* Define to 1 if you have the <machine/endian.h> header file. */
|
||||||
#define HAVE_MACHINE_ENDIAN_H 1
|
#define HAVE_MACHINE_ENDIAN_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <math.h> header file. */
|
/* Define to 1 if you have the <malloc.h> header file. */
|
||||||
#define HAVE_MATH_H 1
|
#define HAVE_MALLOC_H 1
|
||||||
|
|
||||||
/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
|
/* Define to 1 if mbrtowc and mbstate_t are properly declared. */
|
||||||
#define HAVE_MBRTOWC 1
|
#define HAVE_MBRTOWC 1
|
||||||
@ -116,6 +116,9 @@
|
|||||||
/* Define to 1 if you have the `mbsinit' function. */
|
/* Define to 1 if you have the `mbsinit' function. */
|
||||||
#define HAVE_MBSINIT 1
|
#define HAVE_MBSINIT 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `memcpy' function. */
|
||||||
|
#define HAVE_MEMCPY 1
|
||||||
|
|
||||||
/* Define to 1 if you have the `memmove' function. */
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
#define HAVE_MEMMOVE 1
|
#define HAVE_MEMMOVE 1
|
||||||
|
|
||||||
@ -131,6 +134,9 @@
|
|||||||
/* Define to 1 if you have the <pwd.h> header file. */
|
/* Define to 1 if you have the <pwd.h> header file. */
|
||||||
#define HAVE_PWD_H 1
|
#define HAVE_PWD_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `random' function. */
|
||||||
|
#undef HAVE_RANDOM
|
||||||
|
|
||||||
/* Define to 1 if you have the `realpath' function. */
|
/* Define to 1 if you have the `realpath' function. */
|
||||||
#undef HAVE_REALPATH
|
#undef HAVE_REALPATH
|
||||||
|
|
||||||
@ -143,9 +149,12 @@
|
|||||||
/* Define to 1 if you have the `setxattr' function. */
|
/* Define to 1 if you have the `setxattr' function. */
|
||||||
#undef HAVE_SETXATTR
|
#undef HAVE_SETXATTR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `snprintf' function. */
|
||||||
|
#define HAVE_SNPRINTF 1
|
||||||
|
|
||||||
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
/* Define to 1 if `stat' has the bug that it succeeds when given the
|
||||||
zero-length file name argument. */
|
zero-length file name argument. */
|
||||||
#define HAVE_STAT_EMPTY_STRING_BUG 1
|
#undef HAVE_STAT_EMPTY_STRING_BUG
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||||
#define HAVE_STDARG_H 1
|
#define HAVE_STDARG_H 1
|
||||||
@ -312,13 +321,13 @@
|
|||||||
#define PACKAGE_NAME "ntfs-3g"
|
#define PACKAGE_NAME "ntfs-3g"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* Define to the full name and version of this package. */
|
||||||
#define PACKAGE_STRING "ntfs-3g 2012.1.15"
|
#define PACKAGE_STRING "ntfs-3g 2013.1.13"
|
||||||
|
|
||||||
/* Define to the one symbol short name of this package. */
|
/* Define to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "ntfs-3g"
|
#define PACKAGE_TARNAME "ntfs-3g"
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "2012.1.15"
|
#define PACKAGE_VERSION "2013.1.13"
|
||||||
|
|
||||||
/* POSIX ACL support */
|
/* POSIX ACL support */
|
||||||
#undef POSIXACLS
|
#undef POSIXACLS
|
||||||
@ -326,29 +335,8 @@
|
|||||||
/* Define to 1 if you have the ANSI C header files. */
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
#define STDC_HEADERS 1
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
/* Enable extensions on AIX 3, Interix. */
|
|
||||||
#ifndef _ALL_SOURCE
|
|
||||||
# define _ALL_SOURCE 1
|
|
||||||
#endif
|
|
||||||
/* Enable GNU extensions on systems that have them. */
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE 1
|
|
||||||
#endif
|
|
||||||
/* Enable threading extensions on Solaris. */
|
|
||||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
|
||||||
# define _POSIX_PTHREAD_SEMANTICS 1
|
|
||||||
#endif
|
|
||||||
/* Enable extensions on HP NonStop. */
|
|
||||||
#ifndef _TANDEM_SOURCE
|
|
||||||
# define _TANDEM_SOURCE 1
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on Solaris. */
|
|
||||||
#ifndef __EXTENSIONS__
|
|
||||||
# define __EXTENSIONS__ 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "2012.1.15"
|
#define VERSION "2013.1.13"
|
||||||
|
|
||||||
/* Define to 1 if this is a Windows OS */
|
/* Define to 1 if this is a Windows OS */
|
||||||
#undef WINDOWS
|
#undef WINDOWS
|
||||||
@ -392,3 +380,6 @@
|
|||||||
|
|
||||||
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
/* Define to `unsigned int' if <sys/types.h> does not define. */
|
||||||
#undef size_t
|
#undef size_t
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <math.h> header file. */
|
||||||
|
#define HAVE_MATH_H 1
|
||||||
|
@ -867,6 +867,87 @@ typedef enum {
|
|||||||
INDEX_TYPE_ALLOCATION, /* index allocation */
|
INDEX_TYPE_ALLOCATION, /* index allocation */
|
||||||
} INDEX_TYPE;
|
} INDEX_TYPE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode Interix file types
|
||||||
|
*
|
||||||
|
* Non-Interix types are returned as plain files, because a
|
||||||
|
* Windows user may force patterns very similar to Interix,
|
||||||
|
* and most metadata files have such similar patters.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u32 ntfs_interix_types(ntfs_inode *ni)
|
||||||
|
{
|
||||||
|
ntfs_attr *na;
|
||||||
|
u32 dt_type;
|
||||||
|
le64 magic;
|
||||||
|
|
||||||
|
dt_type = NTFS_DT_UNKNOWN;
|
||||||
|
na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
|
||||||
|
if (na) {
|
||||||
|
/* Unrecognized patterns (eg HID + SYST) are plain files */
|
||||||
|
dt_type = NTFS_DT_REG;
|
||||||
|
if (na->data_size <= 1) {
|
||||||
|
if (!(ni->flags & FILE_ATTR_HIDDEN))
|
||||||
|
dt_type = (na->data_size ?
|
||||||
|
NTFS_DT_SOCK : NTFS_DT_FIFO);
|
||||||
|
} else {
|
||||||
|
if ((na->data_size >= (s64)sizeof(magic))
|
||||||
|
&& (ntfs_attr_pread(na, 0, sizeof(magic), &magic)
|
||||||
|
== sizeof(magic))) {
|
||||||
|
if (magic == INTX_SYMBOLIC_LINK)
|
||||||
|
dt_type = NTFS_DT_LNK;
|
||||||
|
else if (magic == INTX_BLOCK_DEVICE)
|
||||||
|
dt_type = NTFS_DT_BLK;
|
||||||
|
else if (magic == INTX_CHARACTER_DEVICE)
|
||||||
|
dt_type = NTFS_DT_CHR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ntfs_attr_close(na);
|
||||||
|
}
|
||||||
|
return (dt_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode file types
|
||||||
|
*
|
||||||
|
* Better only use for Interix types and junctions,
|
||||||
|
* unneeded complexity when used for plain files or directories
|
||||||
|
*
|
||||||
|
* Error cases are logged and returned as unknown.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref,
|
||||||
|
FILE_ATTR_FLAGS attributes)
|
||||||
|
{
|
||||||
|
ntfs_inode *ni;
|
||||||
|
u32 dt_type;
|
||||||
|
|
||||||
|
dt_type = NTFS_DT_UNKNOWN;
|
||||||
|
ni = ntfs_inode_open(dir_ni->vol, mref);
|
||||||
|
if (ni) {
|
||||||
|
if ((attributes & FILE_ATTR_REPARSE_POINT)
|
||||||
|
&& ntfs_possible_symlink(ni))
|
||||||
|
dt_type = NTFS_DT_LNK;
|
||||||
|
else
|
||||||
|
if ((attributes & FILE_ATTR_SYSTEM)
|
||||||
|
&& !(attributes & FILE_ATTR_I30_INDEX_PRESENT))
|
||||||
|
dt_type = ntfs_interix_types(ni);
|
||||||
|
else
|
||||||
|
dt_type = (attributes
|
||||||
|
& FILE_ATTR_I30_INDEX_PRESENT
|
||||||
|
? NTFS_DT_DIR : NTFS_DT_REG);
|
||||||
|
if (ntfs_inode_close(ni)) {
|
||||||
|
/* anything special worth doing ? */
|
||||||
|
ntfs_log_error("Failed to close inode %lld\n",
|
||||||
|
(long long)MREF(mref));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dt_type == NTFS_DT_UNKNOWN)
|
||||||
|
ntfs_log_error("Could not decode the type of inode %lld\n",
|
||||||
|
(long long)MREF(mref));
|
||||||
|
return (dt_type);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ntfs_filldir - ntfs specific filldir method
|
* ntfs_filldir - ntfs specific filldir method
|
||||||
* @dir_ni: ntfs inode of current directory
|
* @dir_ni: ntfs inode of current directory
|
||||||
@ -901,19 +982,23 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
|
|||||||
dir_ni->vol->mft_record_size;
|
dir_ni->vol->mft_record_size;
|
||||||
else /* if (index_type == INDEX_TYPE_ROOT) */
|
else /* if (index_type == INDEX_TYPE_ROOT) */
|
||||||
*pos = (u8*)ie - (u8*)iu.ir;
|
*pos = (u8*)ie - (u8*)iu.ir;
|
||||||
|
mref = le64_to_cpu(ie->indexed_file);
|
||||||
|
metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user);
|
||||||
/* Skip root directory self reference entry. */
|
/* Skip root directory self reference entry. */
|
||||||
if (MREF_LE(ie->indexed_file) == FILE_root)
|
if (MREF_LE(ie->indexed_file) == FILE_root)
|
||||||
return 0;
|
return 0;
|
||||||
if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT)
|
if ((ie->key.file_name.file_attributes
|
||||||
|
& (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM))
|
||||||
|
&& !metadata)
|
||||||
|
dt_type = ntfs_dir_entry_type(dir_ni, mref,
|
||||||
|
ie->key.file_name.file_attributes);
|
||||||
|
else if (ie->key.file_name.file_attributes
|
||||||
|
& FILE_ATTR_I30_INDEX_PRESENT)
|
||||||
dt_type = NTFS_DT_DIR;
|
dt_type = NTFS_DT_DIR;
|
||||||
else if (fn->file_attributes & FILE_ATTR_SYSTEM)
|
|
||||||
dt_type = NTFS_DT_UNKNOWN;
|
|
||||||
else
|
else
|
||||||
dt_type = NTFS_DT_REG;
|
dt_type = NTFS_DT_REG;
|
||||||
|
|
||||||
/* return metadata files and hidden files if requested */
|
/* return metadata files and hidden files if requested */
|
||||||
mref = le64_to_cpu(ie->indexed_file);
|
|
||||||
metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user);
|
|
||||||
if ((!metadata && (NVolShowHidFiles(dir_ni->vol)
|
if ((!metadata && (NVolShowHidFiles(dir_ni->vol)
|
||||||
|| !(fn->file_attributes & FILE_ATTR_HIDDEN)))
|
|| !(fn->file_attributes & FILE_ATTR_HIDDEN)))
|
||||||
|| (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
|
|| (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
|
||||||
@ -1397,8 +1482,8 @@ err_out:
|
|||||||
* on error with errno set to the error code.
|
* on error with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, mode_t type, dev_t dev,
|
const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
|
||||||
ntfschar *target, int target_len)
|
const ntfschar *target, int target_len)
|
||||||
{
|
{
|
||||||
ntfs_inode *ni;
|
ntfs_inode *ni;
|
||||||
int rollback_data = 0, rollback_sd = 0;
|
int rollback_data = 0, rollback_sd = 0;
|
||||||
@ -1667,7 +1752,7 @@ err_out:
|
|||||||
* Some wrappers around __ntfs_create() ...
|
* Some wrappers around __ntfs_create() ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name,
|
ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name,
|
||||||
u8 name_len, mode_t type)
|
u8 name_len, mode_t type)
|
||||||
{
|
{
|
||||||
if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
|
if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
|
||||||
@ -1679,7 +1764,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
|
ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, mode_t type, dev_t dev)
|
const ntfschar *name, u8 name_len, mode_t type, dev_t dev)
|
||||||
{
|
{
|
||||||
if (type != S_IFCHR && type != S_IFBLK) {
|
if (type != S_IFCHR && type != S_IFBLK) {
|
||||||
ntfs_log_error("Invalid arguments.\n");
|
ntfs_log_error("Invalid arguments.\n");
|
||||||
@ -1689,7 +1774,8 @@ ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
|
ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, ntfschar *target, int target_len)
|
const ntfschar *name, u8 name_len, const ntfschar *target,
|
||||||
|
int target_len)
|
||||||
{
|
{
|
||||||
if (!target || !target_len) {
|
if (!target || !target_len) {
|
||||||
ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
|
ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
|
||||||
@ -1764,7 +1850,8 @@ no_hardlink:
|
|||||||
* Return 0 on success or -1 on error with errno set to the error code.
|
* Return 0 on success or -1 on error with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
int ntfs_delete(ntfs_volume *vol, const char *pathname,
|
int ntfs_delete(ntfs_volume *vol, const char *pathname,
|
||||||
ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
|
ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
||||||
|
u8 name_len)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *actx = NULL;
|
ntfs_attr_search_ctx *actx = NULL;
|
||||||
FILE_NAME_ATTR *fn = NULL;
|
FILE_NAME_ATTR *fn = NULL;
|
||||||
@ -1878,8 +1965,18 @@ search:
|
|||||||
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
|
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
if (ntfs_attr_record_rm(actx))
|
/*
|
||||||
goto err_out;
|
* Keep the last name in place, this is useful for undeletion
|
||||||
|
* (Windows also does so), however delete the name if it were
|
||||||
|
* in an extent, to avoid leaving an attribute list.
|
||||||
|
*/
|
||||||
|
if ((ni->mrec->link_count == cpu_to_le16(1)) && !actx->base_ntfs_ino) {
|
||||||
|
/* make sure to not loop to another search */
|
||||||
|
looking_for_dos_name = FALSE;
|
||||||
|
} else {
|
||||||
|
if (ntfs_attr_record_rm(actx))
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
|
||||||
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
|
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
|
||||||
ni->mrec->link_count) - 1);
|
ni->mrec->link_count) - 1);
|
||||||
@ -2002,6 +2099,7 @@ search:
|
|||||||
"Leaving inconsistent metadata.\n");
|
"Leaving inconsistent metadata.\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
debug_double_inode(ni->mft_no,0);
|
||||||
if (ntfs_mft_record_free(ni->vol, ni)) {
|
if (ntfs_mft_record_free(ni->vol, ni)) {
|
||||||
err = errno;
|
err = errno;
|
||||||
ntfs_log_error("Failed to free base MFT record. "
|
ntfs_log_error("Failed to free base MFT record. "
|
||||||
@ -2044,7 +2142,7 @@ err_out:
|
|||||||
*
|
*
|
||||||
* Return 0 on success or -1 on error with errno set to the error code.
|
* Return 0 on success or -1 on error with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
|
static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
||||||
u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
|
u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
|
||||||
{
|
{
|
||||||
FILE_NAME_ATTR *fn = NULL;
|
FILE_NAME_ATTR *fn = NULL;
|
||||||
@ -2064,6 +2162,15 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
|
|||||||
err = EOPNOTSUPP;
|
err = EOPNOTSUPP;
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
if (NVolHideDotFiles(dir_ni->vol)) {
|
||||||
|
/* Set hidden flag according to the latest name */
|
||||||
|
if ((name_len > 1)
|
||||||
|
&& (name[0] == const_cpu_to_le16('.'))
|
||||||
|
&& (name[1] != const_cpu_to_le16('.')))
|
||||||
|
ni->flags |= FILE_ATTR_HIDDEN;
|
||||||
|
else
|
||||||
|
ni->flags &= ~FILE_ATTR_HIDDEN;
|
||||||
|
}
|
||||||
|
|
||||||
/* Create FILE_NAME attribute. */
|
/* Create FILE_NAME attribute. */
|
||||||
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
|
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
|
||||||
@ -2121,7 +2228,8 @@ err_out:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
|
int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
||||||
|
u8 name_len)
|
||||||
{
|
{
|
||||||
return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
|
return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
|
||||||
}
|
}
|
||||||
@ -2172,6 +2280,8 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
|
|||||||
/*
|
/*
|
||||||
* Get a DOS name for a file in designated directory
|
* Get a DOS name for a file in designated directory
|
||||||
*
|
*
|
||||||
|
* Not allowed if there are several non-dos names (EMLINK)
|
||||||
|
*
|
||||||
* Returns size if found
|
* Returns size if found
|
||||||
* 0 if not found
|
* 0 if not found
|
||||||
* -1 if there was an error (described by errno)
|
* -1 if there was an error (described by errno)
|
||||||
@ -2180,6 +2290,7 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
|
|||||||
static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
||||||
{
|
{
|
||||||
size_t outsize = 0;
|
size_t outsize = 0;
|
||||||
|
int namecount = 0;
|
||||||
FILE_NAME_ATTR *fn;
|
FILE_NAME_ATTR *fn;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
|
|
||||||
@ -2194,6 +2305,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
|||||||
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
|
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
|
||||||
le16_to_cpu(ctx->attr->value_offset));
|
le16_to_cpu(ctx->attr->value_offset));
|
||||||
|
|
||||||
|
if (fn->file_name_type != FILE_NAME_DOS)
|
||||||
|
namecount++;
|
||||||
if ((fn->file_name_type & FILE_NAME_DOS)
|
if ((fn->file_name_type & FILE_NAME_DOS)
|
||||||
&& (MREF_LE(fn->parent_directory) == dnum)) {
|
&& (MREF_LE(fn->parent_directory) == dnum)) {
|
||||||
/*
|
/*
|
||||||
@ -2208,6 +2321,10 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
|
if ((outsize > 0) && (namecount > 1)) {
|
||||||
|
outsize = -1;
|
||||||
|
errno = EMLINK; /* this error implies there is a dos name */
|
||||||
|
}
|
||||||
return (outsize);
|
return (outsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2215,6 +2332,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
|||||||
/*
|
/*
|
||||||
* Get a long name for a file in designated directory
|
* Get a long name for a file in designated directory
|
||||||
*
|
*
|
||||||
|
* Not allowed if there are several non-dos names (EMLINK)
|
||||||
|
*
|
||||||
* Returns size if found
|
* Returns size if found
|
||||||
* 0 if not found
|
* 0 if not found
|
||||||
* -1 if there was an error (described by errno)
|
* -1 if there was an error (described by errno)
|
||||||
@ -2223,6 +2342,7 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
|
|||||||
static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
|
static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
|
||||||
{
|
{
|
||||||
size_t outsize = 0;
|
size_t outsize = 0;
|
||||||
|
int namecount = 0;
|
||||||
FILE_NAME_ATTR *fn;
|
FILE_NAME_ATTR *fn;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
|
|
||||||
@ -2238,6 +2358,8 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
|
|||||||
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
|
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
|
||||||
le16_to_cpu(ctx->attr->value_offset));
|
le16_to_cpu(ctx->attr->value_offset));
|
||||||
|
|
||||||
|
if (fn->file_name_type != FILE_NAME_DOS)
|
||||||
|
namecount++;
|
||||||
if ((fn->file_name_type & FILE_NAME_WIN32)
|
if ((fn->file_name_type & FILE_NAME_WIN32)
|
||||||
&& (MREF_LE(fn->parent_directory) == dnum)) {
|
&& (MREF_LE(fn->parent_directory) == dnum)) {
|
||||||
/*
|
/*
|
||||||
@ -2247,6 +2369,11 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
|
|||||||
outsize = fn->file_name_length;
|
outsize = fn->file_name_length;
|
||||||
memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
|
memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (namecount > 1) {
|
||||||
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
|
errno = EMLINK;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
/* if not found search for POSIX names */
|
/* if not found search for POSIX names */
|
||||||
if (!outsize) {
|
if (!outsize) {
|
||||||
@ -2324,7 +2451,7 @@ int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
|
static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
|
||||||
ntfschar *name, int len,
|
const ntfschar *name, int len,
|
||||||
FILE_NAME_TYPE_FLAGS nametype)
|
FILE_NAME_TYPE_FLAGS nametype)
|
||||||
{
|
{
|
||||||
ntfs_attr_search_ctx *actx;
|
ntfs_attr_search_ctx *actx;
|
||||||
@ -2398,9 +2525,9 @@ static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
||||||
ntfschar *shortname, int shortlen,
|
const ntfschar *shortname, int shortlen,
|
||||||
ntfschar *longname, int longlen,
|
const ntfschar *longname, int longlen,
|
||||||
ntfschar *deletename, int deletelen, BOOL existed)
|
const ntfschar *deletename, int deletelen, BOOL existed)
|
||||||
{
|
{
|
||||||
unsigned int linkcount;
|
unsigned int linkcount;
|
||||||
ntfs_volume *vol;
|
ntfs_volume *vol;
|
||||||
@ -2568,7 +2695,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||||||
res = -1;
|
res = -1;
|
||||||
} else {
|
} else {
|
||||||
res = -1;
|
res = -1;
|
||||||
errno = ENOENT;
|
if (!longlen)
|
||||||
|
errno = ENOENT;
|
||||||
}
|
}
|
||||||
free(shortname);
|
free(shortname);
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
@ -2644,7 +2772,8 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errno = ENOENT;
|
if (!longlen)
|
||||||
|
errno = ENOENT;
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
if (!deleted) {
|
if (!deleted) {
|
||||||
|
@ -68,17 +68,18 @@ extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name,
|
|||||||
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
||||||
const char *pathname);
|
const char *pathname);
|
||||||
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, mode_t type);
|
const ntfschar *name, u8 name_len, mode_t type);
|
||||||
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
|
extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, mode_t type, dev_t dev);
|
const ntfschar *name, u8 name_len, mode_t type, dev_t dev);
|
||||||
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
|
extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
|
||||||
ntfschar *name, u8 name_len, ntfschar *target, int target_len);
|
const ntfschar *name, u8 name_len, const ntfschar *target,
|
||||||
|
int target_len);
|
||||||
extern int ntfs_check_empty_dir(ntfs_inode *ni);
|
extern int ntfs_check_empty_dir(ntfs_inode *ni);
|
||||||
extern int ntfs_delete(ntfs_volume *vol, const char *path,
|
extern int ntfs_delete(ntfs_volume *vol, const char *path,
|
||||||
ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
|
ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
||||||
u8 name_len);
|
u8 name_len);
|
||||||
|
|
||||||
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
|
extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
||||||
u8 name_len);
|
u8 name_len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1279,7 +1279,7 @@ static int ntfs_ie_add_vcn(INDEX_ENTRY **ie)
|
|||||||
INDEX_ENTRY *p, *old = *ie;
|
INDEX_ENTRY *p, *old = *ie;
|
||||||
|
|
||||||
old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN));
|
old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN));
|
||||||
p = MEM2_realloc(old, le16_to_cpu(old->length));
|
p = realloc(old, le16_to_cpu(old->length));
|
||||||
if (!p)
|
if (!p)
|
||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
|
|
||||||
|
@ -2398,18 +2398,19 @@ typedef enum {
|
|||||||
IO_REPARSE_TAG_RESERVED_ONE = const_cpu_to_le32(0x00000001),
|
IO_REPARSE_TAG_RESERVED_ONE = const_cpu_to_le32(0x00000001),
|
||||||
IO_REPARSE_TAG_RESERVED_RANGE = const_cpu_to_le32(0x00000001),
|
IO_REPARSE_TAG_RESERVED_RANGE = const_cpu_to_le32(0x00000001),
|
||||||
|
|
||||||
IO_REPARSE_TAG_NSS = const_cpu_to_le32(0x68000005),
|
IO_REPARSE_TAG_CSV = const_cpu_to_le32(0x80000009),
|
||||||
IO_REPARSE_TAG_NSS_RECOVER = const_cpu_to_le32(0x68000006),
|
IO_REPARSE_TAG_DEDUP = const_cpu_to_le32(0x80000013),
|
||||||
IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x68000007),
|
IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x8000000A),
|
||||||
IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x68000008),
|
IO_REPARSE_TAG_DFSR = const_cpu_to_le32(0x80000012),
|
||||||
|
IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xC0000004),
|
||||||
|
IO_REPARSE_TAG_HSM2 = const_cpu_to_le32(0x80000006),
|
||||||
|
IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0xA0000003),
|
||||||
|
IO_REPARSE_TAG_NFS = const_cpu_to_le32(0x80000014),
|
||||||
|
IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x80000007),
|
||||||
|
IO_REPARSE_TAG_SYMLINK = const_cpu_to_le32(0xA000000C),
|
||||||
|
IO_REPARSE_TAG_WIM = const_cpu_to_le32(0x80000008),
|
||||||
|
|
||||||
IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0x88000003),
|
IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xf000ffff),
|
||||||
|
|
||||||
IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xa8000004),
|
|
||||||
|
|
||||||
IO_REPARSE_TAG_SYMBOLIC_LINK = const_cpu_to_le32(0xe8000000),
|
|
||||||
|
|
||||||
IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xe000ffff),
|
|
||||||
} PREDEFINED_REPARSE_TAGS;
|
} PREDEFINED_REPARSE_TAGS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,7 +356,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
|
|||||||
/* Reallocate memory if necessary. */
|
/* Reallocate memory if necessary. */
|
||||||
if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
|
if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
|
||||||
rlsize += 4096;
|
rlsize += 4096;
|
||||||
trl = MEM2_realloc(rl, rlsize);
|
trl = realloc(rl, rlsize);
|
||||||
if (!trl) {
|
if (!trl) {
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
ntfs_log_perror("realloc() failed");
|
ntfs_log_perror("realloc() failed");
|
||||||
|
@ -84,13 +84,21 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
|
|||||||
"position in $LogFile.\n");
|
"position in $LogFile.\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/* We only know how to handle version 1.1. */
|
/*
|
||||||
if (sle16_to_cpu(rp->major_ver) != 1 ||
|
* We only know how to handle version 1.1 and 2.0, though
|
||||||
sle16_to_cpu(rp->minor_ver) != 1) {
|
* version 2.0 is probably related to cached metadata in
|
||||||
|
* Windows 8, and we will refuse to mount.
|
||||||
|
* Nevertheless, do all the relevant checks before rejecting.
|
||||||
|
*/
|
||||||
|
if (((rp->major_ver != const_cpu_to_le16(1))
|
||||||
|
|| (rp->minor_ver != const_cpu_to_le16(1)))
|
||||||
|
&& ((rp->major_ver != const_cpu_to_le16(2))
|
||||||
|
|| (rp->minor_ver != const_cpu_to_le16(0)))) {
|
||||||
ntfs_log_error("$LogFile version %i.%i is not "
|
ntfs_log_error("$LogFile version %i.%i is not "
|
||||||
"supported. (This driver supports version "
|
"supported.\n (This driver supports version "
|
||||||
"1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver),
|
"1.1 and 2.0 only.)\n",
|
||||||
(int)sle16_to_cpu(rp->minor_ver));
|
(int)sle16_to_cpu(rp->major_ver),
|
||||||
|
(int)sle16_to_cpu(rp->minor_ver));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -28,12 +28,20 @@
|
|||||||
|
|
||||||
static inline void* ntfs_alloc (size_t size)
|
static inline void* ntfs_alloc (size_t size)
|
||||||
{
|
{
|
||||||
|
#ifdef __wii__
|
||||||
return MEM2_alloc(size);
|
return MEM2_alloc(size);
|
||||||
|
#else
|
||||||
|
return malloc(size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* ntfs_align (size_t size)
|
static inline void* ntfs_align (size_t size)
|
||||||
{
|
{
|
||||||
return MEM2_alloc(size);
|
#ifdef __wii__
|
||||||
|
return memalign(32, size);
|
||||||
|
#else
|
||||||
|
return malloc(size);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ntfs_free (void* mem)
|
static inline void ntfs_free (void* mem)
|
||||||
|
@ -34,21 +34,17 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "mem2.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ntfs_calloc
|
* ntfs_calloc
|
||||||
*
|
*
|
||||||
* Return a pointer to the allocated memory or NULL if the request fails.
|
* Return a pointer to the allocated memory or NULL if the request fails.
|
||||||
*/
|
*/
|
||||||
void *ntfs_calloc(size_t size)
|
void *ntfs_calloc(size_t size)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
p = MEM2_alloc(size);
|
p = calloc(1, size);
|
||||||
if(p)
|
|
||||||
memset(p, 0, size);
|
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
ntfs_log_perror("Failed to calloc %lld bytes", (long long)size);
|
ntfs_log_perror("Failed to calloc %lld bytes", (long long)size);
|
||||||
return p;
|
return p;
|
||||||
@ -57,8 +53,8 @@ void *ntfs_calloc(size_t size)
|
|||||||
void *ntfs_malloc(size_t size)
|
void *ntfs_malloc(size_t size)
|
||||||
{
|
{
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
p = MEM2_alloc(size);
|
p = malloc(size);
|
||||||
if (!p)
|
if (!p)
|
||||||
ntfs_log_perror("Failed to malloc %lld bytes", (long long)size);
|
ntfs_log_perror("Failed to malloc %lld bytes", (long long)size);
|
||||||
return p;
|
return p;
|
||||||
|
@ -81,9 +81,6 @@ void ntfsInit (void)
|
|||||||
#else
|
#else
|
||||||
ntfs_log_set_handler(ntfs_log_handler_null);
|
ntfs_log_set_handler(ntfs_log_handler_null);
|
||||||
#endif
|
#endif
|
||||||
// Set our current local
|
|
||||||
ntfs_set_locale();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -478,20 +475,20 @@ bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSe
|
|||||||
|
|
||||||
// Build the mount flags
|
// Build the mount flags
|
||||||
if (flags & NTFS_READ_ONLY)
|
if (flags & NTFS_READ_ONLY)
|
||||||
vd->flags |= MS_RDONLY;
|
vd->flags |= NTFS_MNT_RDONLY;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!(interface->features & FEATURE_MEDIUM_CANWRITE))
|
if (!(interface->features & FEATURE_MEDIUM_CANWRITE))
|
||||||
vd->flags |= MS_RDONLY;
|
vd->flags |= NTFS_MNT_RDONLY;
|
||||||
if ((interface->features & FEATURE_MEDIUM_CANREAD) && (interface->features & FEATURE_MEDIUM_CANWRITE))
|
if ((interface->features & FEATURE_MEDIUM_CANREAD) && (interface->features & FEATURE_MEDIUM_CANWRITE))
|
||||||
vd->flags |= MS_EXCLUSIVE;
|
vd->flags |= NTFS_MNT_EXCLUSIVE;
|
||||||
}
|
}
|
||||||
if (flags & NTFS_RECOVER)
|
if (flags & NTFS_RECOVER)
|
||||||
vd->flags |= MS_RECOVER;
|
vd->flags |= NTFS_MNT_RECOVER;
|
||||||
if (flags & NTFS_IGNORE_HIBERFILE)
|
if (flags & NTFS_IGNORE_HIBERFILE)
|
||||||
vd->flags |= MS_IGNORE_HIBERFILE;
|
vd->flags |= NTFS_MNT_IGNORE_HIBERFILE;
|
||||||
|
|
||||||
if (vd->flags & MS_RDONLY)
|
if (vd->flags & NTFS_MNT_RDONLY)
|
||||||
ntfs_log_debug("Mounting \"%s\" as read-only\n", name);
|
ntfs_log_debug("Mounting \"%s\" as read-only\n", name);
|
||||||
|
|
||||||
// Mount the device
|
// Mount the device
|
||||||
|
@ -670,7 +670,7 @@ cleanup:
|
|||||||
// Unlock
|
// Unlock
|
||||||
ntfsUnlock(vd);
|
ntfsUnlock(vd);
|
||||||
|
|
||||||
return 0;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfsSync (ntfs_vd *vd, ntfs_inode *ni)
|
int ntfsSync (ntfs_vd *vd, ntfs_inode *ni)
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
|
@ -44,12 +44,18 @@ enum {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* default option for compression */
|
/* default option for compression */
|
||||||
#define DEFAULT_COMPRESSION FALSE
|
#define DEFAULT_COMPRESSION 0
|
||||||
/* (log2 of) number of clusters in a compression block for new files */
|
/* (log2 of) number of clusters in a compression block for new files */
|
||||||
#define STANDARD_COMPRESSION_UNIT 4
|
#define STANDARD_COMPRESSION_UNIT 4
|
||||||
/* maximum cluster size for allowing compression for new files */
|
/* maximum cluster size for allowing compression for new files */
|
||||||
#define MAX_COMPRESSION_CLUSTER_SIZE 4096
|
#define MAX_COMPRESSION_CLUSTER_SIZE 4096
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parameters for default options
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DEFAULT_DMTIME 60 /* default 1mn for delay_mtime */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use of big write buffers
|
* Use of big write buffers
|
||||||
*
|
*
|
||||||
@ -109,7 +115,11 @@ enum {
|
|||||||
* of 6 is added in the mount report.
|
* of 6 is added in the mount report.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if defined(__sun) && defined(__SVR4)
|
||||||
|
#define HPERMSCONFIG 4 /* access control by kernel is broken on OpenIndiana */
|
||||||
|
#else
|
||||||
#define HPERMSCONFIG 1
|
#define HPERMSCONFIG 1
|
||||||
|
#endif
|
||||||
#if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28)
|
#if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28)
|
||||||
#define LPERMSCONFIG 5
|
#define LPERMSCONFIG 5
|
||||||
#else
|
#else
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* This module is part of ntfs-3g library
|
* 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
|
* 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
|
* modify it under the terms of the GNU General Public License as published
|
||||||
@ -46,8 +46,10 @@
|
|||||||
#include <sys/sysmacros.h>
|
#include <sys/sysmacros.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
#include "layout.h"
|
||||||
#include "attrib.h"
|
#include "attrib.h"
|
||||||
#include "inode.h"
|
#include "inode.h"
|
||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
@ -59,18 +61,6 @@
|
|||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
#include "reparse.h"
|
#include "reparse.h"
|
||||||
|
|
||||||
/* the definitions in layout.h are wrong, we use names defined in
|
|
||||||
http://msdn.microsoft.com/en-us/library/aa365740(VS.85).aspx
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define IO_REPARSE_TAG_DFS const_cpu_to_le32(0x8000000A)
|
|
||||||
#define IO_REPARSE_TAG_DFSR const_cpu_to_le32(0x80000012)
|
|
||||||
#define IO_REPARSE_TAG_HSM const_cpu_to_le32(0xC0000004)
|
|
||||||
#define IO_REPARSE_TAG_HSM2 const_cpu_to_le32(0x80000006)
|
|
||||||
#define IO_REPARSE_TAG_MOUNT_POINT const_cpu_to_le32(0xA0000003)
|
|
||||||
#define IO_REPARSE_TAG_SIS const_cpu_to_le32(0x80000007)
|
|
||||||
#define IO_REPARSE_TAG_SYMLINK const_cpu_to_le32(0xA000000C)
|
|
||||||
|
|
||||||
struct MOUNT_POINT_REPARSE_DATA { /* reparse data for junctions */
|
struct MOUNT_POINT_REPARSE_DATA { /* reparse data for junctions */
|
||||||
le16 subst_name_offset;
|
le16 subst_name_offset;
|
||||||
le16 subst_name_length;
|
le16 subst_name_length;
|
||||||
@ -235,6 +225,17 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path,
|
|||||||
ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
|
ni = ntfs_inode_open(vol, (MFT_REF)FILE_root);
|
||||||
if (ni) {
|
if (ni) {
|
||||||
start = 0;
|
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 {
|
do {
|
||||||
len = 0;
|
len = 0;
|
||||||
while (((start + len) < count)
|
while (((start + len) < count)
|
||||||
@ -252,9 +253,11 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path,
|
|||||||
}
|
}
|
||||||
} while (ni
|
} while (ni
|
||||||
&& (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
&& (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
|
||||||
|
&& !(ni->flags & FILE_ATTR_REPARSE_POINT)
|
||||||
&& (start < count));
|
&& (start < count));
|
||||||
if (ni
|
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 (ntfs_ucstombs(path, count, &target, 0) < 0) {
|
||||||
if (target) {
|
if (target) {
|
||||||
free(target);
|
free(target);
|
||||||
@ -288,12 +291,25 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count)
|
|||||||
int pos;
|
int pos;
|
||||||
int lth;
|
int lth;
|
||||||
BOOL ok;
|
BOOL ok;
|
||||||
|
BOOL morelinks;
|
||||||
int max = 32; /* safety */
|
int max = 32; /* safety */
|
||||||
|
|
||||||
pos = 0;
|
pos = 0;
|
||||||
ok = TRUE;
|
ok = TRUE;
|
||||||
|
morelinks = FALSE;
|
||||||
curni = ntfs_dir_parent_inode(ni);
|
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))
|
if ((count >= (pos + 2))
|
||||||
&& (path[pos] == const_cpu_to_le16('.'))
|
&& (path[pos] == const_cpu_to_le16('.'))
|
||||||
&& (path[pos+1] == const_cpu_to_le16('\\'))) {
|
&& (path[pos+1] == const_cpu_to_le16('\\'))) {
|
||||||
@ -331,12 +347,18 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count)
|
|||||||
if (!curni)
|
if (!curni)
|
||||||
ok = FALSE;
|
ok = FALSE;
|
||||||
else {
|
else {
|
||||||
|
if (curni->flags & FILE_ATTR_REPARSE_POINT)
|
||||||
|
morelinks = TRUE;
|
||||||
if (ok && ((pos + lth) < count)) {
|
if (ok && ((pos + lth) < count)) {
|
||||||
path[pos + lth] = const_cpu_to_le16('/');
|
path[pos + lth] = const_cpu_to_le16('/');
|
||||||
pos += lth + 1;
|
pos += lth + 1;
|
||||||
|
if (morelinks
|
||||||
|
&& ntfs_inode_close(curni))
|
||||||
|
ok = FALSE;
|
||||||
} else {
|
} else {
|
||||||
pos += lth;
|
pos += lth;
|
||||||
if ((ni->mrec->flags ^ curni->mrec->flags)
|
if (!morelinks
|
||||||
|
&& (ni->mrec->flags ^ curni->mrec->flags)
|
||||||
& MFT_RECORD_IS_DIRECTORY)
|
& MFT_RECORD_IS_DIRECTORY)
|
||||||
ok = FALSE;
|
ok = FALSE;
|
||||||
if (ntfs_inode_close(curni))
|
if (ntfs_inode_close(curni))
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* Copyright (c) 2004 Anton Altaparmakov
|
* Copyright (c) 2004 Anton Altaparmakov
|
||||||
* Copyright (c) 2005-2006 Szabolcs Szakacsits
|
* Copyright (c) 2005-2006 Szabolcs Szakacsits
|
||||||
* Copyright (c) 2006 Yura Pakhuchiy
|
* Copyright (c) 2006 Yura Pakhuchiy
|
||||||
* Copyright (c) 2007-2010 Jean-Pierre Andre
|
* Copyright (c) 2007-2012 Jean-Pierre Andre
|
||||||
*
|
*
|
||||||
* This program/include file is free software; you can redistribute it and/or
|
* 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
|
* modify it under the terms of the GNU General Public License as published
|
||||||
@ -52,6 +52,7 @@
|
|||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "layout.h"
|
#include "layout.h"
|
||||||
@ -1128,10 +1129,86 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid
|
|||||||
return (ingroup);
|
return (ingroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__sun) && defined (__SVR4)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check whether current thread owner is member of file group
|
* Check whether current thread owner is member of file group
|
||||||
|
* Solaris/OpenIndiana version
|
||||||
|
* Should not be called for user root, however the group may be root
|
||||||
*
|
*
|
||||||
|
* The group list is available in "/proc/$PID/cred"
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
|
||||||
|
{
|
||||||
|
typedef struct prcred {
|
||||||
|
uid_t pr_euid; /* effective user id */
|
||||||
|
uid_t pr_ruid; /* real user id */
|
||||||
|
uid_t pr_suid; /* saved user id (from exec) */
|
||||||
|
gid_t pr_egid; /* effective group id */
|
||||||
|
gid_t pr_rgid; /* real group id */
|
||||||
|
gid_t pr_sgid; /* saved group id (from exec) */
|
||||||
|
int pr_ngroups; /* number of supplementary groups */
|
||||||
|
gid_t pr_groups[1]; /* array of supplementary groups */
|
||||||
|
} prcred_t;
|
||||||
|
enum { readset = 16 };
|
||||||
|
|
||||||
|
prcred_t basecreds;
|
||||||
|
gid_t groups[readset];
|
||||||
|
char filename[64];
|
||||||
|
int fd;
|
||||||
|
int k;
|
||||||
|
int cnt;
|
||||||
|
gid_t *p;
|
||||||
|
BOOL ismember;
|
||||||
|
int got;
|
||||||
|
pid_t tid;
|
||||||
|
|
||||||
|
if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS))
|
||||||
|
ismember = staticgroupmember(scx, uid, gid);
|
||||||
|
else {
|
||||||
|
ismember = FALSE; /* default return */
|
||||||
|
tid = scx->tid;
|
||||||
|
sprintf(filename,"/proc/%u/cred",tid);
|
||||||
|
fd = open(filename,O_RDONLY);
|
||||||
|
if (fd >= 0) {
|
||||||
|
got = read(fd, &basecreds, sizeof(prcred_t));
|
||||||
|
if (got == sizeof(prcred_t)) {
|
||||||
|
if (basecreds.pr_egid == gid)
|
||||||
|
ismember = TRUE;
|
||||||
|
p = basecreds.pr_groups;
|
||||||
|
cnt = 1;
|
||||||
|
k = 0;
|
||||||
|
while (!ismember
|
||||||
|
&& (k < basecreds.pr_ngroups)
|
||||||
|
&& (cnt > 0)
|
||||||
|
&& (*p != gid)) {
|
||||||
|
k++;
|
||||||
|
cnt--;
|
||||||
|
p++;
|
||||||
|
if (cnt <= 0) {
|
||||||
|
got = read(fd, groups,
|
||||||
|
readset*sizeof(gid_t));
|
||||||
|
cnt = got/sizeof(gid_t);
|
||||||
|
p = groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((cnt > 0)
|
||||||
|
&& (k < basecreds.pr_ngroups))
|
||||||
|
ismember = TRUE;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (ismember);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else /* defined(__sun) && defined (__SVR4) */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether current thread owner is member of file group
|
||||||
|
* Linux version
|
||||||
* Should not be called for user root, however the group may be root
|
* Should not be called for user root, however the group may be root
|
||||||
*
|
*
|
||||||
* As indicated by Miklos Szeredi :
|
* As indicated by Miklos Szeredi :
|
||||||
@ -1234,6 +1311,8 @@ static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
|
|||||||
return (ismember);
|
return (ismember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* defined(__sun) && defined (__SVR4) */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Cacheing is done two-way :
|
* Cacheing is done two-way :
|
||||||
* - from uid, gid and perm to securid (CACHED_SECURID)
|
* - from uid, gid and perm to securid (CACHED_SECURID)
|
||||||
@ -1797,7 +1876,7 @@ static int access_check_posix(struct SECURITY_CONTEXT *scx,
|
|||||||
if (!scx->uid) {
|
if (!scx->uid) {
|
||||||
/* root access if owner or other execution */
|
/* root access if owner or other execution */
|
||||||
if (perms & 0101)
|
if (perms & 0101)
|
||||||
perms = 07777;
|
perms |= 01777;
|
||||||
else {
|
else {
|
||||||
/* root access if some group execution */
|
/* root access if some group execution */
|
||||||
groupperms = 0;
|
groupperms = 0;
|
||||||
@ -2213,7 +2292,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
|
|||||||
if (!scx->uid) {
|
if (!scx->uid) {
|
||||||
/* root access and execution */
|
/* root access and execution */
|
||||||
if (perm & 0111)
|
if (perm & 0111)
|
||||||
perm = 07777;
|
perm |= 01777;
|
||||||
else
|
else
|
||||||
perm = 0;
|
perm = 0;
|
||||||
} else
|
} else
|
||||||
@ -3316,6 +3395,56 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
|
|||||||
return (allow);
|
return (allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check whether user can create a file (or directory)
|
||||||
|
*
|
||||||
|
* Returns TRUE if access is allowed,
|
||||||
|
* Also returns the gid and dsetgid applicable to the created file
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ntfs_allowed_create(struct SECURITY_CONTEXT *scx,
|
||||||
|
ntfs_inode *dir_ni, gid_t *pgid, mode_t *pdsetgid)
|
||||||
|
{
|
||||||
|
int perm;
|
||||||
|
int res;
|
||||||
|
int allow;
|
||||||
|
struct stat stbuf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always allow for root.
|
||||||
|
* Also always allow if no mapping has been defined
|
||||||
|
*/
|
||||||
|
if (!scx->mapping[MAPUSERS])
|
||||||
|
perm = 0777;
|
||||||
|
else
|
||||||
|
perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC);
|
||||||
|
if (!scx->mapping[MAPUSERS]
|
||||||
|
|| !scx->uid) {
|
||||||
|
allow = 1;
|
||||||
|
} else {
|
||||||
|
perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC);
|
||||||
|
if (perm >= 0) {
|
||||||
|
res = EACCES;
|
||||||
|
allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0)
|
||||||
|
&& ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0);
|
||||||
|
if (!allow)
|
||||||
|
errno = res;
|
||||||
|
} else
|
||||||
|
allow = 0;
|
||||||
|
}
|
||||||
|
*pgid = scx->gid;
|
||||||
|
*pdsetgid = 0;
|
||||||
|
/* return directory group if S_ISGID is set */
|
||||||
|
if (allow && (perm & S_ISGID)) {
|
||||||
|
if (ntfs_get_owner_mode(scx, dir_ni, &stbuf) >= 0) {
|
||||||
|
*pdsetgid = stbuf.st_mode & S_ISGID;
|
||||||
|
if (perm & S_ISGID)
|
||||||
|
*pgid = stbuf.st_gid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (allow);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0 /* not needed any more */
|
#if 0 /* not needed any more */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3467,10 +3596,12 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
|
|||||||
uid = fileuid;
|
uid = fileuid;
|
||||||
if ((int)gid < 0)
|
if ((int)gid < 0)
|
||||||
gid = filegid;
|
gid = filegid;
|
||||||
|
#if !defined(__sun) || !defined (__SVR4)
|
||||||
/* clear setuid and setgid if owner has changed */
|
/* clear setuid and setgid if owner has changed */
|
||||||
/* unless request originated by root */
|
/* unless request originated by root */
|
||||||
if (uid && (fileuid != uid))
|
if (uid && (fileuid != uid))
|
||||||
mode &= 01777;
|
mode &= 01777;
|
||||||
|
#endif
|
||||||
#if POSIXACLS
|
#if POSIXACLS
|
||||||
res = ntfs_set_owner_mode(scx, ni, uid, gid,
|
res = ntfs_set_owner_mode(scx, ni, uid, gid,
|
||||||
mode, pxdesc);
|
mode, pxdesc);
|
||||||
@ -3679,7 +3810,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
|
|||||||
pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
|
pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
|
||||||
pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
|
pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
|
||||||
pnhead->alignment = 0;
|
pnhead->alignment = 0;
|
||||||
pnhead->control = SE_SELF_RELATIVE;
|
pnhead->control = (pphead->control
|
||||||
|
& (SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED))
|
||||||
|
| SE_SELF_RELATIVE;
|
||||||
pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
|
||||||
/*
|
/*
|
||||||
* locate and inherit DACL
|
* locate and inherit DACL
|
||||||
@ -3690,7 +3823,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
|
|||||||
offpacl = le32_to_cpu(pphead->dacl);
|
offpacl = le32_to_cpu(pphead->dacl);
|
||||||
ppacl = (const ACL*)&parentattr[offpacl];
|
ppacl = (const ACL*)&parentattr[offpacl];
|
||||||
pnacl = (ACL*)&newattr[pos];
|
pnacl = (ACL*)&newattr[pos];
|
||||||
aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir);
|
aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid,
|
||||||
|
fordir, pphead->control
|
||||||
|
& SE_DACL_AUTO_INHERITED);
|
||||||
if (aclsz) {
|
if (aclsz) {
|
||||||
pnhead->dacl = cpu_to_le32(pos);
|
pnhead->dacl = cpu_to_le32(pos);
|
||||||
pos += aclsz;
|
pos += aclsz;
|
||||||
@ -3705,7 +3840,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
|
|||||||
offpacl = le32_to_cpu(pphead->sacl);
|
offpacl = le32_to_cpu(pphead->sacl);
|
||||||
ppacl = (const ACL*)&parentattr[offpacl];
|
ppacl = (const ACL*)&parentattr[offpacl];
|
||||||
pnacl = (ACL*)&newattr[pos];
|
pnacl = (ACL*)&newattr[pos];
|
||||||
aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir);
|
aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid,
|
||||||
|
fordir, pphead->control
|
||||||
|
& SE_SACL_AUTO_INHERITED);
|
||||||
if (aclsz) {
|
if (aclsz) {
|
||||||
pnhead->sacl = cpu_to_le32(pos);
|
pnhead->sacl = cpu_to_le32(pos);
|
||||||
pos += aclsz;
|
pos += aclsz;
|
||||||
@ -3723,7 +3860,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
|
|||||||
*/
|
*/
|
||||||
memcpy(&newattr[pos],gsid,gsidsz);
|
memcpy(&newattr[pos],gsid,gsidsz);
|
||||||
pnhead->group = cpu_to_le32(pos);
|
pnhead->group = cpu_to_le32(pos);
|
||||||
pos += usidsz;
|
pos += gsidsz;
|
||||||
securid = setsecurityattr(scx->vol,
|
securid = setsecurityattr(scx->vol,
|
||||||
(SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos);
|
(SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos);
|
||||||
free(newattr);
|
free(newattr);
|
||||||
|
@ -255,6 +255,8 @@ int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode);
|
|||||||
BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni);
|
BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni);
|
||||||
int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
|
int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
|
||||||
ntfs_inode *ni, int accesstype);
|
ntfs_inode *ni, int accesstype);
|
||||||
|
int ntfs_allowed_create(struct SECURITY_CONTEXT *scx,
|
||||||
|
ntfs_inode *ni, gid_t *pgid, mode_t *pdsetgid);
|
||||||
BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
|
BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx,
|
||||||
const char *path, int accesstype);
|
const char *path, int accesstype);
|
||||||
|
|
||||||
|
@ -710,9 +710,9 @@ static int utf8_to_unicode(u32 *wc, const char *s)
|
|||||||
| ((u32)(s[1] & 0x3F) << 12)
|
| ((u32)(s[1] & 0x3F) << 12)
|
||||||
| ((u32)(s[2] & 0x3F) << 6)
|
| ((u32)(s[2] & 0x3F) << 6)
|
||||||
| ((u32)(s[3] & 0x3F));
|
| ((u32)(s[3] & 0x3F));
|
||||||
/* Check valid ranges */
|
/* Check valid ranges */
|
||||||
if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
|
if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -1011,7 +1011,7 @@ int ntfs_mbstoucs(const char *ins, ntfschar **outs)
|
|||||||
if (o >= ucs_len) {
|
if (o >= ucs_len) {
|
||||||
ntfschar *tc;
|
ntfschar *tc;
|
||||||
ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63;
|
ucs_len = (ucs_len * sizeof(ntfschar) + 64) & ~63;
|
||||||
tc = MEM2_realloc(ucs, ucs_len);
|
tc = realloc(ucs, ucs_len);
|
||||||
if (!tc)
|
if (!tc)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
ucs = tc;
|
ucs = tc;
|
||||||
|
@ -54,6 +54,10 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__sun) && defined (__SVR4)
|
||||||
|
#include <sys/mnttab.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "param.h"
|
#include "param.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "volume.h"
|
#include "volume.h"
|
||||||
@ -89,13 +93,9 @@ static const char *corrupt_volume_msg =
|
|||||||
"for more details.\n";
|
"for more details.\n";
|
||||||
|
|
||||||
static const char *hibernated_volume_msg =
|
static const char *hibernated_volume_msg =
|
||||||
"The NTFS partition is hibernated. Please resume and shutdown Windows\n"
|
"The NTFS partition is in an unsafe state. Please resume and shutdown\n"
|
||||||
"properly, or mount the volume read-only with the 'ro' mount option, or\n"
|
"Windows fully (no hibernation or fast restarting), or mount the volume\n"
|
||||||
"mount the volume read-write with the 'remove_hiberfile' mount option.\n"
|
"read-only with the 'ro' mount option.\n";
|
||||||
"For example type on the command line:\n"
|
|
||||||
"\n"
|
|
||||||
" mount -t ntfs-3g -o remove_hiberfile %s %s\n"
|
|
||||||
"\n";
|
|
||||||
|
|
||||||
static const char *unclean_journal_msg =
|
static const char *unclean_journal_msg =
|
||||||
"Write access is denied because the disk wasn't safely powered\n"
|
"Write access is denied because the disk wasn't safely powered\n"
|
||||||
@ -466,7 +466,8 @@ error_exit:
|
|||||||
* Return the allocated volume structure on success and NULL on error with
|
* Return the allocated volume structure on success and NULL on error with
|
||||||
* errno set to the error code.
|
* errno set to the error code.
|
||||||
*/
|
*/
|
||||||
ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags)
|
ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
||||||
|
ntfs_mount_flags flags)
|
||||||
{
|
{
|
||||||
LCN mft_zone_size, mft_lcn;
|
LCN mft_zone_size, mft_lcn;
|
||||||
s64 br;
|
s64 br;
|
||||||
@ -508,13 +509,25 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags)
|
|||||||
#else
|
#else
|
||||||
NVolClearCompression(vol);
|
NVolClearCompression(vol);
|
||||||
#endif
|
#endif
|
||||||
if (flags & MS_RDONLY)
|
if (flags & NTFS_MNT_RDONLY)
|
||||||
NVolSetReadOnly(vol);
|
NVolSetReadOnly(vol);
|
||||||
|
|
||||||
/* ...->open needs bracketing to compile with glibc 2.7 */
|
/* ...->open needs bracketing to compile with glibc 2.7 */
|
||||||
if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
|
if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
|
||||||
ntfs_log_perror("Error opening '%s'", dev->d_name);
|
if (!NVolReadOnly(vol) && (errno == EROFS)) {
|
||||||
goto error_exit;
|
if ((dev->d_ops->open)(dev, O_RDONLY)) {
|
||||||
|
ntfs_log_perror("Error opening read-only '%s'",
|
||||||
|
dev->d_name);
|
||||||
|
goto error_exit;
|
||||||
|
} else {
|
||||||
|
ntfs_log_info("Can only open '%s' as read-only\n",
|
||||||
|
dev->d_name);
|
||||||
|
NVolSetReadOnly(vol);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ntfs_log_perror("Error opening '%s'", dev->d_name);
|
||||||
|
goto error_exit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Attach the device to the volume. */
|
/* Attach the device to the volume. */
|
||||||
vol->dev = dev;
|
vol->dev = dev;
|
||||||
@ -649,6 +662,24 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
|
|||||||
|
|
||||||
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
|
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
|
||||||
err = EOPNOTSUPP;
|
err = EOPNOTSUPP;
|
||||||
|
/*
|
||||||
|
* If the latest restart page was identified as version
|
||||||
|
* 2.0, then Windows may have kept a cached copy of
|
||||||
|
* metadata for fast restarting, and we should not mount.
|
||||||
|
* Hibernation will be seen the same way on a non
|
||||||
|
* Windows-system partition, so we have to use the same
|
||||||
|
* error code (EPERM).
|
||||||
|
* The restart page may also be identified as version 2.0
|
||||||
|
* when access to the file system is terminated abruptly
|
||||||
|
* by unplugging or power cut, so mounting is also rejected
|
||||||
|
* after such an event.
|
||||||
|
*/
|
||||||
|
if (rp
|
||||||
|
&& (rp->major_ver == const_cpu_to_le16(2))
|
||||||
|
&& (rp->minor_ver == const_cpu_to_le16(0))) {
|
||||||
|
ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n");
|
||||||
|
err = EPERM;
|
||||||
|
}
|
||||||
free(rp);
|
free(rp);
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
out:
|
out:
|
||||||
@ -762,7 +793,8 @@ int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose)
|
|||||||
errno = EPERM;
|
errno = EPERM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (memcmp(buf, "hibr", 4) == 0) {
|
if ((memcmp(buf, "hibr", 4) == 0)
|
||||||
|
|| (memcmp(buf, "HIBR", 4) == 0)) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
ntfs_log_error("Windows is hibernated, refused to mount.\n");
|
ntfs_log_error("Windows is hibernated, refused to mount.\n");
|
||||||
errno = EPERM;
|
errno = EPERM;
|
||||||
@ -856,7 +888,7 @@ static int fix_txf_data(ntfs_volume *vol)
|
|||||||
* @flags is an optional second parameter. The same flags are used as for
|
* @flags is an optional second parameter. The same flags are used as for
|
||||||
* the mount system call (man 2 mount). Currently only the following flag
|
* the mount system call (man 2 mount). Currently only the following flag
|
||||||
* is implemented:
|
* is implemented:
|
||||||
* MS_RDONLY - mount volume read-only
|
* NTFS_MNT_RDONLY - mount volume read-only
|
||||||
*
|
*
|
||||||
* The function opens the device @dev and verifies that it contains a valid
|
* The function opens the device @dev and verifies that it contains a valid
|
||||||
* bootsector. Then, it allocates an ntfs_volume structure and initializes
|
* bootsector. Then, it allocates an ntfs_volume structure and initializes
|
||||||
@ -867,7 +899,7 @@ static int fix_txf_data(ntfs_volume *vol)
|
|||||||
* Return the allocated volume structure on success and NULL on error with
|
* Return the allocated volume structure on success and NULL on error with
|
||||||
* errno set to the error code.
|
* errno set to the error code.
|
||||||
*/
|
*/
|
||||||
ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
|
ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
|
||||||
{
|
{
|
||||||
s64 l;
|
s64 l;
|
||||||
ntfs_volume *vol;
|
ntfs_volume *vol;
|
||||||
@ -1195,12 +1227,13 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
|
|||||||
* Check for dirty logfile and hibernated Windows.
|
* Check for dirty logfile and hibernated Windows.
|
||||||
* We care only about read-write mounts.
|
* We care only about read-write mounts.
|
||||||
*/
|
*/
|
||||||
if (!(flags & (MS_RDONLY | MS_FORENSIC))) {
|
if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) {
|
||||||
if (!(flags & MS_IGNORE_HIBERFILE) &&
|
if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) &&
|
||||||
ntfs_volume_check_hiberfile(vol, 1) < 0)
|
ntfs_volume_check_hiberfile(vol, 1) < 0)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
if (ntfs_volume_check_logfile(vol) < 0) {
|
if (ntfs_volume_check_logfile(vol) < 0) {
|
||||||
if (!(flags & MS_RECOVER))
|
/* Always reject cached metadata for now */
|
||||||
|
if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM))
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
ntfs_log_info("The file system wasn't safely "
|
ntfs_log_info("The file system wasn't safely "
|
||||||
"closed on Windows. Fixing.\n");
|
"closed on Windows. Fixing.\n");
|
||||||
@ -1289,7 +1322,7 @@ int ntfs_set_ignore_case(ntfs_volume *vol)
|
|||||||
* @flags is an optional second parameter. The same flags are used as for
|
* @flags is an optional second parameter. The same flags are used as for
|
||||||
* the mount system call (man 2 mount). Currently only the following flags
|
* the mount system call (man 2 mount). Currently only the following flags
|
||||||
* is implemented:
|
* is implemented:
|
||||||
* MS_RDONLY - mount volume read-only
|
* NTFS_MNT_RDONLY - mount volume read-only
|
||||||
*
|
*
|
||||||
* The function opens the device or file @name and verifies that it contains a
|
* The function opens the device or file @name and verifies that it contains a
|
||||||
* valid bootsector. Then, it allocates an ntfs_volume structure and initializes
|
* valid bootsector. Then, it allocates an ntfs_volume structure and initializes
|
||||||
@ -1304,7 +1337,7 @@ int ntfs_set_ignore_case(ntfs_volume *vol)
|
|||||||
* soon as the function returns.
|
* soon as the function returns.
|
||||||
*/
|
*/
|
||||||
ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),
|
ntfs_volume *ntfs_mount(const char *name __attribute__((unused)),
|
||||||
unsigned long flags __attribute__((unused)))
|
ntfs_mount_flags flags __attribute__((unused)))
|
||||||
{
|
{
|
||||||
#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
|
#ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS
|
||||||
struct ntfs_device *dev;
|
struct ntfs_device *dev;
|
||||||
@ -1429,6 +1462,60 @@ exit:
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else /* HAVE_MNTENT_H */
|
||||||
|
|
||||||
|
#if defined(__sun) && defined (__SVR4)
|
||||||
|
|
||||||
|
static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
|
||||||
|
{
|
||||||
|
struct mnttab *mnt = NULL;
|
||||||
|
char *real_file = NULL, *real_fsname = NULL;
|
||||||
|
FILE *f;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
real_file = (char*)ntfs_malloc(PATH_MAX + 1);
|
||||||
|
if (!real_file)
|
||||||
|
return -1;
|
||||||
|
real_fsname = (char*)ntfs_malloc(PATH_MAX + 1);
|
||||||
|
mnt = (struct mnttab*)ntfs_malloc(MNT_LINE_MAX + 1);
|
||||||
|
if (!real_fsname || !mnt) {
|
||||||
|
err = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!ntfs_realpath_canonicalize(file, real_file)) {
|
||||||
|
err = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!(f = fopen(MNTTAB, "r"))) {
|
||||||
|
err = errno;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
while (!getmntent(f, mnt)) {
|
||||||
|
if (!ntfs_realpath_canonicalize(mnt->mnt_special, real_fsname))
|
||||||
|
continue;
|
||||||
|
if (!strcmp(real_file, real_fsname)) {
|
||||||
|
*mnt_flags = NTFS_MF_MOUNTED;
|
||||||
|
if (!strcmp(mnt->mnt_mountp, "/"))
|
||||||
|
*mnt_flags |= NTFS_MF_ISROOT;
|
||||||
|
if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw"))
|
||||||
|
*mnt_flags |= NTFS_MF_READONLY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(f);
|
||||||
|
exit:
|
||||||
|
free(mnt);
|
||||||
|
free(real_file);
|
||||||
|
free(real_fsname);
|
||||||
|
if (err) {
|
||||||
|
errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* defined(__sun) && defined (__SVR4) */
|
||||||
#endif /* HAVE_MNTENT_H */
|
#endif /* HAVE_MNTENT_H */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1460,7 +1547,7 @@ int ntfs_check_if_mounted(const char *file __attribute__((unused)),
|
|||||||
unsigned long *mnt_flags)
|
unsigned long *mnt_flags)
|
||||||
{
|
{
|
||||||
*mnt_flags = 0;
|
*mnt_flags = 0;
|
||||||
#ifdef HAVE_MNTENT_H
|
#if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4))
|
||||||
return ntfs_mntent_check(file, mnt_flags);
|
return ntfs_mntent_check(file, mnt_flags);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
@ -1642,6 +1729,10 @@ int ntfs_volume_error(int err)
|
|||||||
ret = NTFS_VOLUME_CORRUPT;
|
ret = NTFS_VOLUME_CORRUPT;
|
||||||
break;
|
break;
|
||||||
case EPERM:
|
case EPERM:
|
||||||
|
/*
|
||||||
|
* Hibernation and fast restarting are seen the
|
||||||
|
* same way on a non Windows-system partition.
|
||||||
|
*/
|
||||||
ret = NTFS_VOLUME_HIBERNATED;
|
ret = NTFS_VOLUME_HIBERNATED;
|
||||||
break;
|
break;
|
||||||
case EOPNOTSUPP:
|
case EOPNOTSUPP:
|
||||||
@ -1742,7 +1833,7 @@ int ntfs_volume_get_free_space(ntfs_volume *vol)
|
|||||||
*
|
*
|
||||||
* Change the label on the volume @vol to @label.
|
* Change the label on the volume @vol to @label.
|
||||||
*/
|
*/
|
||||||
int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len)
|
int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, int label_len)
|
||||||
{
|
{
|
||||||
ntfs_attr *na;
|
ntfs_attr *na;
|
||||||
char *old_vol_name;
|
char *old_vol_name;
|
||||||
@ -1777,7 +1868,7 @@ int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len)
|
|||||||
|
|
||||||
/* The volume name attribute does not exist. Need to add it. */
|
/* The volume name attribute does not exist. Need to add it. */
|
||||||
if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
|
if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
|
||||||
(u8*) label, label_len))
|
(const u8*) label, label_len))
|
||||||
{
|
{
|
||||||
err = errno;
|
err = errno;
|
||||||
ntfs_log_perror("Encountered error while adding "
|
ntfs_log_perror("Encountered error while adding "
|
||||||
|
@ -43,23 +43,6 @@
|
|||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
|
||||||
* Under Cygwin, DJGPP and FreeBSD we do not have MS_RDONLY,
|
|
||||||
* so we define them ourselves.
|
|
||||||
*/
|
|
||||||
#ifndef MS_RDONLY
|
|
||||||
#define MS_RDONLY 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MS_EXCLUSIVE 0x08000000
|
|
||||||
|
|
||||||
#ifndef MS_RECOVER
|
|
||||||
#define MS_RECOVER 0x10000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MS_IGNORE_HIBERFILE 0x20000000
|
|
||||||
#define MS_FORENSIC 0x04000000 /* No modification during mount */
|
|
||||||
|
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
typedef struct _ntfs_volume ntfs_volume;
|
typedef struct _ntfs_volume ntfs_volume;
|
||||||
|
|
||||||
@ -74,13 +57,29 @@ typedef struct _ntfs_volume ntfs_volume;
|
|||||||
/**
|
/**
|
||||||
* enum ntfs_mount_flags -
|
* enum ntfs_mount_flags -
|
||||||
*
|
*
|
||||||
|
* Flags for the ntfs_mount() function.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
NTFS_MNT_NONE = 0x00000000,
|
||||||
|
NTFS_MNT_RDONLY = 0x00000001,
|
||||||
|
NTFS_MNT_FORENSIC = 0x04000000, /* No modification during
|
||||||
|
* mount. */
|
||||||
|
NTFS_MNT_EXCLUSIVE = 0x08000000,
|
||||||
|
NTFS_MNT_RECOVER = 0x10000000,
|
||||||
|
NTFS_MNT_IGNORE_HIBERFILE = 0x20000000,
|
||||||
|
};
|
||||||
|
typedef unsigned long ntfs_mount_flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum ntfs_mounted_flags -
|
||||||
|
*
|
||||||
* Flags returned by the ntfs_check_if_mounted() function.
|
* Flags returned by the ntfs_check_if_mounted() function.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NTFS_MF_MOUNTED = 1, /* Device is mounted. */
|
NTFS_MF_MOUNTED = 1, /* Device is mounted. */
|
||||||
NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */
|
NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */
|
||||||
NTFS_MF_READONLY = 4, /* Device is mounted read-only. */
|
NTFS_MF_READONLY = 4, /* Device is mounted read-only. */
|
||||||
} ntfs_mount_flags;
|
} ntfs_mounted_flags;
|
||||||
|
|
||||||
extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags);
|
extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags);
|
||||||
|
|
||||||
@ -284,12 +283,12 @@ extern const char *ntfs_home;
|
|||||||
extern ntfs_volume *ntfs_volume_alloc(void);
|
extern ntfs_volume *ntfs_volume_alloc(void);
|
||||||
|
|
||||||
extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
||||||
unsigned long flags);
|
ntfs_mount_flags flags);
|
||||||
|
|
||||||
extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev,
|
extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev,
|
||||||
unsigned long flags);
|
ntfs_mount_flags flags);
|
||||||
|
|
||||||
extern ntfs_volume *ntfs_mount(const char *name, unsigned long flags);
|
extern ntfs_volume *ntfs_mount(const char *name, ntfs_mount_flags flags);
|
||||||
extern int ntfs_umount(ntfs_volume *vol, const BOOL force);
|
extern int ntfs_umount(ntfs_volume *vol, const BOOL force);
|
||||||
|
|
||||||
extern int ntfs_version_is_supported(ntfs_volume *vol);
|
extern int ntfs_version_is_supported(ntfs_volume *vol);
|
||||||
@ -302,7 +301,8 @@ extern int ntfs_volume_error(int err);
|
|||||||
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
|
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
|
||||||
|
|
||||||
extern int ntfs_volume_get_free_space(ntfs_volume *vol);
|
extern int ntfs_volume_get_free_space(ntfs_volume *vol);
|
||||||
extern int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len);
|
extern int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label,
|
||||||
|
int label_len);
|
||||||
|
|
||||||
extern int ntfs_set_shown_files(ntfs_volume *vol,
|
extern int ntfs_set_shown_files(ntfs_volume *vol,
|
||||||
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);
|
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);
|
||||||
|
Loading…
Reference in New Issue
Block a user