[haiku-commits] haiku: hrev46483 - in src/add-ons/kernel/file_systems/ntfs: libntfs utils

  • From: Gerasim Troeglazov <3deyes@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 4 Dec 2013 13:46:55 +0100 (CET)

hrev46483 adds 3 changesets to branch 'master'
old head: 9e47d4f714a395d060ecb4113042532bdb82ebcb
new head: 5287b8a778715de8320fe2bd932ceab5c185cc41
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5287b8a+%5E9e47d4f

----------------------------------------------------------------------------

da0906f: ntfs: Update ntfs3g

0d4e157: ntfs: Fix several warnings

5287b8a: ntfs: Directory position must be signed

                                   [ Gerasim Troeglazov <3dEyes@xxxxxxxxx> ]

----------------------------------------------------------------------------

25 files changed, 728 insertions(+), 460 deletions(-)
src/add-ons/kernel/file_systems/ntfs/fs_func.c   |   6 +-
.../kernel/file_systems/ntfs/libntfs/acls.c      | 170 ++++++++++++----
.../kernel/file_systems/ntfs/libntfs/acls.h      |   3 +-
.../kernel/file_systems/ntfs/libntfs/attrib.c    |  38 ++--
.../kernel/file_systems/ntfs/libntfs/attrib.h    |  15 +-
.../kernel/file_systems/ntfs/libntfs/bootsect.c  |   4 +-
.../kernel/file_systems/ntfs/libntfs/compat.h    |   6 +
.../kernel/file_systems/ntfs/libntfs/dir.c       | 173 ++++++++++++++---
.../kernel/file_systems/ntfs/libntfs/dir.h       |  13 +-
.../kernel/file_systems/ntfs/libntfs/layout.h    |  25 +--
.../kernel/file_systems/ntfs/libntfs/list.h      | 192 -------------------
.../kernel/file_systems/ntfs/libntfs/logfile.c   |  20 +-
.../kernel/file_systems/ntfs/libntfs/logging.c   |  18 +-
.../kernel/file_systems/ntfs/libntfs/logging.h   |   4 +-
.../kernel/file_systems/ntfs/libntfs/object_id.c |   1 +
.../kernel/file_systems/ntfs/libntfs/param.h     |  10 +
.../kernel/file_systems/ntfs/libntfs/reparse.c   |  54 ++++--
.../kernel/file_systems/ntfs/libntfs/security.c  | 169 ++++++++++++++--
.../kernel/file_systems/ntfs/libntfs/security.h  |   2 +
.../kernel/file_systems/ntfs/libntfs/unistr.c    |   6 +-
.../kernel/file_systems/ntfs/libntfs/volume.c    | 139 +++++++++++---
.../kernel/file_systems/ntfs/libntfs/volume.h    |  44 ++---
src/add-ons/kernel/file_systems/ntfs/ntfsdir.h   |   2 +-
.../kernel/file_systems/ntfs/utils/utils.c       |  73 +------
.../kernel/file_systems/ntfs/utils/utils.h       |   1 -

############################################################################

Commit:      da0906f232bbb77a42c8ef4bcce42fec93f7e7c4
URL:         http://cgit.haiku-os.org/haiku/commit/?id=da0906f
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Wed Dec  4 12:20:24 2013 UTC

ntfs: Update ntfs3g

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/ntfs/fs_func.c 
b/src/add-ons/kernel/file_systems/ntfs/fs_func.c
index 430922d..a6919ce 100644
--- a/src/add-ons/kernel/file_systems/ntfs/fs_func.c
+++ b/src/add-ons/kernel/file_systems/ntfs/fs_func.c
@@ -264,7 +264,7 @@ fs_identify_partition(int fd, partition_data *partition, 
void **_cookie)
        // get path for device
        if (ioctl(fd, B_GET_PATH_FOR_DEVICE, devpath) != 0) {
                // try mount
-               ntVolume = utils_mount_volume(devpath, MS_RDONLY | MS_RECOVER);
+               ntVolume = utils_mount_volume(devpath, NTFS_MNT_RDONLY | 
NTFS_MNT_RECOVER);
                if (ntVolume != NULL) {
                        if (ntVolume->vol_name && ntVolume->vol_name[0] != '\0')
                                strcpy(cookie->label, ntVolume->vol_name);
@@ -384,7 +384,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, 
const char *args,
 
        if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0
                || is_device_read_only(device)) {
-               mountFlags |= MS_RDONLY;
+               mountFlags |= NTFS_MNT_RDONLY;
                ns->flags |= B_FS_IS_READONLY;
        }
 
@@ -418,7 +418,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, 
const char *args,
                gNTFSVnodeOps.remove_attr = fs_remove_attrib;           
        }
 
-       ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER);
+       ns->ntvol = utils_mount_volume(device, mountFlags | NTFS_MNT_RECOVER);
        if (ns->ntvol != NULL)
                result = B_NO_ERROR;
        else
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.c
index 788ed03..fb6e877 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.c
@@ -4,7 +4,7 @@
  *     This module is part of ntfs-3g library, but may also be
  *     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
  * modify it under the terms of the GNU General Public License as published
@@ -108,7 +108,6 @@
 #include "secaudit.h"
 #endif /* HAVE_CONFIG_H */
 
-
 #ifdef __HAIKU__
 #define getgrnam(x) NULL
 #define getpwnam(x) NULL
@@ -142,6 +141,19 @@ static const char worldsidbytes[] = {
                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;
 
 /*
@@ -241,6 +253,12 @@ static int is_world_sid(const SID * usid)
            && (usid->identifier_authority.low_part ==  const_cpu_to_be32(5))
            && (usid->sub_authority[0] == const_cpu_to_le32(32))
            && (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)))
                );
 }
 
@@ -629,7 +647,7 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int 
attrsz)
                            && (offdacl+sizeof(ACL) < attrsz)))
                && (!offsacl
                        || ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE))
-                           && (offsacl+sizeof(ACL) < attrsz)))
+                           && (offsacl+sizeof(ACL) <= attrsz)))
                && !(phead->owner & const_cpu_to_le32(3))
                && !(phead->group & const_cpu_to_le32(3))
                && !(phead->dacl & const_cpu_to_le32(3))
@@ -670,7 +688,8 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int 
attrsz)
  */
 
 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 dst;
@@ -683,7 +702,9 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
        int gsidsz;
        const ACCESS_ALLOWED_ACE *poldace;
        ACCESS_ALLOWED_ACE *pnewace;
+       ACCESS_ALLOWED_ACE *pauthace;
 
+       pauthace = (ACCESS_ALLOWED_ACE*)NULL;
        usidsz = ntfs_sid_size(usid);
        gsidsz = ntfs_sid_size(gsid);
 
@@ -700,25 +721,19 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
        for (nace = 0; nace < oldcnt; nace++) {
                poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + 
src);
                acesz = le16_to_cpu(poldace->size);
-                       /* inheritance for access */
-               if (poldace->flags & selection) {
+               src += acesz;
+                       /*
+                        * 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*)
                                        ((char*)newacl + dst);
                        memcpy(pnewace,poldace,acesz);
-                               /*
-                                * 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);
-                       }
+                               /* reencode GENERIC_ALL */
                        if (pnewace->mask & GENERIC_ALL) {
                                pnewace->mask &= ~GENERIC_ALL;
                                if (fordir)
@@ -737,16 +752,70 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                                                        | FILE_EXEC
                                                        | 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 */
                        pnewace->flags &= ~(OBJECT_INHERIT_ACE
                                                | CONTAINER_INHERIT_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
-                  && (poldace->flags
+                       /*
+                        * Inheritance for access, specific to
+                        * creator-owner (and creator-group)
+                        */
+               if (fordir || !inherited
+                  || (poldace->flags
                           & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
                        pnewace = (ACCESS_ALLOWED_ACE*)
                                        ((char*)newacl + dst);
@@ -754,19 +823,46 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                                /*
                                 * Replace generic creator-owner and
                                 * creator-group by owner and group
+                                * (but keep for further inheritance)
                                 */
                        if (ntfs_same_sid(&pnewace->sid, ownersid)) {
                                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)) {
                                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;
                        newcnt++;
                }
-               src += acesz;
        }
                /*
                 * Adjust header if something was inherited
@@ -3065,6 +3161,7 @@ static int build_owngrp_permissions(const char *securattr,
        int nace;
        le32 special;
        BOOL grppresent;
+       BOOL ownpresent;
        le32 allowown, allowgrp, allowall;
        le32 denyown, denygrp, denyall;
 
@@ -3074,21 +3171,26 @@ static int build_owngrp_permissions(const char 
*securattr,
        special = const_cpu_to_le32(0);
        allowown = allowgrp = allowall = const_cpu_to_le32(0);
        denyown = denygrp = denyall = const_cpu_to_le32(0);
+       ownpresent = FALSE;
        grppresent = FALSE;
        if (offdacl) {
                acecnt = le16_to_cpu(pacl->ace_count);
                offace = offdacl + sizeof(ACL);
-       } else
+       } else {
                acecnt = 0;
+               offace = 0;
+       }
        for (nace = 0; nace < acecnt; nace++) {
                pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
                if (!(pace->flags & INHERIT_ONLY_ACE)) {
                        if ((ntfs_same_sid(usid, &pace->sid)
                           || ntfs_same_sid(ownersid, &pace->sid))
                            && (pace->mask & WRITE_OWNER)) {
-                               if (pace->type == ACCESS_ALLOWED_ACE_TYPE)
+                               if (pace->type == ACCESS_ALLOWED_ACE_TYPE) {
                                        allowown |= pace->mask;
-                               } else
+                                       ownpresent = TRUE;
+                               }
+                       } else
                                if (ntfs_same_sid(usid, &pace->sid)
                                   && (!(pace->mask & WRITE_OWNER))) {
                                        if (pace->type == 
ACCESS_ALLOWED_ACE_TYPE) {
@@ -3109,6 +3211,8 @@ static int build_owngrp_permissions(const char *securattr,
                        }
                        offace += le16_to_cpu(pace->size);
                }
+       if (!ownpresent)
+               allowown = allowall;
        if (!grppresent)
                allowgrp = allowall;
        return (merge_permissions(isdir,
@@ -3711,7 +3815,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                                pxace->perms |= POSIX_PERM_DENIAL;
                        else
                                if (pxace->tag == POSIX_ACL_OTHER)
-                                       pctx->permswrld = pxace->perms;
+                                       pctx->permswrld |= pxace->perms;
                        pctx->tagsset |= pxace->tag;
                        if (pace->flags & INHERIT_ONLY_ACE) {
                                l--;
@@ -3901,7 +4005,6 @@ int ntfs_build_permissions(const char *securattr,
 /*
  *             The following must be in some library...
  */
-
 #ifndef __HAIKU__
 static unsigned long atoul(const char *p)
 {                              /* must be somewhere ! */
@@ -3914,7 +4017,6 @@ static unsigned long atoul(const char *p)
 }
 #endif
 
-
 /*
  *             Build an internal representation of a SID
  *     Returns a copy in allocated memory if it succeeds
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h
index 8a83d32..4b08388 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h
@@ -185,7 +185,8 @@ char *ntfs_build_descr_posix(struct MAPPING* const 
mapping[],
 #endif /* POSIXACLS */
 
 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,
                        const SID *usid, const SID *gsid, BOOL isdir);
 char *ntfs_build_descr(mode_t mode,
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c
index 281a620..c116d9a 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c
@@ -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");
                        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
                if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
                        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.
  */
 int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
-                       ntfschar *name, u8 name_len, u8 *val, u32 size,
-                       ATTR_FLAGS data_flags)
+                       const ntfschar *name, u8 name_len, const u8 *val,
+                       u32 size, ATTR_FLAGS data_flags)
 {
        ntfs_attr_search_ctx *ctx;
        u32 length;
@@ -3864,7 +3871,7 @@ put_err_out:
  *     EIO     - I/O error occurred or damaged filesystem.
  */
 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)
 {
        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.
  */
 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;
        int err, i, offset;
@@ -4342,8 +4349,8 @@ err_out:
  *             Change an attribute flag
  */
 
-int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type,
-               ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
+int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, const ntfschar *name,
+               u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask)
 {
        ntfs_attr_search_ctx *ctx;
        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. */
                na->allocated_size = first_free_vcn << vol->cluster_size_bits;
-               /* Write mapping pairs for new runlist. */
 #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
+               /* Write mapping pairs for new runlist. */
                if (ntfs_attr_update_mapping_pairs(na, 0)) {
 #endif
                        err = errno;
@@ -6646,9 +6661,8 @@ exit:
  *     Returns the amount of data written, negative if there was an error
  */
 
-int ntfs_attr_data_write(ntfs_inode *ni,
-               ntfschar *stream_name, int stream_name_len,
-               char *buf, size_t size, off_t offset)
+int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name,
+               int stream_name_len, const char *buf, size_t size, off_t offset)
 {
        ntfs_attr *na = NULL;
        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)
 {
        ntfs_attr_search_ctx *ctx;
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h
index 67fb957..1979ba6 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h
@@ -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_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);
 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,
-               ATTR_FLAGS flags);
+               const ntfschar *name, u8 name_len, VCN lowest_vcn,
+               int dataruns_size, ATTR_FLAGS flags);
 extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
 
 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,
-               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_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 char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len);
 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,
                              ntfschar *name, u32 name_len);
 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);
 extern int ntfs_attr_data_write(ntfs_inode *ni,
                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 */
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c
index e9bea37..e9be072 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c
@@ -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);
        ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn);
        ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn);
-       if (vol->mft_lcn     > vol->nr_clusters ||
-           vol->mftmirr_lcn > vol->nr_clusters) {
+       if ((vol->mft_lcn     < 0 || vol->mft_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 "
                              "greater than the number of clusters (%lld).\n",
                              (long long)vol->mft_lcn, (long 
long)vol->mftmirr_lcn,
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h
index 04767b0..cc84670 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h
@@ -31,6 +31,12 @@
 #include <sys/param.h>
 #endif
 
+#include <errno.h>     /* ENODATA */
+
+#ifndef ENODATA
+#define ENODATA ENOENT
+#endif
+
 #ifndef PATH_MAX
 #define PATH_MAX 4096
 #endif
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c
index ccae47c..d5f08f2 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c
@@ -867,6 +867,87 @@ typedef enum {
        INDEX_TYPE_ALLOCATION,  /* index allocation */
 } 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
  * @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;
        else /* if (index_type == INDEX_TYPE_ROOT) */
                *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. */
        if (MREF_LE(ie->indexed_file) == FILE_root)
                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;
-       else if (fn->file_attributes & FILE_ATTR_SYSTEM)
-               dt_type = NTFS_DT_UNKNOWN;
        else
                dt_type = NTFS_DT_REG;
 
                /* 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)
                                || !(fn->file_attributes & FILE_ATTR_HIDDEN)))
             || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
@@ -962,7 +1047,7 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 
ivcn_bits,
  * Return the mft reference of the parent directory on success or -1 on error
  * with errno set to the error code.
  */
-static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
+MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
 {
        MFT_REF mref;
        ntfs_attr_search_ctx *ctx;
@@ -1397,8 +1482,8 @@ err_out:
  * on error with errno set to the error code.
  */
 static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
-               ntfschar *name, u8 name_len, mode_t type, dev_t dev,
-               ntfschar *target, int target_len)
+               const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
+               const ntfschar *target, int target_len)
 {
        ntfs_inode *ni;
        int rollback_data = 0, rollback_sd = 0;
@@ -1667,7 +1752,7 @@ err_out:
  * 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)
 {
        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,
-               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) {
                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,
-               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) {
                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.
  */
 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;
        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)))
                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) - 1);
@@ -2002,6 +2099,7 @@ search:
                                        "Leaving inconsistent metadata.\n");
                }
 #endif
+       debug_double_inode(ni->mft_no,0);
        if (ntfs_mft_record_free(ni->vol, ni)) {
                err = errno;
                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.
  */
-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)
 {
        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;
                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. */
        fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
@@ -2121,7 +2228,8 @@ err_out:
        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));
 }
@@ -2172,6 +2280,8 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
 /*
  *             Get a DOS name for a file in designated directory
  *
+ *     Not allowed if there are several non-dos names (EMLINK)
+ *
  *     Returns size if found
  *             0 if not found
  *             -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)
 {
        size_t outsize = 0;
+       int namecount = 0;
        FILE_NAME_ATTR *fn;
        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 +
                                le16_to_cpu(ctx->attr->value_offset));
 
+               if (fn->file_name_type != FILE_NAME_DOS)
+                       namecount++;
                if ((fn->file_name_type & FILE_NAME_DOS)
                    && (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);
+       if ((outsize > 0) && (namecount > 1)) {
+               outsize = -1;
+               errno = EMLINK; /* this error implies there is a dos name */
+       }
        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
  *
+ *     Not allowed if there are several non-dos names (EMLINK)
+ *
  *     Returns size if found
  *             0 if not found
  *             -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)
 {
        size_t outsize = 0;
+       int namecount = 0;
        FILE_NAME_ATTR *fn;
        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 +
                                le16_to_cpu(ctx->attr->value_offset));
 
+               if (fn->file_name_type != FILE_NAME_DOS)
+                       namecount++;
                if ((fn->file_name_type & FILE_NAME_WIN32)
                    && (MREF_LE(fn->parent_directory) == dnum)) {
                                /*
@@ -2248,6 +2370,11 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, 
ntfschar *longname)
                        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 (!outsize) {
                ntfs_attr_reinit_search_ctx(ctx);
@@ -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,
-                       ntfschar *name, int len,
+                       const ntfschar *name, int len,
                        FILE_NAME_TYPE_FLAGS nametype)
 {
        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,
-                       ntfschar *shortname, int shortlen,
-                       ntfschar *longname, int longlen,
-                       ntfschar *deletename, int deletelen, BOOL existed)
+                       const ntfschar *shortname, int shortlen,
+                       const ntfschar *longname, int longlen,
+                       const ntfschar *deletename, int deletelen, BOOL existed)
 {
        unsigned int linkcount;
        ntfs_volume *vol;
@@ -2568,7 +2695,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode 
*dir_ni,
                        res = -1;
        } else {
                res = -1;
-               errno = ENOENT;
+               if (!longlen)
+                       errno = ENOENT;
        }
        free(shortname);
        if (!closed) {
@@ -2644,7 +2772,8 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode 
*dir_ni)
                        }
                }
        } else {
-               errno = ENOENT;
+               if (!longlen)
+                       errno = ENOENT;
                res = -1;
        }
        if (!deleted) {
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
index 02ada58..66c8782 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
@@ -74,17 +74,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,
                const char *pathname);
 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,
-               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,
-               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_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);
 
-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);
 
 /*
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h
index c167135..427f152 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h
@@ -2398,18 +2398,19 @@ typedef enum {
        IO_REPARSE_TAG_RESERVED_ONE     = 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_NSS_RECOVER      = const_cpu_to_le32(0x68000006),
-       IO_REPARSE_TAG_SIS              = const_cpu_to_le32(0x68000007),
-       IO_REPARSE_TAG_DFS              = const_cpu_to_le32(0x68000008),
-
-       IO_REPARSE_TAG_MOUNT_POINT      = const_cpu_to_le32(0x88000003),
-
-       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),
+       IO_REPARSE_TAG_CSV              = const_cpu_to_le32(0x80000009),
+       IO_REPARSE_TAG_DEDUP            = const_cpu_to_le32(0x80000013),
+       IO_REPARSE_TAG_DFS              = const_cpu_to_le32(0x8000000A),
+       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_VALID_VALUES     = const_cpu_to_le32(0xf000ffff),
 } PREDEFINED_REPARSE_TAGS;
 
 /**
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h
deleted file mode 100644
index 415e03c..0000000
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * list.h - Linked list implementation. Originated from the Linux-NTFS project.
- *
- * Copyright (c) 2000-2002 Anton Altaparmakov and others
- *
- * This program/include file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program/include file is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program (in the main directory of the NTFS-3G
- * distribution in the file COPYING); if not, write to the Free Software
- * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef _NTFS_LIST_H
-#define _NTFS_LIST_H
-
-/**
- * struct list_head - Simple doubly linked list implementation.
- * 
- * Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor
- * modifications). - AIA
- *
- * Some of the internal functions ("__xxx") are useful when
- * manipulating whole lists rather than single entries, as
- * sometimes we already know the next/prev entries and we can
- * generate better code by using them directly rather than
- * using the generic single-entry routines.
- */
-struct list_head {
-       struct list_head *next, *prev;
-};
-
-#define LIST_HEAD_INIT(name) { &(name), &(name) }
-
-#define LIST_HEAD(name) \
-       struct list_head name = LIST_HEAD_INIT(name)
-
-#define INIT_LIST_HEAD(ptr) do { \
-       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
-} while (0)
-
-/**
- * __list_add - Insert a new entry between two known consecutive entries.
- * @new:
- * @prev:
- * @next:
- *
- * This is only for internal list manipulation where we know the prev/next
- * entries already!
- */
-static void __list_add(struct list_head * new,
-               struct list_head * prev, struct list_head * next)
-{
-       next->prev = new;
-       new->next = next;
-       new->prev = prev;
-       prev->next = new;
-}
-
-/**
- * list_add - add a new entry
- * @new:       new entry to be added
- * @head:      list head to add it after
- *
- * Insert a new entry after the specified head.
- * This is good for implementing stacks.
- */
-static __inline__ void list_add(struct list_head *new, struct list_head *head)
-{
-       __list_add(new, head, head->next);
-}
-
-/**
- * list_add_tail - add a new entry
- * @new:       new entry to be added
- * @head:      list head to add it before
- *
- * Insert a new entry before the specified head.
- * This is useful for implementing queues.
- */
-static __inline__ void list_add_tail(struct list_head *new, struct list_head 
*head)
-{
-       __list_add(new, head->prev, head);
-}
-
-/**
- * __list_del -
- * @prev:
- * @next:
- *
- * Delete a list entry by making the prev/next entries point to each other.
- *
- * This is only for internal list manipulation where we know the prev/next
- * entries already!
- */
-static __inline__ void __list_del(struct list_head * prev,
-               struct list_head * next)
-{
-       next->prev = prev;
-       prev->next = next;
-}
-
-/**
- * list_del - deletes entry from list.
- * @entry:     the element to delete from the list.
- *
- * Note: list_empty on entry does not return true after this, the entry is in
- * an undefined state.
- */
-static __inline__ void list_del(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-}
-
-/**
- * list_del_init - deletes entry from list and reinitialize it.
- * @entry:     the element to delete from the list.
- */
-static __inline__ void list_del_init(struct list_head *entry)
-{
-       __list_del(entry->prev, entry->next);
-       INIT_LIST_HEAD(entry);
-}
-
-/**
- * list_empty - tests whether a list is empty
- * @head:      the list to test.
- */
-static __inline__ int list_empty(struct list_head *head)
-{
-       return head->next == head;
-}
-
-/**
- * list_splice - join two lists
- * @list:      the new list to add.
- * @head:      the place to add it in the first list.
- */
-static void list_splice(struct list_head *list,
-               struct list_head *head)
-{
-       struct list_head *first = list->next;
-
-       if (first != list) {
-               struct list_head *last = list->prev;
-               struct list_head *at = head->next;
-
-               first->prev = head;
-               head->next = first;
-
-               last->next = at;
-               at->prev = last;
-       }
-}
-
-/**
- * list_entry - get the struct for this entry
- * @ptr:       the &struct list_head pointer.
- * @type:      the type of the struct this is embedded in.
- * @member:    the name of the list_struct within the struct.
- */
-#define list_entry(ptr, type, member) \
-       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
-
-/**
- * list_for_each - iterate over a list
- * @pos:       the &struct list_head to use as a loop counter.
- * @head:      the head for your list.
- */
-#define list_for_each(pos, head) \
-       for (pos = (head)->next; pos != (head); pos = pos->next)
-
-/**
- * list_for_each_safe  -       iterate over a list safe against removal of 
list entry
- * @pos:       the &struct list_head to use as a loop counter.
- * @n:         another &struct list_head to use as temporary storage
- * @head:      the head for your list.
- */
-#define list_for_each_safe(pos, n, head) \
-       for (pos = (head)->next, n = pos->next; pos != (head); \
-               pos = n, n = pos->next)
-
-#endif /* defined _NTFS_LIST_H */
-
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c
index a4f00d5..336bdd2 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c
@@ -84,13 +84,21 @@ static BOOL 
ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos)
                                "position in $LogFile.\n");
                return FALSE;
        }
-       /* We only know how to handle version 1.1. */
-       if (sle16_to_cpu(rp->major_ver) != 1 ||
-                       sle16_to_cpu(rp->minor_ver) != 1) {
+       /*
+        * We only know how to handle version 1.1 and 2.0, though
+        * 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 "
-                               "supported.  (This driver supports version "
-                               "1.1 only.)\n", 
(int)sle16_to_cpu(rp->major_ver),
-                               (int)sle16_to_cpu(rp->minor_ver));
+                               "supported.\n   (This driver supports version "
+                               "1.1 and 2.0 only.)\n",
+                                       (int)sle16_to_cpu(rp->major_ver),
+                                       (int)sle16_to_cpu(rp->minor_ver));
                return FALSE;
        }
        /*
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
index af672dc..f781ee1 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
@@ -188,7 +188,6 @@ u32 ntfs_log_clear_flags(u32 flags)
        return old;
 }
 
-#ifndef __HAIKU__
 /**
  * ntfs_log_get_stream - Default output streams for logging levels
  * @level:     Log level
@@ -198,6 +197,7 @@ u32 ntfs_log_clear_flags(u32 flags)
  *
  * Returns:  "string"  Prefix to be used
  */
+#ifndef __HAIKU__
 static FILE * ntfs_log_get_stream(u32 level)
 {
        FILE *stream;
@@ -276,8 +276,7 @@ static const char * ntfs_log_get_prefix(u32 level)
 
        return prefix;
 }
-#endif
-
+#endif //__HAIKU___
 
 /**
  * ntfs_log_set_handler - Provide an alternate logging handler
@@ -399,7 +398,7 @@ out:
 
 void ntfs_log_early_error(const char *format, ...)
 {
-#ifndef __HAIKU__      
+#ifndef __HAIKU__
        va_list args;
 
        va_start(args, format);
@@ -412,10 +411,9 @@ void ntfs_log_early_error(const char *format, ...)
        vfprintf(stderr,format,args);
 #endif
        va_end(args);
-#endif
+#endif //__HAIKU__
 }
 
-#ifndef __HAIKU__
 /**
  * ntfs_log_handler_fprintf - Basic logging handler
  * @function:  Function in which the log line occurred
@@ -437,6 +435,7 @@ void ntfs_log_early_error(const char *format, ...)
  *            0  Message wasn't logged
  *          num  Number of output characters
  */
+#ifndef __HAIKU__
 int ntfs_log_handler_fprintf(const char *function, const char *file,
        int line, u32 level, void *data, const char *format, va_list args)
 {
@@ -491,7 +490,6 @@ int ntfs_log_handler_fprintf(const char *function, const 
char *file,
        errno = olderr;
        return ret;
 }
-
 #endif // __HAIKU__
 
 /**
@@ -516,8 +514,6 @@ int ntfs_log_handler_null(const char *function 
__attribute__((unused)), const ch
        return 0;
 }
 
-#ifndef __HAIKU__
-
 /**
  * ntfs_log_handler_stdout - All logs go to stdout
  * @function:  Function in which the log line occurred
@@ -539,6 +535,7 @@ int ntfs_log_handler_null(const char *function 
__attribute__((unused)), const ch
  *            0  Message wasn't logged
  *          num  Number of output characters
  */
+#ifndef __HAIKU__
 int ntfs_log_handler_stdout(const char *function, const char *file,
        int line, u32 level, void *data, const char *format, va_list args)
 {
@@ -608,8 +605,7 @@ int ntfs_log_handler_stderr(const char *function, const 
char *file,
 
        return ntfs_log_handler_fprintf(function, file, line, level, data, 
format, args);
 }
-
-#endif // __HAIKU__
+#endif //__HAIKU__
 
 /**
  * ntfs_log_parse_option - Act upon command line options
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h
index c68cd4c..1f55fda 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h
@@ -37,11 +37,11 @@
 typedef int (ntfs_log_handler)(const char *function, const char *file, int 
line,
        u32 level, void *data, const char *format, va_list args);
 
-#ifndef __HAIKU__
 /* Set the logging handler from one of the functions, below. */
+#ifndef __HAIKU__
 void ntfs_log_set_handler(ntfs_log_handler *handler 
                          __attribute__((format(printf, 6, 0))));
-#endif                   
+#endif
 
 /* Logging handlers */
 ntfs_log_handler ntfs_log_handler_syslog  __attribute__((format(printf, 6, 
0)));
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c
index 059e882..299357e 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c
@@ -46,6 +46,7 @@
 #include <sys/sysmacros.h>
 #endif
 
+#include "compat.h"
 #include "types.h"
 #include "debug.h"
 #include "attrib.h"
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h
index 5d96b1c..da794ab 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h
@@ -51,6 +51,12 @@ enum {
 #define MAX_COMPRESSION_CLUSTER_SIZE 4096
 
 /*
+ *             Parameters for default options
+ */
+
+#define DEFAULT_DMTIME 60 /* default 1mn for delay_mtime */
+
+/*
  *             Use of big write buffers
  *
  *     With small volumes, the cluster allocator may fail to allocate
@@ -109,7 +115,11 @@ enum {
  *     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
+#endif
 #if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28)
 #define LPERMSCONFIG 5
 #else
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c
index 05490bf..dc44bcd 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c
@@ -3,7 +3,7 @@
  *
  *     This module is part of ntfs-3g library
  *
- * Copyright (c) 2008-2009 Jean-Pierre Andre
+ * Copyright (c) 2008-2012 Jean-Pierre Andre
  *
  * This program/include file is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as published
@@ -46,8 +46,10 @@
 #include <sys/sysmacros.h>
 #endif
 
+#include "compat.h"
 #include "types.h"
 #include "debug.h"
+#include "layout.h"
 #include "attrib.h"
 #include "inode.h"
 #include "dir.h"
@@ -59,18 +61,6 @@
 #include "misc.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 */
        le16    subst_name_offset;
        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);
        if (ni) {
                start = 0;
+               /*
+                * Examine and translate the path, until we reach either
+                *  - the end,
+                *  - an unknown item
+                *  - a non-directory
+                *  - another reparse point,
+                * A reparse point is not dereferenced, it will be
+                * examined later when the translated path is dereferenced,
+                * however the final part of the path will not be adjusted
+                * to correct case.
+                */
                do {
                        len = 0;
                        while (((start + len) < count)
@@ -252,9 +253,11 @@ static char *search_absolute(ntfs_volume *vol, ntfschar 
*path,
                        }
                } while (ni
                    && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
+                   && !(ni->flags & FILE_ATTR_REPARSE_POINT)
                    && (start < count));
        if (ni
-           && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir))
+           && ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)
+               || (ni->flags & FILE_ATTR_REPARSE_POINT)))
                if (ntfs_ucstombs(path, count, &target, 0) < 0) {
                        if (target) {
                                free(target);
@@ -288,12 +291,25 @@ static char *search_relative(ntfs_inode *ni, ntfschar 
*path, int count)
        int pos;
        int lth;
        BOOL ok;
+       BOOL morelinks;
        int max = 32; /* safety */
 
        pos = 0;
        ok = TRUE;
+       morelinks = FALSE;
        curni = ntfs_dir_parent_inode(ni);
-       while (curni && ok && (pos < (count - 1)) && --max) {
+               /*
+                * Examine and translate the path, until we reach either
+                *  - the end,
+                *  - an unknown item
+                *  - a non-directory
+                *  - another reparse point,
+                * A reparse point is not dereferenced, it will be
+                * examined later when the translated path is dereferenced,
+                * however the final part of the path will not be adjusted
+                * to correct case.
+                */
+       while (curni && ok && !morelinks && (pos < (count - 1)) && --max) {
                if ((count >= (pos + 2))
                    && (path[pos] == const_cpu_to_le16('.'))
                    && (path[pos+1] == const_cpu_to_le16('\\'))) {
@@ -331,12 +347,18 @@ static char *search_relative(ntfs_inode *ni, ntfschar 
*path, int count)
                                        if (!curni)
                                                ok = FALSE;
                                        else {
+                                               if (curni->flags & 
FILE_ATTR_REPARSE_POINT)
+                                                       morelinks = TRUE;
                                                if (ok && ((pos + lth) < 
count)) {
                                                        path[pos + lth] = 
const_cpu_to_le16('/');
                                                        pos += lth + 1;
+                                                       if (morelinks
+                                                          && 
ntfs_inode_close(curni))
+                                                               ok = FALSE;
                                                } else {
                                                        pos += lth;
-                                                       if ((ni->mrec->flags ^ 
curni->mrec->flags)
+                                                       if (!morelinks
+                                                         && (ni->mrec->flags ^ 
curni->mrec->flags)
                                                            & 
MFT_RECORD_IS_DIRECTORY)
                                                                ok = FALSE;
                                                        if 
(ntfs_inode_close(curni))
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
index 7075ca2..4fcf4c1 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2004 Anton Altaparmakov
  * Copyright (c) 2005-2006 Szabolcs Szakacsits
  * 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
  * modify it under the terms of the GNU General Public License as published
@@ -52,6 +52,7 @@
 #include <pwd.h>
 #include <grp.h>
 
+#include "compat.h"
 #include "param.h"
 #include "types.h"
 #include "layout.h"
@@ -69,6 +70,7 @@
 #define getpwuid(a) NULL
 #endif
 
+
 /*
  *     JPA NTFS constants or structs
  *     should be moved to layout.h
@@ -1133,10 +1135,93 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT 
*scx, uid_t uid, gid_t gid
        return (ingroup);
 }
 
+#if defined(__sun) && defined (__SVR4)
 
 /*
  *             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);
+}
+
+#elif defined(__HAIKU__)
+
+static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
+{
+       return TRUE;
+}
+
+#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
  *
  * As indicated by Miklos Szeredi :
@@ -1155,12 +1240,6 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT 
*scx, uid_t uid, gid_t gid
  * contains the same data.
  */
 
-#ifdef __HAIKU__
-static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
-{
-       return TRUE;
-}
-#else
 static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid)
 {
        static char key[] = "\nGroups:";
@@ -1244,7 +1323,8 @@ static BOOL groupmember(struct SECURITY_CONTEXT *scx, 
uid_t uid, gid_t gid)
        }
        return (ismember);
 }
-#endif
+
+#endif /* defined(__sun) && defined (__SVR4) */
 
 /*
  *     Cacheing is done two-way :
@@ -1809,7 +1889,7 @@ static int access_check_posix(struct SECURITY_CONTEXT 
*scx,
                if (!scx->uid) {
                                        /* root access if owner or other 
execution */
                        if (perms & 0101)
-                               perms = 07777;
+                               perms |= 01777;
                        else {
                                        /* root access if some group execution 
*/
                                groupperms = 0;
@@ -2225,7 +2305,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
                        if (!scx->uid) {
                                /* root access and execution */
                                if (perm & 0111)
-                                       perm = 07777;
+                                       perm |= 01777;
                                else
                                        perm = 0;
                        } else
@@ -3328,6 +3408,56 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
        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 */
 
 /*
@@ -3479,10 +3609,12 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, 
ntfs_inode *ni,
                                uid = fileuid;
                        if ((int)gid < 0)
                                gid = filegid;
+#if !defined(__sun) || !defined (__SVR4)
                        /* clear setuid and setgid if owner has changed */
                         /* unless request originated by root */
                        if (uid && (fileuid != uid))
                                mode &= 01777;
+#endif
 #if POSIXACLS
                        res = ntfs_set_owner_mode(scx, ni, uid, gid, 
                                mode, pxdesc);
@@ -3691,7 +3823,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT 
*scx,
                pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr;
                pnhead->revision = SECURITY_DESCRIPTOR_REVISION;
                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);
                        /*
                         * locate and inherit DACL
@@ -3702,7 +3836,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT 
*scx,
                        offpacl = le32_to_cpu(pphead->dacl);
                        ppacl = (const ACL*)&parentattr[offpacl];
                        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) {
                                pnhead->dacl = cpu_to_le32(pos);
                                pos += aclsz;
@@ -3717,7 +3853,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT 
*scx,
                        offpacl = le32_to_cpu(pphead->sacl);
                        ppacl = (const ACL*)&parentattr[offpacl];
                        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) {
                                pnhead->sacl = cpu_to_le32(pos);
                                pos += aclsz;
@@ -3735,7 +3873,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT 
*scx,
                         */
                memcpy(&newattr[pos],gsid,gsidsz);
                pnhead->group = cpu_to_le32(pos);
-               pos += usidsz;
+               pos += gsidsz;
                securid = setsecurityattr(scx->vol,
                        (SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos);
                free(newattr);
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h
index 9d7dd33..8875c9c 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h
@@ -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);
 int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
                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,
                const char *path, int accesstype);
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c
index a5e88e8..72dd3b0 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c
@@ -719,9 +719,9 @@ static int utf8_to_unicode(u32 *wc, const char *s)
                            | ((u32)(s[1] & 0x3F) << 12)
                            | ((u32)(s[2] & 0x3F) << 6)
                            | ((u32)(s[3] & 0x3F));
-               /* Check valid ranges */
-               if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
-                       return 4;
+                       /* Check valid ranges */
+                       if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
+                               return 4;
                }
                goto fail;
        }
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c
index 3f19879..6acef48 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c
@@ -54,6 +54,10 @@
 #include <locale.h>
 #endif
 
+#if defined(__sun) && defined (__SVR4)
+#include <sys/mnttab.h>
+#endif
+
 #include "param.h"
 #include "compat.h"
 #include "volume.h"
@@ -89,13 +93,9 @@ static const char *corrupt_volume_msg =
 "for more details.\n";
 
 static const char *hibernated_volume_msg =
-"The NTFS partition is hibernated. Please resume and shutdown Windows\n"
-"properly, or mount the volume read-only with the 'ro' mount option, or\n"
-"mount the volume read-write with the 'remove_hiberfile' mount option.\n"
-"For example type on the command line:\n"
-"\n"
-"            mount -t ntfs-3g -o remove_hiberfile %s %s\n"
-"\n";
+"The NTFS partition is in an unsafe state. Please resume and shutdown\n"
+"Windows fully (no hibernation or fast restarting), or mount the volume\n"
+"read-only with the 'ro' mount option.\n";
 
 static const char *unclean_journal_msg =
 "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
  * 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;
        s64 br;
@@ -508,13 +509,25 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, 
unsigned long flags)
 #else
        NVolClearCompression(vol);
 #endif
-       if (flags & MS_RDONLY)
+       if (flags & NTFS_MNT_RDONLY)
                NVolSetReadOnly(vol);
        
        /* ...->open needs bracketing to compile with glibc 2.7 */
        if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
-               ntfs_log_perror("Error opening '%s'", dev->d_name);
-               goto error_exit;
+               if (!NVolReadOnly(vol) && (errno == EROFS)) {
+                       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. */
        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))
                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);
        ntfs_attr_close(na);
 out:   
@@ -762,7 +793,8 @@ int ntfs_volume_check_hiberfile(ntfs_volume *vol, int 
verbose)
                errno = EPERM;
                goto out;
        }
-       if (memcmp(buf, "hibr", 4) == 0) {
+       if ((memcmp(buf, "hibr", 4) == 0)
+          ||  (memcmp(buf, "HIBR", 4) == 0)) {
                if (verbose)
                        ntfs_log_error("Windows is hibernated, refused to 
mount.\n");
                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
  * the mount system call (man 2 mount). Currently only the following flag
  * 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
  * 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
  * 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;
        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.
         * We care only about read-write mounts.
         */
-       if (!(flags & (MS_RDONLY | MS_FORENSIC))) {
-               if (!(flags & MS_IGNORE_HIBERFILE) && 
+       if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) {
+               if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) &&
                    ntfs_volume_check_hiberfile(vol, 1) < 0)
                        goto error_exit;
                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;
                        ntfs_log_info("The file system wasn't safely "
                                      "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
  * the mount system call (man 2 mount). Currently only the following flags
  * 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
  * 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.
  */
 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
        struct ntfs_device *dev;
@@ -1429,6 +1462,60 @@ exit:
        }
        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 */
 
 /**
@@ -1460,7 +1547,7 @@ int ntfs_check_if_mounted(const char *file 
__attribute__((unused)),
                unsigned long *mnt_flags)
 {
        *mnt_flags = 0;
-#ifdef HAVE_MNTENT_H
+#if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4))
        return ntfs_mntent_check(file, mnt_flags);
 #else
        return 0;
@@ -1642,6 +1729,10 @@ int ntfs_volume_error(int err)
                        ret = NTFS_VOLUME_CORRUPT;
                        break;
                case EPERM:
+                       /*
+                        * Hibernation and fast restarting are seen the
+                        * same way on a non Windows-system partition.
+                        */
                        ret = NTFS_VOLUME_HIBERNATED;
                        break;
                case EOPNOTSUPP:
@@ -1693,7 +1784,7 @@ void ntfs_mount_error(const char *volume, const char 
*mntpoint, int err)
 
 int ntfs_set_locale(void)
 {
-#ifndef __HAIKU__      
+#ifndef __HAIKU__
        const char *locale;
 
        locale = setlocale(LC_ALL, "");
@@ -1703,7 +1794,7 @@ int ntfs_set_locale(void)
                               "'%s'.\n", locale);
                return 1;
        }
-#endif 
+#endif
        return 0;
 }
 
@@ -1744,7 +1835,7 @@ int ntfs_volume_get_free_space(ntfs_volume *vol)
  *
  * 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;
        char *old_vol_name;
@@ -1779,7 +1870,7 @@ int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, 
int label_len)
 
                /* The volume name attribute does not exist.  Need to add it. */
                if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
-                       (u8*) label, label_len))
+                       (const u8*) label, label_len))
                {
                        err = errno;
                        ntfs_log_perror("Encountered error while adding "
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h
index 9d62d66..a181ccc 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h
@@ -43,23 +43,6 @@
 #include <mntent.h>
 #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 */
 typedef struct _ntfs_volume ntfs_volume;
 
@@ -74,13 +57,29 @@ typedef struct _ntfs_volume ntfs_volume;
 /**
  * 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.
  */
 typedef enum {
        NTFS_MF_MOUNTED         = 1,    /* Device is mounted. */
        NTFS_MF_ISROOT          = 2,    /* Device is mounted as system root. */
        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);
 
@@ -284,12 +283,12 @@ extern const char *ntfs_home;
 extern ntfs_volume *ntfs_volume_alloc(void);
 
 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,
-               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_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 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,
                BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);
diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c 
b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c
index e224d5f..545c609 100644
--- a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c
+++ b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c
@@ -275,11 +275,11 @@ ntfs_volume * utils_mount_volume(const char *device, 
unsigned long flags)
         *
         * libntfs-3g only has safety check number 2. The dirty flag is simply
         * ignored because we are confident that we can handle a dirty volume.
-        * So we treat MS_RECOVER like NTFS_MNT_FORCE, knowing that the first
-        * check is always bypassed.
+        * So we treat NTFS_MNT_RECOVER like NTFS_MNT_FORCE, knowing that the
+        * first check is always bypassed.
         */
 
-       if (!utils_valid_device(device, flags & MS_RECOVER))
+       if (!utils_valid_device(device, flags & NTFS_MNT_RECOVER))
                return NULL;
 
        vol = ntfs_mount(device, flags);
@@ -305,7 +305,7 @@ ntfs_volume * utils_mount_volume(const char *device, 
unsigned long flags)
         * before mount, so we can only warn if the VOLUME_IS_DIRTY flag is set
         * in VOLUME_INFORMATION. */
        if (vol->flags & VOLUME_IS_DIRTY) {
-               if (!(flags & MS_RECOVER)) {
+               if (!(flags & NTFS_MNT_RECOVER)) {
                        ntfs_log_error("%s", dirty_volume_msg);
                        ntfs_umount(vol, FALSE);
                        return NULL;
@@ -1122,69 +1122,4 @@ int mft_next_record(struct mft_search_ctx *ctx)
        return (ctx->inode == NULL);
 }
 
-/**
- * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode
- * @ni:                ntfs inode whose parent directory to find
- *
- * Find the parent directory of the ntfs inode @ni. To do this, find the first
- * file name attribute in the mft record of @ni and return the parent mft
- * reference from that.
- *
- * Note this only makes sense for directories, since files can be hard linked
- * from multiple directories and there is no way for us to tell which one is
- * being looked for.
- *
- * Technically directories can have hard links, too, but we consider that as
- * illegal as Linux/UNIX do not support directory hard links.
- *
- * Return the mft reference of the parent directory on success or -1 on error
- * with errno set to the error code.
- */
-MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
-{
-       MFT_REF mref;
-       ntfs_attr_search_ctx *ctx;
-       FILE_NAME_ATTR *fn;
-       int eo;
-
-       ntfs_log_trace("Entering.\n");
-       
-       if (!ni) {
-               errno = EINVAL;
-               return ERR_MREF(-1);
-       }
-
-       ctx = ntfs_attr_get_search_ctx(ni, NULL);
-       if (!ctx)
-               return ERR_MREF(-1);
-       if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
-               ntfs_log_error("No file name found in inode %lld\n", 
-                              (unsigned long long)ni->mft_no);
-               goto err_out;
-       }
-       if (ctx->attr->non_resident) {
-               ntfs_log_error("File name attribute must be resident (inode "
-                              "%lld)\n", (unsigned long long)ni->mft_no);
-               goto io_err_out;
-       }
-       fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
-                       le16_to_cpu(ctx->attr->value_offset));
-       if ((u8*)fn +   le32_to_cpu(ctx->attr->value_length) >
-                       (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) {
-               ntfs_log_error("Corrupt file name attribute in inode %lld.\n",
-                              (unsigned long long)ni->mft_no);
-               goto io_err_out;
-       }
-       mref = le64_to_cpu(fn->parent_directory);
-       ntfs_attr_put_search_ctx(ctx);
-       return mref;
-io_err_out:
-       errno = EIO;
-err_out:
-       eo = errno;
-       ntfs_attr_put_search_ctx(ctx);
-       errno = eo;
-       return ERR_MREF(-1);
-}
-
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/utils.h 
b/src/add-ons/kernel/file_systems/ntfs/utils/utils.h
index 027a15a..3974da0 100644
--- a/src/add-ons/kernel/file_systems/ntfs/utils/utils.h
+++ b/src/add-ons/kernel/file_systems/ntfs/utils/utils.h
@@ -85,7 +85,6 @@ struct mft_search_ctx {
 struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol);
 void mft_put_search_ctx(struct mft_search_ctx *ctx);
 int mft_next_record(struct mft_search_ctx *ctx);
-MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni);
 
 // Flags for dump mem
 #define DM_DEFAULTS    0

############################################################################

Commit:      0d4e157ba44dccb274f7b0d300a921d9d5cca8c4
URL:         http://cgit.haiku-os.org/haiku/commit/?id=0d4e157
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Wed Dec  4 12:34:49 2013 UTC

ntfs: Fix several warnings

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
index 66c8782..43308d1 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h
@@ -88,6 +88,8 @@ extern int ntfs_delete(ntfs_volume *vol, const char *path,
 extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
                u8 name_len);
 
+extern MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni);
+
 /*
  * File types (adapted from include <linux/fs.h>)
  */
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
index f781ee1..8102827 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c
@@ -276,7 +276,6 @@ static const char * ntfs_log_get_prefix(u32 level)
 
        return prefix;
 }
-#endif //__HAIKU___
 
 /**
  * ntfs_log_set_handler - Provide an alternate logging handler
@@ -296,6 +295,7 @@ void ntfs_log_set_handler(ntfs_log_handler *handler)
        } else
                ntfs_log.handler = ntfs_log_handler_null;
 }
+#endif //__HAIKU___
 
 /**
  * ntfs_log_redirect - Pass on the request to the real handler
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
index 4fcf4c1..2ff3306 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c
@@ -1112,7 +1112,7 @@ static int upgrade_secur_desc(ntfs_volume *vol,
  *     Should not be called for user root, however the group may be root
  *
  */
-
+#ifndef __HAIKU__
 static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t 
gid)
 {
        BOOL ingroup;
@@ -1134,6 +1134,7 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT 
*scx, uid_t uid, gid_t gid
        }
        return (ingroup);
 }
+#endif //__HAIKU__
 
 #if defined(__sun) && defined (__SVR4)
 

############################################################################

Revision:    hrev46483
Commit:      5287b8a778715de8320fe2bd932ceab5c185cc41
URL:         http://cgit.haiku-os.org/haiku/commit/?id=5287b8a
Author:      Gerasim Troeglazov <3dEyes@xxxxxxxxx>
Date:        Wed Dec  4 12:44:02 2013 UTC

ntfs: Directory position must be signed

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h 
b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h
index 2fa305c..0b47031 100644
--- a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h
+++ b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h
@@ -31,7 +31,7 @@ typedef struct cache_entry {
 
 
 typedef struct dircookie {
-       u64                                     pos;
+       s64                                     pos;
        dev_t                           dev_id;
        BOOL                            show_sys_files;
        cache_entry             *cache_root;


Other related posts: