[haiku-commits] haiku: hrev52407 - src/add-ons/kernel/file_systems/ntfs/libntfs

  • From: waddlesplash@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 17 Oct 2018 18:06:03 -0400 (EDT)

hrev52407 adds 4 changesets to branch 'master'
old head: 4124da508abbc4a28fbc23dd0f1ee88d5e805941
new head: 7deac31935900b7be3a61ad06b7924b2153dbfbc
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=7deac3193590+%5E4124da508abb

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

c053e48f87dd: freebsd11_network: intr_wrapper method does return handled 
information.
  
  Probably this was a copy/paste error from the "FAST_INTR" method
  which did not return handled information (and was removed in FreeBSD ~8.)
  Note that this is a *major* change, as our interrupt scheduling system
  puts "no handling information" interrupts last, and so it's possible
  this unbreaks some of the more esoteric chipsets.
  
  But it's also possible that our interrupts glue code for some of the
  drivers is incorrect, and so this will break other devices on the same
  interrupt line. Please test carefully.

0490778ed1bf: NTFS: Update libntfs from 2014.2.15 to 2017.3.23.
  
  I rewrote the "config.h" at the same time, which enables usage of gettimeofday
  and some other API functions we didn't have whenever this port was first done,
  enabling more accurate timestamp handling, among other things.

e39df8a97c6b: bios_ia32: Remove some extra debug info.

7deac3193590: interface: Fix -Wuninitialized in RegionSupport.
  
  Also trim trailing spaces...

                              [ Augustin Cavalier <waddlesplash@xxxxxxxxx> ]

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

54 files changed, 3789 insertions(+), 1554 deletions(-)
src/add-ons/kernel/file_systems/ntfs/Jamfile     |   5 -
.../kernel/file_systems/ntfs/libntfs/Jamfile     |   1 +
.../kernel/file_systems/ntfs/libntfs/acls.c      | 323 +++++++----
.../kernel/file_systems/ntfs/libntfs/acls.h      |  32 +-
.../kernel/file_systems/ntfs/libntfs/attrib.c    | 319 +++++++----
.../kernel/file_systems/ntfs/libntfs/attrib.h    |   7 +
.../kernel/file_systems/ntfs/libntfs/attrlist.c  |   8 +-
.../kernel/file_systems/ntfs/libntfs/bootsect.c  |   6 +-
.../kernel/file_systems/ntfs/libntfs/compat.h    |   6 +-
.../kernel/file_systems/ntfs/libntfs/compress.c  | 472 +++++++++------
.../kernel/file_systems/ntfs/libntfs/config.h    | 364 ++++++++----
.../kernel/file_systems/ntfs/libntfs/device.c    |  15 +-
.../kernel/file_systems/ntfs/libntfs/device_io.h |   2 +-
.../kernel/file_systems/ntfs/libntfs/dir.c       | 176 +++---
.../kernel/file_systems/ntfs/libntfs/dir.h       |  10 +-
.../kernel/file_systems/ntfs/libntfs/ea.c        | 395 +++++++++++++
.../kernel/file_systems/ntfs/libntfs/ea.h        |  33 ++
.../kernel/file_systems/ntfs/libntfs/efs.c       |  17 +-
.../kernel/file_systems/ntfs/libntfs/endians.h   | 116 +++-
.../kernel/file_systems/ntfs/libntfs/index.c     |  37 +-
.../kernel/file_systems/ntfs/libntfs/index.h     |   1 +
.../kernel/file_systems/ntfs/libntfs/inode.c     |  38 +-
.../kernel/file_systems/ntfs/libntfs/inode.h     |   2 +-
.../kernel/file_systems/ntfs/libntfs/ioctl.c     | 388 +++++++++++++
.../kernel/file_systems/ntfs/libntfs/ioctl.h     |  30 +
.../kernel/file_systems/ntfs/libntfs/layout.h    | 457 +++++++--------
.../kernel/file_systems/ntfs/libntfs/lcnalloc.c  |   2 +-
.../kernel/file_systems/ntfs/libntfs/logfile.c   |  12 +-
.../kernel/file_systems/ntfs/libntfs/logfile.h   | 160 ++++--
.../kernel/file_systems/ntfs/libntfs/logging.c   |  54 +-
.../kernel/file_systems/ntfs/libntfs/logging.h   |   7 +-
.../kernel/file_systems/ntfs/libntfs/mft.c       | 101 +++-
.../kernel/file_systems/ntfs/libntfs/mft.h       |   2 +
.../kernel/file_systems/ntfs/libntfs/mst.c       |  64 ++-
.../kernel/file_systems/ntfs/libntfs/ntfstime.h  |   2 +-
.../kernel/file_systems/ntfs/libntfs/object_id.c |  16 +-
.../kernel/file_systems/ntfs/libntfs/param.h     |  44 +-
.../kernel/file_systems/ntfs/libntfs/plugin.h    | 141 +++++
.../kernel/file_systems/ntfs/libntfs/reparse.c   |  79 ++-
.../kernel/file_systems/ntfs/libntfs/reparse.h   |   6 +-
.../kernel/file_systems/ntfs/libntfs/runlist.c   |  63 +-
.../kernel/file_systems/ntfs/libntfs/security.c  | 387 +++++++++----
.../kernel/file_systems/ntfs/libntfs/security.h  |  35 +-
.../kernel/file_systems/ntfs/libntfs/types.h     |  14 +-
.../kernel/file_systems/ntfs/libntfs/unistr.c    | 573 +++++++++++++------
.../kernel/file_systems/ntfs/libntfs/unistr.h    |   4 +-
.../kernel/file_systems/ntfs/libntfs/volume.c    | 127 ++--
.../kernel/file_systems/ntfs/libntfs/volume.h    |   5 +-
.../kernel/file_systems/ntfs/libntfs/win32_io.c  |  35 +-
.../kernel/file_systems/ntfs/libntfs/xattrs.c    |  23 +-
.../kernel/file_systems/ntfs/libntfs/xattrs.h    |  28 +-
src/kits/interface/RegionSupport.cpp             |  96 ++--
src/libs/compat/freebsd11_network/bus.cpp        |   2 +-
src/system/boot/platform/bios_ia32/Jamfile       |   1 -

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

Commit:      c053e48f87ddb79db754199eea18585d41f38788
URL:         https://git.haiku-os.org/haiku/commit/?id=c053e48f87dd
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Wed Oct 17 21:09:38 2018 UTC

freebsd11_network: intr_wrapper method does return handled information.

Probably this was a copy/paste error from the "FAST_INTR" method
which did not return handled information (and was removed in FreeBSD ~8.)
Note that this is a *major* change, as our interrupt scheduling system
puts "no handling information" interrupts last, and so it's possible
this unbreaks some of the more esoteric chipsets.

But it's also possible that our interrupts glue code for some of the
drivers is incorrect, and so this will break other devices on the same
interrupt line. Please test carefully.

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

diff --git a/src/libs/compat/freebsd11_network/bus.cpp 
b/src/libs/compat/freebsd11_network/bus.cpp
index 7bda24aec5..7524ef3585 100644
--- a/src/libs/compat/freebsd11_network/bus.cpp
+++ b/src/libs/compat/freebsd11_network/bus.cpp
@@ -369,7 +369,7 @@ bus_setup_intr(device_t dev, struct resource *res, int 
flags,
                }
 
                status = install_io_interrupt_handler(intr->irq,
-                       intr_wrapper, intr, B_NO_HANDLED_INFO);
+                       intr_wrapper, intr, 0);
        }
 
        if (status == B_OK && res->r_bustag == 1 && gPCIx86 != NULL) {

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

Commit:      0490778ed1bf2e39eb9d9ea8d62a2b0ab378fecd
URL:         https://git.haiku-os.org/haiku/commit/?id=0490778ed1bf
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Wed Oct 17 21:46:55 2018 UTC

NTFS: Update libntfs from 2014.2.15 to 2017.3.23.

I rewrote the "config.h" at the same time, which enables usage of gettimeofday
and some other API functions we didn't have whenever this port was first done,
enabling more accurate timestamp handling, among other things.

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

diff --git a/src/add-ons/kernel/file_systems/ntfs/Jamfile 
b/src/add-ons/kernel/file_systems/ntfs/Jamfile
index 315370dd5a..aa82fec037 100644
--- a/src/add-ons/kernel/file_systems/ntfs/Jamfile
+++ b/src/add-ons/kernel/file_systems/ntfs/Jamfile
@@ -27,12 +27,7 @@ KernelAddon ntfs :
        libntfs.a
        ;
 
-SEARCH on [ FGristFiles
-               kernel_cpp.cpp
-       ] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
-
 SEARCH on [ FGristFiles mime_ext_table.c ]
        += [ FDirName $(HAIKU_TOP) src add-ons kernel file_systems shared ] ;
 
 SubInclude HAIKU_TOP src add-ons kernel file_systems ntfs libntfs ;
-
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/Jamfile 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/Jamfile
index 3cc7cd8413..423a451a1f 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/Jamfile
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/Jamfile
@@ -15,6 +15,7 @@ KernelStaticLibrary libntfs.a :
        debug.c
        device.c
        dir.c
+       ea.c
        efs.c
        index.c
        inode.c
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 76599b4ada..98d8067e57 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-2012 Jean-Pierre Andre
+ * Copyright (c) 2007-2016 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
@@ -22,10 +22,6 @@
  * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef HAVE_CONFIG_H
-                               /*
-                                * integration into ntfs-3g
-                                */
 #include "config.h"
 
 #ifdef HAVE_STDIO_H
@@ -53,65 +49,18 @@
 #include <pwd.h>
 #include <grp.h>
 
+#ifdef __HAIKU__
+#define getgrgid(a) NULL
+#define getpwuid(a) NULL
+#define getgrnam(x) NULL
+#define getpwnam(x) NULL
+#endif
+
 #include "types.h"
 #include "layout.h"
 #include "security.h"
 #include "acls.h"
 #include "misc.h"
-#else
-
-                               /*
-                                * integration into secaudit, check whether 
Win32,
-                                * may have to be adapted to compiler or 
something else
-                                */
-
-#ifndef WIN32
-#if defined(__WIN32) | defined(__WIN32__) | defined(WNSC)
-#define WIN32 1
-#endif
-#endif
-
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <errno.h>
-
-                               /*
-                                * integration into secaudit/Win32
-                                */
-#ifdef WIN32
-#include <fcntl.h>
-#include <windows.h>
-#define __LITTLE_ENDIAN 1234
-#define __BYTE_ORDER __LITTLE_ENDIAN
-#else
-                               /*
-                                * integration into secaudit/STSC
-                                */
-#ifdef STSC
-#include <stat.h>
-#undef __BYTE_ORDER
-#define __BYTE_ORDER __BIG_ENDIAN
-#else
-                               /*
-                                * integration into secaudit/Linux
-                                */
-#include <sys/stat.h>
-#include <endian.h>
-#include <unistd.h>
-#include <dlfcn.h>
-#endif /* STSC */
-#endif /* WIN32 */
-#include "secaudit.h"
-#endif /* HAVE_CONFIG_H */
-
-#ifdef __HAIKU__
-#define getgrnam(x) NULL
-#define getpwnam(x) NULL
-#endif
 
 /*
  *     A few useful constants
@@ -141,6 +90,8 @@ static const char worldsidbytes[] = {
                0, 0, 0, 0      /* 1st level */
 } ;
 
+const SID *worldsid = (const SID*)worldsidbytes;
+
 /*
  *             SID for authenticated user (S-1-5-11)
  */
@@ -149,12 +100,10 @@ static const char authsidbytes[] = {
                1,              /* revision */
                1,              /* auth count */
                0, 0, 0, 0, 0, 5,       /* base */
-               11, 0, 0, 0     /* 1st level */ 
+               11, 0, 0, 0     /* 1st level */
 };
-               
-static const SID *authsid = (const SID*)authsidbytes;
 
-const SID *worldsid = (const SID*)worldsidbytes;
+static const SID *authsid = (const SID*)authsidbytes;
 
 /*
  *             SID for administrator
@@ -235,7 +184,11 @@ BOOL ntfs_same_sid(const SID *first, const SID *second)
 
 /*
  *             Test whether a SID means "world user"
- *     Local users group also recognized as world
+ *     Local users group recognized as world
+ *     Also interactive users so that /Users/Public is world accessible,
+ *     but only if Posix ACLs are not enabled (if Posix ACLs are enabled,
+ *     access to /Users/Public should be done by defining interactive users
+ *     as a mapped group.)
  */
 
 static int is_world_sid(const SID * usid)
@@ -259,6 +212,14 @@ static int is_world_sid(const SID * usid)
            && (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)))
+
+#if !POSIXACLS
+            /* check whether S-1-5-4 : interactive 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(4)))
+#endif /* !POSIXACLS */
                );
 }
 
@@ -276,6 +237,25 @@ BOOL ntfs_is_user_sid(const SID *usid)
            && (usid->sub_authority[0] ==  const_cpu_to_le32(21)));
 }
 
+/*
+ *             Test whether a SID means "some special group"
+ *     Currently we only check for a few S-1-5-n but we should
+ *     probably test for other configurations.
+ *
+ *     This is useful for granting access to /Users/Public for
+ *     specific users when the Posix ACLs are enabled.
+ */
+
+static BOOL ntfs_known_group_sid(const SID *usid)
+{
+                       /* count == 1 excludes S-1-5-5-X-Y (logon) */
+       return ((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))
+           && (le32_to_cpu(usid->sub_authority[0]) >=  1)
+           && (le32_to_cpu(usid->sub_authority[0]) <=  6));
+}
+
 /*
  *             Determine the size of a security attribute
  *     whatever the order of fields
@@ -336,16 +316,18 @@ unsigned int ntfs_attr_size(const char *attr)
        return (attrsz);
 }
 
-/*
- *             Do sanity checks on a SID read from storage
- *     (just check revision and number of authorities)
+/**
+ * ntfs_valid_sid - determine if a SID is valid
+ * @sid:       SID for which to determine if it is valid
+ *
+ * Determine if the SID pointed to by @sid is valid.
+ *
+ * Return TRUE if it is valid and FALSE otherwise.
  */
-
 BOOL ntfs_valid_sid(const SID *sid)
 {
-       return ((sid->revision == SID_REVISION)
-               && (sid->sub_authority_count >= 1)
-               && (sid->sub_authority_count <= 8));
+       return sid && sid->revision == SID_REVISION &&
+               sid->sub_authority_count <= SID_MAX_SUB_AUTHORITIES;
 }
 
 /*
@@ -571,6 +553,7 @@ static BOOL valid_acl(const ACL *pacl, unsigned int end)
        unsigned int acecnt;
        unsigned int acesz;
        unsigned int nace;
+       unsigned int wantsz;
        BOOL ok;
 
        ok = TRUE;
@@ -585,9 +568,16 @@ static BOOL valid_acl(const ACL *pacl, unsigned int end)
                                &((const char*)pacl)[offace];
                        acesz = le16_to_cpu(pace->size);
                        if (((offace + acesz) > end)
-                          || !ntfs_valid_sid(&pace->sid)
-                          || ((ntfs_sid_size(&pace->sid) + 8) != (int)acesz))
+                          || !ntfs_valid_sid(&pace->sid))
                                 ok = FALSE;
+                       else {
+                               /* Win10 may insert garbage in the last ACE */
+                               wantsz = ntfs_sid_size(&pace->sid) + 8;
+                               if (((nace < (acecnt - 1))
+                                       && (wantsz != acesz))
+                                   || (wantsz > acesz))
+                                       ok = FALSE;
+                       }
                        offace += acesz;
                }
        }
@@ -703,8 +693,10 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
        const ACCESS_ALLOWED_ACE *poldace;
        ACCESS_ALLOWED_ACE *pnewace;
        ACCESS_ALLOWED_ACE *pauthace;
+       ACCESS_ALLOWED_ACE *pownerace;
 
        pauthace = (ACCESS_ALLOWED_ACE*)NULL;
+       pownerace = (ACCESS_ALLOWED_ACE*)NULL;
        usidsz = ntfs_sid_size(usid);
        gsidsz = ntfs_sid_size(gsid);
 
@@ -722,12 +714,24 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + 
src);
                acesz = le16_to_cpu(poldace->size);
                src += acesz;
-                       /*
-                        * Inheritance for access, unless this is inheriting
-                        * an inherited ACL to a directory.
-                        */
+               /*
+                * Extract inheritance for access, including inheritance for
+                * access from an ACE with is both applied and inheritable.
+                *
+                * must not output OBJECT_INHERIT_ACE or CONTAINER_INHERIT_ACE
+                *
+                *      According to MSDN :
+                * "For a case in which a container object inherits an ACE
+                * "that is both effective on the container and inheritable
+                * "by its descendants, the container may inherit two ACEs.
+                * "This occurs if the inheritable ACE contains generic
+                * "information."
+                */
                if ((poldace->flags & selection)
-                   && !(fordir && inherited)
+                   && (!fordir
+                       || (poldace->flags & NO_PROPAGATE_INHERIT_ACE)
+                       || (poldace->mask & (GENERIC_ALL | GENERIC_READ
+                                       | GENERIC_WRITE | GENERIC_EXECUTE)))
                    && !ntfs_same_sid(&poldace->sid, ownersid)
                    && !ntfs_same_sid(&poldace->sid, groupsid)) {
                        pnewace = (ACCESS_ALLOWED_ACE*)
@@ -750,7 +754,7 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                                                        | FILE_READ
                                                        | FILE_WRITE
                                                        | FILE_EXEC
-                                                       | cpu_to_le32(0x40);
+                                                       | 
const_cpu_to_le32(0x40);
                        }
                                /* reencode GENERIC_READ (+ EXECUTE) */
                        if (pnewace->mask & GENERIC_READ) {
@@ -790,8 +794,7 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                         * Group similar ACE for authenticated users
                         * (should probably be done for other SIDs)
                         */
-                       if (!fordir
-                           && (poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+                       if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
                            && ntfs_same_sid(&poldace->sid, authsid)) {
                                if (pauthace) {
                                        pauthace->flags |= pnewace->flags;
@@ -834,8 +837,14 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                                                | INHERIT_ONLY_ACE);
                                if (inherited)
                                        pnewace->flags |= INHERITED_ACE;
-                               dst += usidsz + 8;
-                               newcnt++;
+                               if ((pnewace->type == ACCESS_ALLOWED_ACE_TYPE)
+                                   && pownerace
+                                   && !(pnewace->flags & ~pownerace->flags)) {
+                                       pownerace->mask |= pnewace->mask;
+                               } else {
+                                       dst += usidsz + 8;
+                                       newcnt++;
+                               }
                        }
                        if (ntfs_same_sid(&pnewace->sid, groupsid)) {
                                memcpy(&pnewace->sid, gsid, gsidsz);
@@ -851,15 +860,52 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl,
                        }
                }
 
-                       /* inheritance for further inheritance */
+                       /*
+                        * inheritance for further inheritance
+                        *
+                        * Situations leading to output CONTAINER_INHERIT_ACE
+                        *      or OBJECT_INHERIT_ACE
+                        */
                if (fordir
                   && (poldace->flags
                           & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) {
                        pnewace = (ACCESS_ALLOWED_ACE*)
                                        ((char*)newacl + dst);
                        memcpy(pnewace,poldace,acesz);
+                       if ((poldace->flags & OBJECT_INHERIT_ACE)
+                          && !(poldace->flags & (CONTAINER_INHERIT_ACE
+                                       | NO_PROPAGATE_INHERIT_ACE)))
+                               pnewace->flags |= INHERIT_ONLY_ACE;
+                       if ((poldace->flags & CONTAINER_INHERIT_ACE)
+                           && !(poldace->flags & NO_PROPAGATE_INHERIT_ACE)
+                           && !ntfs_same_sid(&poldace->sid, ownersid)
+                           && !ntfs_same_sid(&poldace->sid, groupsid)) {
+                               if ((poldace->mask & (GENERIC_ALL | GENERIC_READ
+                                       | GENERIC_WRITE | GENERIC_EXECUTE)))
+                                       pnewace->flags |= INHERIT_ONLY_ACE;
+                               else
+                                       pnewace->flags &= ~INHERIT_ONLY_ACE;
+                       }
                        if (inherited)
                                pnewace->flags |= INHERITED_ACE;
+                       /*
+                        * Prepare grouping similar ACE for authenticated users
+                        */
+                       if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+                           && !pauthace
+                           && !(pnewace->flags & INHERIT_ONLY_ACE)
+                           && ntfs_same_sid(&poldace->sid, authsid)) {
+                               pauthace = pnewace;
+                       }
+                       /*
+                        * Prepare grouping similar ACE for owner
+                        */
+                       if ((poldace->type == ACCESS_ALLOWED_ACE_TYPE)
+                           && !pownerace
+                           && !(pnewace->flags & INHERIT_ONLY_ACE)
+                           && ntfs_same_sid(&poldace->sid, usid)) {
+                               pownerace = pnewace;
+                       }
                        dst += acesz;
                        newcnt++;
                }
@@ -980,7 +1026,7 @@ BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc)
                }
        }
        if ((pxdesc->acccnt > 0)
-          && ((checks[0].owners != 1) || (checks[0].groups != 1) 
+          && ((checks[0].owners != 1) || (checks[0].groups != 1)
                || (checks[0].others != 1)))
                ok = FALSE;
                /* do not check owner, group or other are present in */
@@ -1221,6 +1267,45 @@ struct POSIX_SECURITY *ntfs_replace_acl(const struct 
POSIX_SECURITY *oldpxdesc,
        return (newpxdesc);
 }
 
+/*
+ *             Build a basic Posix ACL from a mode and umask,
+ *     ignoring inheritance from the parent directory
+ */
+
+struct POSIX_SECURITY *ntfs_build_basic_posix(
+               const struct POSIX_SECURITY *pxdesc __attribute__((unused)),
+               mode_t mode, mode_t mask, BOOL isdir __attribute__((unused)))
+{
+       struct POSIX_SECURITY *pydesc;
+       struct POSIX_ACE *pyace;
+
+       pydesc = (struct POSIX_SECURITY*)malloc(
+               sizeof(struct POSIX_SECURITY) + 3*sizeof(struct POSIX_ACE));
+       if (pydesc) {
+               pyace = &pydesc->acl.ace[0];
+               pyace->tag = POSIX_ACL_USER_OBJ;
+               pyace->perms = ((mode & ~mask) >> 6) & 7;
+               pyace->id = -1;
+               pyace = &pydesc->acl.ace[1];
+               pyace->tag = POSIX_ACL_GROUP_OBJ;
+               pyace->perms = ((mode & ~mask) >> 3) & 7;
+               pyace->id = -1;
+               pyace = &pydesc->acl.ace[2];
+               pyace->tag = POSIX_ACL_OTHER;
+               pyace->perms = (mode & ~mask) & 7;
+               pyace->id = -1;
+               pydesc->mode = mode;
+               pydesc->tagsset = POSIX_ACL_USER_OBJ
+                               | POSIX_ACL_GROUP_OBJ
+                               | POSIX_ACL_OTHER;
+               pydesc->acccnt = 3;
+               pydesc->defcnt = 0;
+               pydesc->firstdef = 6;
+       } else
+               errno = ENOMEM;
+       return (pydesc);
+}
+
 /*
  *             Build an inherited Posix descriptor from parent
  *     descriptor (if any) restricted to creation mode
@@ -1515,7 +1600,7 @@ static BOOL build_user_denials(ACL *pacl,
                grants = OWNER_RIGHTS;
        } else {
                if (pxace->id) {
-                       sid = NTFS_FIND_USID(mapping[MAPUSERS],
+                       sid = ntfs_find_usid(mapping[MAPUSERS],
                                pxace->id, (SID*)&defsid);
                        grants = WORLD_RIGHTS;
                } else {
@@ -1671,7 +1756,7 @@ static BOOL build_user_grants(ACL *pacl,
                grants = OWNER_RIGHTS;
        } else {
                if (pxace->id) {
-                       sid = NTFS_FIND_USID(mapping[MAPUSERS],
+                       sid = ntfs_find_usid(mapping[MAPUSERS],
                                pxace->id, (SID*)&defsid);
                        if (sid)
                                sidsz = ntfs_sid_size(sid);
@@ -1757,7 +1842,7 @@ static BOOL build_group_denials_grant(ACL *pacl,
                sid = gsid;
        else
                if (pxace->id)
-                       sid = NTFS_FIND_GSID(mapping[MAPGROUPS],
+                       sid = ntfs_find_gsid(mapping[MAPGROUPS],
                                pxace->id, (SID*)&defsid);
                else {
                        sid = adminsid;
@@ -1906,7 +1991,7 @@ static BOOL build_group_denials_grant(ACL *pacl,
  *     - grants to owner (always present - first grant)
  *        + grants to designated user
  *        + mask denial to group (unless mask allows all)
- *     - denials to group (preventing grants to world to apply) 
+ *     - denials to group (preventing grants to world to apply)
  *     - grants to group (unless group has no more than world rights)
  *        + mask denials to designated group (unless mask allows all)
  *        + grants to designated group
@@ -2062,7 +2147,7 @@ static int buildacls_posix(struct MAPPING* const 
mapping[],
                case POSIX_ACL_USER :
                        pset->designates++;
                        if (pxace->id) {
-                               sid = NTFS_FIND_USID(mapping[MAPUSERS],
+                               sid = ntfs_find_usid(mapping[MAPUSERS],
                                        pxace->id, (SID*)&defsid);
                                if (sid && ntfs_same_sid(sid,usid))
                                        pset->selfuserperms |= pxace->perms;
@@ -2073,7 +2158,7 @@ static int buildacls_posix(struct MAPPING* const 
mapping[],
                case POSIX_ACL_GROUP :
                        pset->designates++;
                        if (pxace->id) {
-                               sid = NTFS_FIND_GSID(mapping[MAPUSERS],
+                               sid = ntfs_find_gsid(mapping[MAPUSERS],
                                        pxace->id, (SID*)&defsid);
                                if (sid && ntfs_same_sid(sid,gsid))
                                        pset->selfgrpperms |= pxace->perms;
@@ -2193,10 +2278,21 @@ return (0);
                                        mapping,flags,pxace,pset);
                        break;
 
-               case POSIX_ACL_GROUP :
                case POSIX_ACL_GROUP_OBJ :
+                       /* denials and grants for group when needed */
+                       if (pset->groupowns && !pset->adminowns
+                           && (pset->grpperms == pset->othperms)
+                           && !pset->designates && !pset->withmask) {
+                               ok = TRUE;
+                       } else {
+                               ok = build_group_denials_grant(pacl,gsid,
+                                               mapping,flags,pxace,pset);
+                       }
+                       break;
 
-                       /* denials and grants for groups */
+               case POSIX_ACL_GROUP :
+
+                       /* denials and grants for designated groups */
 
                        ok = build_group_denials_grant(pacl,gsid,
                                        mapping,flags,pxace,pset);
@@ -2453,7 +2549,6 @@ static int buildacls(char *secattr, int offs, mode_t 
mode, int isdir,
        /* this ACE will be inserted after denials for group */
 
        if (adminowns
-           || groupowns
            || (((mode >> 3) ^ mode) & 7)) {
                grants = WORLD_RIGHTS;
                if (isdir) {
@@ -2657,10 +2752,10 @@ char *ntfs_build_descr_posix(struct MAPPING* const 
mapping[],
        for (k=0; k<pxdesc->acccnt; k++) {
                if ((pxdesc->acl.ace[k].tag == POSIX_ACL_USER)
                    || (pxdesc->acl.ace[k].tag == POSIX_ACL_GROUP))
-                       newattrsz += 3*40; /* fixme : maximum size */
+                       newattrsz += 3*MAX_SID_SIZE;
        }
                                /* account for default ACE's */
-       newattrsz += 2*40*pxdesc->defcnt;  /* fixme : maximum size */
+       newattrsz += 2*MAX_SID_SIZE*pxdesc->defcnt;
        newattr = (char*)ntfs_malloc(newattrsz);
        if (newattr) {
                /* build the main header part */
@@ -3514,7 +3609,7 @@ static uid_t find_tenant(struct MAPPING *const mapping[],
                pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace];
                if ((pace->type == ACCESS_ALLOWED_ACE_TYPE)
                   && (pace->mask & DIR_WRITE)) {
-                       xid = NTFS_FIND_USER(mapping[MAPUSERS], &pace->sid);
+                       xid = ntfs_find_user(mapping[MAPUSERS], &pace->sid);
                        if (xid) tid = xid;
                }
                offace += le16_to_cpu(pace->size);
@@ -3649,13 +3744,13 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                                } else {
                                        if (ntfs_same_sid(&pace->sid,usid))
                                                groupowns = TRUE;
-                                       gid = 
NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+                                       gid = 
ntfs_find_group(mapping[MAPGROUPS],&pace->sid);
                                        if (gid) {
                                                pxace->tag = POSIX_ACL_GROUP;
                                                pxace->id = gid;
                                                pctx->prevgid = gid;
                                        } else {
-                                       uid = 
NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+                                       uid = 
ntfs_find_user(mapping[MAPUSERS],&pace->sid);
                                        if (uid) {
                                                pxace->tag = POSIX_ACL_USER;
                                                pxace->id = uid;
@@ -3678,7 +3773,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                                        if (pace->type == 
ACCESS_ALLOWED_ACE_TYPE)
                                                pctx->gotowner = TRUE;
                                        if (pctx->gotownermask && 
!pctx->gotowner) {
-                                               uid = 
NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+                                               uid = 
ntfs_find_user(mapping[MAPUSERS],&pace->sid);
                                                pxace->id = uid;
                                                pxace->tag = POSIX_ACL_USER;
                                        } else
@@ -3710,7 +3805,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                                        pctx->groupmasks++;
                        } else {
                                if (pctx->gotgroup || (pctx->groupmasks > 1)) {
-                                       gid = 
NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+                                       gid = 
ntfs_find_group(mapping[MAPGROUPS],&pace->sid);
                                        if (gid) {
                                                pxace->id = gid;
                                                pxace->tag = POSIX_ACL_GROUP;
@@ -3744,7 +3839,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                        pxace->id = -1;
                        pxace->tag = POSIX_ACL_SPECIAL;
                } else {
-                       uid = NTFS_FIND_USER(mapping[MAPUSERS],&pace->sid);
+                       uid = ntfs_find_user(mapping[MAPUSERS],&pace->sid);
                        if (uid) {
                                if ((pace->type == ACCESS_DENIED_ACE_TYPE)
                                    && (pace->mask & WRITE_OWNER)
@@ -3757,7 +3852,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
                                }
                                pctx->prevuid = uid;
                        } else {
-                               gid = 
NTFS_FIND_GROUP(mapping[MAPGROUPS],&pace->sid);
+                               gid = 
ntfs_find_group(mapping[MAPGROUPS],&pace->sid);
                                if (gid) {
                                        if ((pace->type == 
ACCESS_DENIED_ACE_TYPE)
                                            && (pace->mask & WRITE_OWNER)
@@ -4005,7 +4100,7 @@ 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 ! */
        unsigned long v;
@@ -4015,7 +4110,6 @@ static unsigned long atoul(const char *p)
                v = v * 10 + (*p++) - '0';
        return (v);
 }
-#endif
 
 /*
  *             Build an internal representation of a SID
@@ -4050,7 +4144,8 @@ static SID *encodesid(const char *sidstr)
                        cnt++;
                }
                bsid->sub_authority_count = cnt;
-               if ((cnt > 0) && ntfs_valid_sid(bsid) && 
ntfs_is_user_sid(bsid)) {
+               if ((cnt > 0) && ntfs_valid_sid(bsid)
+                   && (ntfs_is_user_sid(bsid) || ntfs_known_group_sid(bsid))) {
                        sid = (SID*) ntfs_malloc(4 * cnt + 8);
                        if (sid)
                                memcpy(sid, bsid, 4 * cnt + 8);
@@ -4259,6 +4354,12 @@ struct MAPPING *ntfs_do_user_mapping(struct MAPLIST 
*firstitem)
                if (uid
                   || (!item->uidstr[0] && !item->gidstr[0])) {
                        sid = encodesid(item->sidstr);
+                       if (sid && ntfs_known_group_sid(sid)) {
+                               ntfs_log_error("Bad user SID %s\n",
+                                       item->sidstr);
+                               free(sid);
+                               sid = (SID*)NULL;
+                       }
                        if (sid && !item->uidstr[0] && !item->gidstr[0]
                            && !ntfs_valid_pattern(sid)) {
                                ntfs_log_error("Bad implicit SID pattern %s\n",
@@ -4351,7 +4452,15 @@ struct MAPPING *ntfs_do_group_mapping(struct MAPLIST 
*firstitem)
                                        if (mapping) {
                                                mapping->sid = sid;
                                                mapping->xid = gid;
-                                               mapping->grcnt = 0;
+                                       /* special groups point to themselves */
+                                               if (ntfs_known_group_sid(sid)) {
+                                                       mapping->groups =
+                                                         (gid_t*)&mapping->xid;
+                                                       mapping->grcnt = 1;
+                                               } else
+                                                       mapping->grcnt = 0;
+
+
                                                mapping->next = (struct 
MAPPING*)NULL;
                                                if (lastmapping)
                                                        lastmapping->next = 
mapping;
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 4b0838867d..932791e972 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h
@@ -24,6 +24,8 @@
 #ifndef ACLS_H
 #define ACLS_H
 
+#include "endians.h"
+
 /*
  *     JPA configuration modes for security.c / acls.c
  *     should be moved to some config file
@@ -35,28 +37,6 @@
 #define CACHE_PERMISSIONS_BITS 6  /* log2 of unitary allocation of permissions 
*/
 #define CACHE_PERMISSIONS_SIZE 262144 /* max cacheable permissions */
 
-/*
- *     JPA The following must be in some library...
- *     but did not found out where
- */
-
-#define endian_rev16(x) (((x >> 8) & 255) | ((x & 255) << 8))
-#define endian_rev32(x) (((x >> 24) & 255) | ((x >> 8) & 0xff00) \
-               | ((x & 0xff00) << 8) | ((x & 255) << 24))
-
-#define cpu_to_be16(x) endian_rev16(cpu_to_le16(x))
-#define cpu_to_be32(x) endian_rev32(cpu_to_le32(x))
-
-/*
- *             Macro definitions needed to share code with secaudit
- */
-
-#define NTFS_FIND_USID(map,uid,buf) ntfs_find_usid(map,uid,buf)
-#define NTFS_FIND_GSID(map,gid,buf) ntfs_find_gsid(map,gid,buf)
-#define NTFS_FIND_USER(map,usid) ntfs_find_user(map,usid)
-#define NTFS_FIND_GROUP(map,gsid) ntfs_find_group(map,gsid)
-
-
 /*
  *             Matching of ntfs permissions to Linux permissions
  *     these constants are adapted to endianness
@@ -112,10 +92,11 @@
 #define ROOT_GROUP_UNMARK FILE_READ_EA /* ACL granted to root as group */
 
 /*
- *             A type large enough to hold any SID
+ *             Maximum SID size and a type large enough to hold it
  */
 
-typedef char BIGSID[40];
+#define MAX_SID_SIZE (8 + SID_MAX_SUB_AUTHORITIES*4)
+typedef char BIGSID[MAX_SID_SIZE];
 
 /*
  *             Struct to hold the input mapping file
@@ -170,6 +151,9 @@ int ntfs_merge_mode_posix(struct POSIX_SECURITY *pxdesc, 
mode_t mode);
 struct POSIX_SECURITY *ntfs_build_inherited_posix(
                const struct POSIX_SECURITY *pxdesc, mode_t mode,
                mode_t umask, BOOL isdir);
+struct POSIX_SECURITY *ntfs_build_basic_posix(
+               const struct POSIX_SECURITY *pxdesc, mode_t mode,
+               mode_t umask, BOOL isdir);
 struct POSIX_SECURITY *ntfs_replace_acl(const struct POSIX_SECURITY *oldpxdesc,
                const struct POSIX_ACL *newacl, int count, BOOL deflt);
 struct POSIX_SECURITY *ntfs_build_permissions_posix(
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 1a9ef372be..30a8e9cf8a 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c
@@ -5,7 +5,7 @@
  * Copyright (c) 2002-2005 Richard Russon
  * Copyright (c) 2002-2008 Szabolcs Szakacsits
  * Copyright (c) 2004-2007 Yura Pakhuchiy
- * Copyright (c) 2007-2013 Jean-Pierre Andre
+ * Copyright (c) 2007-2015 Jean-Pierre Andre
  * Copyright (c) 2010      Erik Larsson
  *
  * This program/include file is free software; you can redistribute it and/or
@@ -96,7 +96,7 @@ static void NAttrSetFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
                na->ni->flags |= flag;
        else
                ntfs_log_trace("Denied setting flag %d for not unnamed data "
-                              "attribute\n", flag);
+                              "attribute\n", le32_to_cpu(flag));
 }
 
 static void NAttrClearFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
@@ -405,7 +405,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES 
type,
        le16 cs;
 
        ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n",
-                      (unsigned long long)ni->mft_no, type);
+                      (unsigned long long)ni->mft_no, le32_to_cpu(type));
        
        if (!ni || !ni->vol || !ni->mrec) {
                errno = EINVAL;
@@ -452,7 +452,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES 
type,
         * does not detect or fix them so we need to cope with it, too.
         */
        if (type == AT_ATTRIBUTE_LIST)
-               a->flags = 0;
+               a->flags = const_cpu_to_le16(0);
 
        if ((type == AT_DATA)
           && (a->non_resident ? !a->initialized_size : !a->value_length)) {
@@ -484,7 +484,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES 
type,
                errno = EIO;
                ntfs_log_perror("Inode %lld has corrupt attribute flags "
                                "(0x%x <> 0x%x)",(unsigned long long)ni->mft_no,
-                               a->flags, na->ni->flags);
+                               le16_to_cpu(a->flags), 
le32_to_cpu(na->ni->flags));
                goto put_err_out;
        }
 
@@ -494,7 +494,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES 
type,
                        errno = EIO;
                        ntfs_log_perror("Compressed inode %lld attr 0x%x has "
                                        "no compression unit",
-                                       (unsigned long long)ni->mft_no, type);
+                                       (unsigned long long)ni->mft_no, 
le32_to_cpu(type));
                        goto put_err_out;
                }
                ntfs_attr_init(na, TRUE, a->flags,
@@ -561,7 +561,7 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
        ntfs_attr_search_ctx *ctx;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn 0x%llx.\n",
-               (unsigned long long)na->ni->mft_no, na->type, (long long)vcn);
+               (unsigned long long)na->ni->mft_no, le32_to_cpu(na->type), 
(long long)vcn);
 
        lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
        if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
@@ -601,22 +601,19 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
 
 static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
 {
-       LCN lcn;
        VCN last_vcn;
        VCN highest_vcn;
        VCN needed;
-       VCN existing_vcn;
        runlist_element *rl;
        ATTR_RECORD *a;
        BOOL startseen;
        ntfs_attr_search_ctx *ctx;
+       BOOL done;
+       BOOL newrunlist;
 
-       lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
-       if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
+       if (NAttrFullyMapped(na))
                return 0;
 
-       existing_vcn = (na->rl ? na->rl->vcn : -1);
-
        ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
        if (!ctx)
                return -1;
@@ -627,37 +624,56 @@ static int ntfs_attr_map_partial_runlist(ntfs_attr *na, 
VCN vcn)
        needed = vcn;
        highest_vcn = 0;
        startseen = FALSE;
+       done = FALSE;
+       rl = (runlist_element*)NULL;
        do {
+               newrunlist = FALSE;
                /* Find the attribute in the mft record. */
                if (!ntfs_attr_lookup(na->type, na->name, na->name_len, 
CASE_SENSITIVE,
                                needed, NULL, 0, ctx)) {
 
                        a = ctx->attr;
-                       /* Decode and merge the runlist. */
-                       rl = ntfs_mapping_pairs_decompress(na->ni->vol, a,
-                                       na->rl);
+                               /* Decode and merge the runlist. */
+                       if (ntfs_rl_vcn_to_lcn(na->rl, needed)
+                                               == LCN_RL_NOT_MAPPED) {
+                               rl = ntfs_mapping_pairs_decompress(na->ni->vol,
+                                       a, na->rl);
+                               newrunlist = TRUE;
+                       } else
+                               rl = na->rl;
                        if (rl) {
                                na->rl = rl;
-                               highest_vcn = le64_to_cpu(a->highest_vcn);
-                               /* corruption detection */
-                               if (((highest_vcn + 1) < last_vcn)
-                                   && ((highest_vcn + 1) <= needed)) {
-                                       ntfs_log_error("Corrupt attribute 
list\n");
-                                       rl = (runlist_element*)NULL;
+                               highest_vcn = sle64_to_cpu(a->highest_vcn);
+                               if (highest_vcn < needed) {
+                               /* corruption detection on unchanged runlists */
+                                       if (newrunlist
+                                           && ((highest_vcn + 1) < last_vcn)) {
+                                               ntfs_log_error("Corrupt 
attribute list\n");
+                                               rl = (runlist_element*)NULL;
+                                               errno = EIO;
+                                       }
+                                       done = TRUE;
                                }
                                needed = highest_vcn + 1;
                                if (!a->lowest_vcn)
                                        startseen = TRUE;
-                               /* reaching a previously allocated part ? */
-                               if ((existing_vcn >= 0)
-                                   && (needed >= existing_vcn)) {
-                                       needed = last_vcn;
-                               }
                        }
-               } else
-                       rl = (runlist_element*)NULL;
-       } while (rl && (needed < last_vcn));
+               } else {
+                       done = TRUE;
+               }
+       } while (rl && !done && (needed < last_vcn));
        ntfs_attr_put_search_ctx(ctx);
+               /*
+                * Make sure we reached the end, unless the last
+                * runlist was modified earlier (using HOLES_DELAY
+                * leads to have a visibility over attributes which
+                * have not yet been fully updated)
+                */
+       if (done && newrunlist && (needed < last_vcn)) {
+               ntfs_log_error("End of runlist not reached\n");
+               rl = (runlist_element*)NULL;
+               errno = EIO;
+       }
                /* mark fully mapped if we did so */
        if (rl && startseen)
                NAttrSetFullyMapped(na);
@@ -685,9 +701,10 @@ int ntfs_attr_map_whole_runlist(ntfs_attr *na)
        ntfs_volume *vol = na->ni->vol;
        ATTR_RECORD *a;
        int ret = -1;
+       int not_mapped;
 
        ntfs_log_enter("Entering for inode %llu, attr 0x%x.\n",
-                      (unsigned long long)na->ni->mft_no, na->type);
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type));
 
                /* avoid multiple full runlist mappings */
        if (NAttrFullyMapped(na)) {
@@ -704,7 +721,7 @@ int ntfs_attr_map_whole_runlist(ntfs_attr *na)
        while (1) {
                runlist_element *rl;
 
-               int not_mapped = 0;
+               not_mapped = 0;
                if (ntfs_rl_vcn_to_lcn(na->rl, next_vcn) == LCN_RL_NOT_MAPPED)
                        not_mapped = 1;
 
@@ -759,7 +776,13 @@ int ntfs_attr_map_whole_runlist(ntfs_attr *na)
                ntfs_log_perror("Couldn't find attribute for runlist mapping");
                goto err_out;
        }
-       if (highest_vcn && highest_vcn != last_vcn - 1) {
+               /*
+                * Cannot check highest_vcn when the last runlist has
+                * been modified earlier, as runlists and sizes may be
+                * updated without highest_vcn being in sync, when
+                * HOLES_DELAY is used
+                */
+       if (not_mapped && highest_vcn && highest_vcn != last_vcn - 1) {
                errno = EIO;
                ntfs_log_perror("Failed to load full runlist: inode: %llu "
                                "highest_vcn: 0x%llx last_vcn: 0x%llx",
@@ -808,7 +831,7 @@ LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn)
                return (LCN)LCN_EINVAL;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
-                       long)na->ni->mft_no, na->type);
+                       long)na->ni->mft_no, le32_to_cpu(na->type));
 retry:
        /* Convert vcn to lcn. If that fails map the runlist and retry once. */
        lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
@@ -860,7 +883,7 @@ runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const 
VCN vcn)
        }
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, vcn %llx\n",
-                      (unsigned long long)na->ni->mft_no, na->type,
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                       (long long)vcn);
 retry:
        rl = na->rl;
@@ -1017,7 +1040,7 @@ res_err_out:
                                count--;
                                total2++;
                        } else {
-                               *(u16*)((u8*)b+count-2) = 
cpu_to_le16(efs_padding_length);
+                               *(le16*)((u8*)b+count-2) = 
cpu_to_le16(efs_padding_length);
                                count -= 2;
                                total2 +=2;
                        }
@@ -1153,7 +1176,7 @@ s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 
count, void *b)
        
        ntfs_log_enter("Entering for inode %lld attr 0x%x pos %lld count "
                       "%lld\n", (unsigned long long)na->ni->mft_no,
-                      na->type, (long long)pos, (long long)count);
+                      le32_to_cpu(na->type), (long long)pos, (long long)count);
 
        ret = ntfs_attr_pread_i(na, pos, count, b);
        
@@ -1244,19 +1267,15 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 
count, s64 *ofs,
         
        /* Map the runlist to be able to update mapping pairs later. */
 #if PARTIAL_RUNLIST_UPDATING
-       if ((!na->rl
-           || !NAttrDataAppending(na))) {
+       if (!na->rl) {
                if (ntfs_attr_map_whole_runlist(na))
                        goto err_out;
        } else {
-               /* make sure the previous non-hole is mapped */
-               rlc = *rl;
-               rlc--;
-               if (((*rl)->lcn == LCN_HOLE)
-                   && cur_vcn
-                   && (rlc->vcn < 0)) {
-                       if (ntfs_attr_map_partial_runlist(na, cur_vcn - 1))
-                               goto err_out;
+               /* make sure the run ahead of hole is mapped */
+               if ((*rl)->lcn == LCN_HOLE) {
+                       if (ntfs_attr_map_partial_runlist(na,
+                               (cur_vcn ? cur_vcn - 1 : cur_vcn)))
+                                       goto err_out;
                }
        }
 #else
@@ -1343,6 +1362,7 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, 
s64 *ofs,
                na->compressed_size += need << vol->cluster_size_bits;
        
        *rl = ntfs_runlists_merge(na->rl, rlc);
+       NAttrSetRunlistDirty(na);
                /*
                 * For a compressed attribute, we must be sure there are two
                 * available entries, so reserve them before it gets too late.
@@ -1572,6 +1592,7 @@ ntfs_log_error("No free run, case 4\n");
                                rl = ++(*prl);
                        }
                }
+       NAttrSetRunlistDirty(na);
        if ((*update_from == -1) || ((*prl)->vcn < *update_from))
                *update_from = (*prl)->vcn;
        }
@@ -1708,6 +1729,7 @@ static int borrow_from_hole(ntfs_attr *na, 
runlist_element **prl,
                                zrl->length = endblock - allocated;
                                zrl[1].length -= zrl->length;
                                zrl[1].vcn = zrl->vcn + zrl->length;
+                               NAttrSetRunlistDirty(na);
                        }
                }
                if (*prl) {
@@ -1758,7 +1780,8 @@ static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 
newsize,
  * appropriately to the return code of ntfs_pwrite(), or to EINVAL in case of
  * invalid arguments.
  */
-s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
+static s64 ntfs_attr_pwrite_i(ntfs_attr *na, const s64 pos, s64 count,
+                                                               const void *b)
 {
        s64 written, to_write, ofs, old_initialized_size, old_data_size;
        s64 total = 0;
@@ -1776,17 +1799,7 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 
count, const void *b)
        } need_to = { 0, 0 };
        BOOL wasnonresident = FALSE;
        BOOL compressed;
-       BOOL updatemap;
 
-       ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
-                      "0x%llx.\n", (long long)na->ni->mft_no, na->type,
-                      (long long)pos, (long long)count);
-       
-       if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
-               errno = EINVAL;
-               ntfs_log_perror("%s", __FUNCTION__);
-               goto errno_set;
-       }
        vol = na->ni->vol;
        compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
                         != const_cpu_to_le16(0);
@@ -1931,8 +1944,17 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 
count, const void *b)
                 * However, for compressed file, we need the full compression
                 * block, which may be split in several extents.
                 */
-               if (NAttrDataAppending(na)) {
-                       VCN block_begin = pos >> vol->cluster_size_bits;
+               if (compressed && !NAttrDataAppending(na)) {
+                       if (ntfs_attr_map_whole_runlist(na))
+                               goto err_out;
+               } else {
+                       VCN block_begin;
+
+                       if (NAttrDataAppending(na)
+                           || (pos < na->initialized_size))
+                               block_begin = pos >> vol->cluster_size_bits;
+                       else
+                               block_begin = na->initialized_size >> 
vol->cluster_size_bits;
 
                        if (compressed)
                                block_begin &= -na->compression_block_clusters;
@@ -1942,10 +1964,11 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 
count, const void *b)
                                goto err_out;
                        if ((update_from == -1) || (block_begin < update_from))
                                update_from = block_begin;
-               } else
-#endif
+               }
+#else
                        if (ntfs_attr_map_whole_runlist(na))
                                goto err_out;
+#endif
                /*
                 * For a compressed attribute, we must be sure there is an
                 * available entry, and, when reopening a compressed file,
@@ -2192,7 +2215,7 @@ retry:
                                } else
                                        written = ntfs_pwrite(vol->dev, wpos,
                                                to_write, b);
-                               }
+                       }
                } else
                        written = to_write;
                /* If everything ok, update progress counters and continue. */
@@ -2222,13 +2245,7 @@ done:
                 * of the mapping list. This makes a difference only if
                 * inode extents were needed.
                 */
-#if PARTIAL_RUNLIST_UPDATING
-       updatemap = NAttrFullyMapped(na) || NAttrDataAppending(na);
-#else
-       updatemap = (compressed
-                       ? NAttrFullyMapped(na) != 0 : update_from != -1);
-#endif
-       if (updatemap) {
+       if (NAttrRunlistDirty(na)) {
                if (ntfs_attr_update_mapping_pairs(na,
                                (update_from < 0 ? 0 : update_from))) {
                        /*
@@ -2243,7 +2260,6 @@ done:
                NAttrClearDataAppending(na);
        }
 out:   
-       ntfs_log_leave("\n");
        return total;
 rl_err_out:
        eo = errno;
@@ -2298,9 +2314,7 @@ err_out:
        if (ctx)
                ntfs_attr_put_search_ctx(ctx);
        /* Update mapping pairs if needed. */
-       updatemap = (compressed
-                       ? NAttrFullyMapped(na) != 0 : update_from != -1);
-       if (updatemap)
+       if (NAttrRunlistDirty(na))
                ntfs_attr_update_mapping_pairs(na, 0);
        /* Restore original data_size if needed. */
        if (need_to.undo_data_size
@@ -2312,6 +2326,39 @@ errno_set:
        goto out;
 }
 
+s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
+{
+       s64 total;
+       s64 written;
+
+       ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
+                      "0x%llx.\n", (long long)na->ni->mft_no, 
le32_to_cpu(na->type),
+                      (long long)pos, (long long)count);
+       
+       total = 0;
+       if (!na || !na->ni || !na->ni->vol || !b || pos < 0 || count < 0) {
+               errno = EINVAL;
+               written = -1;
+               ntfs_log_perror("%s", __FUNCTION__);
+               goto out;
+       }
+
+               /*
+                * Compressed attributes may be written partially, so
+                * we may have to iterate.
+                */
+       do {
+               written = ntfs_attr_pwrite_i(na, pos + total,
+                               count - total, (const u8*)b + total);
+               if (written > 0)
+                       total += written;
+       } while ((written > 0) && (total < count));
+out :
+       ntfs_log_leave("\n");
+       return (total > 0 ? total : written);
+}
+
+
 int ntfs_attr_pclose(ntfs_attr *na)
 {
        s64 ofs;
@@ -2326,7 +2373,8 @@ int ntfs_attr_pclose(ntfs_attr *na)
        BOOL compressed;
 
        ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x.\n",
-                       na->ni->mft_no, na->type);
+                       (unsigned long long)na->ni->mft_no,
+                       le32_to_cpu(na->type));
        
        if (!na || !na->ni || !na->ni->vol) {
                errno = EINVAL;
@@ -2545,7 +2593,7 @@ s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, 
const s64 bk_cnt,
        BOOL warn;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 
0x%llx.\n",
-                       (unsigned long long)na->ni->mft_no, na->type,
+                       (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                        (long long)pos);
        if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
                errno = EINVAL;
@@ -2601,7 +2649,7 @@ s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos, 
s64 bk_cnt,
        s64 written, i;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 
0x%llx.\n",
-                       (unsigned long long)na->ni->mft_no, na->type,
+                       (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                        (long long)pos);
        if (bk_cnt < 0 || bk_size % NTFS_BLOCK_SIZE) {
                errno = EINVAL;
@@ -2719,7 +2767,7 @@ static int ntfs_attr_find(const ATTR_TYPES type, const 
ntfschar *name,
        ntfschar *upcase;
        u32 upcase_len;
 
-       ntfs_log_trace("attribute type 0x%x.\n", type);
+       ntfs_log_trace("attribute type 0x%x.\n", le32_to_cpu(type));
 
        if (ctx->ntfs_ino) {
                vol = ctx->ntfs_ino->vol;
@@ -2944,7 +2992,7 @@ static int ntfs_external_attr_find(ATTR_TYPES type, const 
ntfschar *name,
        ni = ctx->ntfs_ino;
        base_ni = ctx->base_ntfs_ino;
        ntfs_log_trace("Entering for inode %lld, attribute type 0x%x.\n",
-                       (unsigned long long)ni->mft_no, type);
+                       (unsigned long long)ni->mft_no, le32_to_cpu(type));
        if (!base_ni) {
                /* First call happens with the base mft record. */
                base_ni = ctx->base_ntfs_ino = ctx->ntfs_ino;
@@ -3327,7 +3375,7 @@ int ntfs_attr_lookup(const ATTR_TYPES type, const 
ntfschar *name,
        ntfs_inode *base_ni;
        int ret = -1;
 
-       ntfs_log_enter("Entering for attribute type 0x%x\n", type);
+       ntfs_log_enter("Entering for attribute type 0x%x\n", le32_to_cpu(type));
        
        if (!ctx || !ctx->mrec || !ctx->attr || (name && name != AT_UNNAMED &&
                        (!ctx->ntfs_ino || !(vol = ctx->ntfs_ino->vol) ||
@@ -3495,7 +3543,7 @@ ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume 
*vol,
 
        if (!vol || !vol->attrdef || !type) {
                errno = EINVAL;
-               ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
+               ntfs_log_perror("%s: type=%d", __FUNCTION__, le32_to_cpu(type));
                return NULL;
        }
        for (ad = vol->attrdef; (u8*)ad - (u8*)vol->attrdef <
@@ -3510,7 +3558,7 @@ ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume 
*vol,
                break;
        }
        errno = ENOENT;
-       ntfs_log_perror("%s: type=%d", __FUNCTION__, type);
+       ntfs_log_perror("%s: type=%d", __FUNCTION__, le32_to_cpu(type));
        return NULL;
 }
 
@@ -3571,7 +3619,7 @@ int ntfs_attr_size_bounds_check(const ntfs_volume *vol, 
const ATTR_TYPES type,
            ((max_size > 0) && (size > max_size))) {
                errno = ERANGE;
                ntfs_log_perror("Attr type %d size check failed (min,size,max="
-                       "%lld,%lld,%lld)", type, (long long)min_size,
+                       "%lld,%lld,%lld)", le32_to_cpu(type), (long 
long)min_size,
                        (long long)size, (long long)max_size);
                return -1;
        }
@@ -3751,7 +3799,7 @@ int ntfs_resident_attr_record_add(ntfs_inode *ni, 
ATTR_TYPES type,
        ntfs_inode *base_ni;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, flags 0x%x.\n",
-               (long long) ni->mft_no, (unsigned) type, (unsigned) data_flags);
+               (long long) ni->mft_no, (unsigned) le32_to_cpu(type), 
(unsigned) le16_to_cpu(data_flags));
 
        if (!ni || (!name && name_len)) {
                errno = EINVAL;
@@ -3805,7 +3853,7 @@ int ntfs_resident_attr_record_add(ntfs_inode *ni, 
ATTR_TYPES type,
        a->non_resident = 0;
        a->name_length = name_len;
        a->name_offset = (name_len
-               ? cpu_to_le16(offsetof(ATTR_RECORD, resident_end))
+               ? const_cpu_to_le16(offsetof(ATTR_RECORD, resident_end))
                : const_cpu_to_le16(0));
        a->flags = data_flags;
        a->instance = m->next_attr_instance;
@@ -3884,8 +3932,8 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, 
ATTR_TYPES type,
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn %lld, "
                        "dataruns_size %d, flags 0x%x.\n",
-                       (long long) ni->mft_no, (unsigned) type,
-                       (long long) lowest_vcn, dataruns_size, (unsigned) 
flags);
+                       (long long) ni->mft_no, (unsigned) le32_to_cpu(type),
+                       (long long) lowest_vcn, dataruns_size, (unsigned) 
le16_to_cpu(flags));
 
        if (!ni || dataruns_size <= 0 || (!name && name_len)) {
                errno = EINVAL;
@@ -3912,7 +3960,7 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, 
ATTR_TYPES type,
        if (!ntfs_attr_find(type, name, name_len, CASE_SENSITIVE, NULL, 0,
                        ctx)) {
                err = EEXIST;
-               ntfs_log_perror("Attribute 0x%x already present", type);
+               ntfs_log_perror("Attribute 0x%x already present", 
le32_to_cpu(type));
                goto put_err_out;
        }
        if (errno != ENOENT) {
@@ -3951,10 +3999,10 @@ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, 
ATTR_TYPES type,
                        ? STANDARD_COMPRESSION_UNIT : 0;
        /* If @lowest_vcn == 0, than setup empty attribute. */
        if (!lowest_vcn) {
-               a->highest_vcn = cpu_to_sle64(-1);
-               a->allocated_size = 0;
-               a->data_size = 0;
-               a->initialized_size = 0;
+               a->highest_vcn = const_cpu_to_sle64(-1);
+               a->allocated_size = const_cpu_to_sle64(0);
+               a->data_size = const_cpu_to_sle64(0);
+               a->initialized_size = const_cpu_to_sle64(0);
                /* Set empty mapping pairs. */
                *((u8*)a + le16_to_cpu(a->mapping_pairs_offset)) = 0;
        }
@@ -4173,7 +4221,7 @@ int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
        }
 
        ntfs_log_trace("Entering for inode %lld, attr %x, size %lld.\n",
-                       (long long)ni->mft_no, type, (long long)size);
+                       (long long)ni->mft_no, le32_to_cpu(type), (long 
long)size);
 
        if (ni->nr_extents == -1)
                ni = ni->base_ni;
@@ -4395,7 +4443,7 @@ int ntfs_attr_rm(ntfs_attr *na)
        }
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n",
-               (long long) na->ni->mft_no, na->type);
+               (long long) na->ni->mft_no, le32_to_cpu(na->type));
 
        /* Free cluster allocation. */
        if (NAttrNonResident(na)) {
@@ -4743,7 +4791,7 @@ int ntfs_attr_make_non_resident(ntfs_attr *na,
        int mp_size, mp_ofs, name_ofs, arec_size, err;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
-                       long)na->ni->mft_no, na->type);
+                       long)na->ni->mft_no, le32_to_cpu(na->type));
 
        /* Some preliminary sanity checking. */
        if (NAttrNonResident(na)) {
@@ -4851,7 +4899,7 @@ int ntfs_attr_make_non_resident(ntfs_attr *na,
        a->name_offset = cpu_to_le16(name_ofs);
 
        /* Setup the fields specific to non-resident attributes. */
-       a->lowest_vcn = cpu_to_sle64(0);
+       a->lowest_vcn = const_cpu_to_sle64(0);
        a->highest_vcn = cpu_to_sle64((new_allocated_size - 1) >>
                                                vol->cluster_size_bits);
 
@@ -4868,7 +4916,7 @@ int ntfs_attr_make_non_resident(ntfs_attr *na,
        if ((a->flags & ATTR_COMPRESSION_MASK) == ATTR_IS_COMPRESSED) {
                        /* support only ATTR_IS_COMPRESSED compression mode */
                a->compression_unit = STANDARD_COMPRESSION_UNIT;
-               a->compressed_size = const_cpu_to_le64(0);
+               a->compressed_size = const_cpu_to_sle64(0);
        } else {
                a->compression_unit = 0;
                a->flags &= ~ATTR_COMPRESSION_MASK;
@@ -4937,7 +4985,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, 
const s64 newsize,
        int err, ret = STATUS_ERROR;
 
        ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n", 
-                      (unsigned long long)na->ni->mft_no, na->type, 
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                       (long long)newsize);
 
        /* Get the attribute record that needs modification. */
@@ -5094,6 +5142,10 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, 
const s64 newsize,
         */
        if (na->type==AT_STANDARD_INFORMATION || na->type==AT_ATTRIBUTE_LIST) {
                ntfs_attr_put_search_ctx(ctx);
+               if (!NInoAttrList(na->ni) && ntfs_inode_add_attrlist(na->ni)) {
+                       ntfs_log_perror("Could not add attribute list");
+                       return -1;
+               }
                if (ntfs_inode_free_space(na->ni, offsetof(ATTR_RECORD,
                                non_resident_end) + 8)) {
                        ntfs_log_perror("Could not free space in MFT record");
@@ -5240,7 +5292,7 @@ static int ntfs_attr_make_resident(ntfs_attr *na, 
ntfs_attr_search_ctx *ctx)
        s64 arec_size, bytes_read;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x.\n", (unsigned long
-                       long)na->ni->mft_no, na->type);
+                       long)na->ni->mft_no, le32_to_cpu(na->type));
 
        /* Should be called for the first extent of the attribute. */
        if (sle64_to_cpu(a->lowest_vcn)) {
@@ -5314,7 +5366,7 @@ static int ntfs_attr_make_resident(ntfs_attr *na, 
ntfs_attr_search_ctx *ctx)
 
        /* Convert the attribute record to describe a resident attribute. */
        a->non_resident = 0;
-       a->flags = 0;
+       a->flags = const_cpu_to_le16(0);
        a->value_length = cpu_to_le32(na->data_size);
        a->value_offset = cpu_to_le16(val_ofs);
        /*
@@ -5402,7 +5454,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, 
ntfs_attr *na, MFT_RECORD *m,
        int sparse, ret = 0;
        
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x\n", 
-                      (unsigned long long)na->ni->mft_no, na->type);
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type));
        
        if (a->lowest_vcn)
                goto out;
@@ -5545,7 +5597,7 @@ retry:
        }
 
        ntfs_log_trace("Entering for inode %llu, attr 0x%x\n", 
-                      (unsigned long long)na->ni->mft_no, na->type);
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type));
 
        if (!NAttrNonResident(na)) {
                errno = EINVAL;
@@ -5847,8 +5899,12 @@ retry:
                        ntfs_log_perror("%s: get mp size failed", __FUNCTION__);
                        goto put_err_out;
                }
-               /* Allocate new mft record. */
-               ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
+               /* Allocate new mft record, with special case for mft itself */
+               if (!na->ni->mft_no)
+                       ni = ntfs_mft_rec_alloc(na->ni->vol,
+                               na->type == AT_DATA);
+               else
+                       ni = ntfs_mft_record_alloc(na->ni->vol, base_ni);
                if (!ni) {
                        ntfs_log_perror("Could not allocate new MFT record");
                        goto put_err_out;
@@ -5903,6 +5959,7 @@ retry:
                        break;
        }
 ok:
+       NAttrClearRunlistDirty(na);
        ret = 0;
 out:
        return ret;
@@ -5969,7 +6026,7 @@ static int ntfs_non_resident_attr_shrink(ntfs_attr *na, 
const s64 newsize)
        int err;
 
        ntfs_log_trace("Inode 0x%llx attr 0x%x new size %lld\n", (unsigned long 
long)
-                      na->ni->mft_no, na->type, (long long)newsize);
+                      na->ni->mft_no, le32_to_cpu(na->type), (long 
long)newsize);
 
        vol = na->ni->vol;
 
@@ -6030,6 +6087,7 @@ static int ntfs_non_resident_attr_shrink(ntfs_attr *na, 
const s64 newsize)
                        ntfs_log_trace("Eeek! Run list truncation failed.\n");
                        return -1;
                }
+               NAttrSetRunlistDirty(na);
 
                /* Prepare to mapping pairs update. */
                na->allocated_size = first_free_vcn << vol->cluster_size_bits;
@@ -6080,7 +6138,8 @@ static int ntfs_non_resident_attr_shrink(ntfs_attr *na, 
const s64 newsize)
 
        /* If the attribute now has zero size, make it resident. */
        if (!newsize) {
-               if (ntfs_attr_make_resident(na, ctx)) {
+               if (!(na->data_flags & ATTR_IS_ENCRYPTED)
+                   && ntfs_attr_make_resident(na, ctx)) {
                        /* If couldn't make resident, just continue. */
                        if (errno != EPERM)
                                ntfs_log_error("Failed to make attribute "
@@ -6125,7 +6184,7 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, 
const s64 newsize,
        int err;
 
        ntfs_log_trace("Inode %lld, attr 0x%x, new size %lld old size %lld\n",
-                       (unsigned long long)na->ni->mft_no, na->type,
+                       (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                        (long long)newsize, (long long)na->data_size);
 
        vol = na->ni->vol;
@@ -6245,6 +6304,7 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, 
const s64 newsize,
                        return -1;
                }
                na->rl = rln;
+               NAttrSetRunlistDirty(na);
 
                /* Prepare to mapping pairs update. */
                na->allocated_size = first_free_vcn << vol->cluster_size_bits;
@@ -6330,6 +6390,7 @@ rollback:
                na->rl = NULL;
                ntfs_log_perror("Couldn't truncate runlist. Rollback failed");
        } else {
+               NAttrSetRunlistDirty(na);
                /* Prepare to mapping pairs update. */
                na->allocated_size = org_alloc_size;
                /* Restore mapping pairs. */
@@ -6394,7 +6455,7 @@ static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 
newsize,
        }
 
        ntfs_log_enter("Entering for inode %lld, attr 0x%x, size %lld\n",
-                      (unsigned long long)na->ni->mft_no, na->type, 
+                      (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                       (long long)newsize);
 
        if (na->data_size == newsize) {
@@ -6406,7 +6467,7 @@ static int ntfs_attr_truncate_i(ntfs_attr *na, const s64 
newsize,
         * Encrypted attributes are not supported. We return access denied,
         * which is what Windows NT4 does, too.
         */
-       if (na->data_flags & ATTR_IS_ENCRYPTED) {
+       if ((na->data_flags & ATTR_IS_ENCRYPTED) && !na->ni->vol->efs_raw) {
                errno = EACCES;
                ntfs_log_trace("Cannot truncate encrypted attribute\n");
                goto out;
@@ -6703,6 +6764,42 @@ exit:
        return res;
 }
 
+/*
+ *             Shrink the size of a data attribute if needed
+ *
+ *     For non-resident attributes only.
+ *     The space remains allocated.
+ *
+ *     Returns 0 if successful
+ *             -1 if failed, with errno telling why
+ */
+
+
+int ntfs_attr_shrink_size(ntfs_inode *ni, ntfschar *stream_name,
+               int stream_name_len, off_t offset)
+{
+       ntfs_attr_search_ctx *ctx;
+       ATTR_RECORD *a;
+       int res;
+
+       res = -1;
+       ctx = ntfs_attr_get_search_ctx(ni, NULL);
+       if (ctx) {
+               if (!ntfs_attr_lookup(AT_DATA, stream_name, stream_name_len,
+                       CASE_SENSITIVE, 0, NULL, 0, ctx)) {
+                       a = ctx->attr;
+
+                       if (a->non_resident
+                           && (sle64_to_cpu(a->initialized_size) > offset)) {
+                               a->initialized_size = cpu_to_sle64(offset);
+                               a->data_size = a->initialized_size;
+                       }
+                       res = 0;
+               }
+               ntfs_attr_put_search_ctx(ctx);
+       }
+       return (res);
+}
 
 int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, const ntfschar 
*name,
                    u32 name_len)
@@ -6743,7 +6840,7 @@ int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES 
type, ntfschar *name,
                        /* do not log removal of non-existent stream */
                if (type != AT_DATA) {
                        ntfs_log_perror("Failed to open attribute 0x%02x of 
inode "
-                               "0x%llx", type, (unsigned long long)ni->mft_no);
+                               "0x%llx", le32_to_cpu(type), (unsigned long 
long)ni->mft_no);
                }
                return -1;
        }
@@ -6751,7 +6848,7 @@ int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES 
type, ntfschar *name,
        ret = ntfs_attr_rm(na);
        if (ret)
                ntfs_log_perror("Failed to remove attribute 0x%02x of inode "
-                               "0x%llx", type, (unsigned long long)ni->mft_no);
+                               "0x%llx", le32_to_cpu(type), (unsigned long 
long)ni->mft_no);
        ntfs_attr_close(na);
        
        return ret;
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 a0bee2652a..b3752a608b 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h
@@ -211,6 +211,7 @@ typedef enum {
        NA_FullyMapped,         /* 1: Attribute has been fully mapped */
        NA_DataAppending,       /* 1: Attribute is being appended to */
        NA_ComprClosing,        /* 1: Compressed attribute is being closed */
+       NA_RunlistDirty,        /* 1: Runlist has been updated */
 } ntfs_attr_state_bits;
 
 #define  test_nattr_flag(na, flag)      test_bit(NA_##flag, (na)->state)
@@ -237,6 +238,10 @@ typedef enum {
 #define NAttrSetDataAppending(na)      set_nattr_flag(na, DataAppending)
 #define NAttrClearDataAppending(na)    clear_nattr_flag(na, DataAppending)
 
+#define NAttrRunlistDirty(na)          test_nattr_flag(na, RunlistDirty)
+#define NAttrSetRunlistDirty(na)       set_nattr_flag(na, RunlistDirty)
+#define NAttrClearRunlistDirty(na)     clear_nattr_flag(na, RunlistDirty)
+
 #define NAttrComprClosing(na)          test_nattr_flag(na, ComprClosing)
 #define NAttrSetComprClosing(na)       set_nattr_flag(na, ComprClosing)
 #define NAttrClearComprClosing(na)     clear_nattr_flag(na, ComprClosing)
@@ -391,6 +396,8 @@ extern int ntfs_attr_data_read(ntfs_inode *ni,
 extern int ntfs_attr_data_write(ntfs_inode *ni,
                ntfschar *stream_name, int stream_name_len,
                const char *buf, size_t size, off_t offset);
+extern int ntfs_attr_shrink_size(ntfs_inode *ni, ntfschar *stream_name,
+               int stream_name_len, off_t offset);
 
 #endif /* defined _NTFS_ATTRIB_H */
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrlist.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrlist.c
index 9c62f31614..29d4085980 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrlist.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrlist.c
@@ -107,7 +107,7 @@ int ntfs_attrlist_need(ntfs_inode *ni)
 int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD *attr)
 {
        ATTR_LIST_ENTRY *ale;
-       MFT_REF mref;
+       leMFT_REF mref;
        ntfs_attr *na = NULL;
        ntfs_attr_search_ctx *ctx;
        u8 *new_al;
@@ -150,7 +150,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD 
*attr)
        if (!ntfs_attr_lookup(attr->type, (attr->name_length) ? (ntfschar*)
                        ((u8*)attr + le16_to_cpu(attr->name_offset)) :
                        AT_UNNAMED, attr->name_length, CASE_SENSITIVE,
-                       (attr->non_resident) ? le64_to_cpu(attr->lowest_vcn) :
+                       (attr->non_resident) ? sle64_to_cpu(attr->lowest_vcn) :
                        0, (attr->non_resident) ? NULL : ((u8*)attr +
                        le16_to_cpu(attr->value_offset)), (attr->non_resident) ?
                        0 : le32_to_cpu(attr->value_length), ctx)) {
@@ -193,7 +193,7 @@ int ntfs_attrlist_entry_add(ntfs_inode *ni, ATTR_RECORD 
*attr)
        if (attr->non_resident)
                ale->lowest_vcn = attr->lowest_vcn;
        else
-               ale->lowest_vcn = 0;
+               ale->lowest_vcn = const_cpu_to_sle64(0);
        ale->mft_reference = mref;
        ale->instance = attr->instance;
        memcpy(ale->name, (u8 *)attr + le16_to_cpu(attr->name_offset),
@@ -265,7 +265,7 @@ int ntfs_attrlist_entry_rm(ntfs_attr_search_ctx *ctx)
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, lowest_vcn 
%lld.\n",
                        (long long) ctx->ntfs_ino->mft_no,
                        (unsigned) le32_to_cpu(ctx->al_entry->type),
-                       (long long) le64_to_cpu(ctx->al_entry->lowest_vcn));
+                       (long long) sle64_to_cpu(ctx->al_entry->lowest_vcn));
 
        if (!NInoAttrList(base_ni)) {
                ntfs_log_trace("Attribute list isn't present.\n");
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 e9be072d0a..e185fe3fec 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c
@@ -65,7 +65,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
        ntfs_log_debug("Beginning bootsector check.\n");
 
        ntfs_log_debug("Checking OEMid, NTFS signature.\n");
-       if (b->oem_id != cpu_to_le64(0x202020205346544eULL)) { /* "NTFS    " */
+       if (b->oem_id != const_cpu_to_le64(0x202020205346544eULL)) { /* "NTFS   
 " */
                ntfs_log_error("NTFS signature is missing.\n");
                goto not_ntfs;
        }
@@ -140,7 +140,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
                }
        }
 
-       if (b->end_of_sector_marker != cpu_to_le16(0xaa55))
+       if (b->end_of_sector_marker != const_cpu_to_le16(0xaa55))
                ntfs_log_debug("Warning: Bootsector has invalid end of sector "
                               "marker.\n");
 
@@ -204,7 +204,7 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const 
NTFS_BOOT_SECTOR *bs)
                                  (sectors - 1) << vol->sector_size_bits,
                                  SEEK_SET) == -1) {
                ntfs_log_perror("Failed to read last sector (%lld)",
-                               (long long)sectors);
+                               (long long)(sectors - 1));
                ntfs_log_error("%s", last_sector_error);
                return -1;
        }
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 cc84670f88..ded6c5f853 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h
@@ -37,6 +37,10 @@
 #define ENODATA ENOENT
 #endif
 
+#ifndef ELIBBAD
+#define ELIBBAD ENOEXEC
+#endif
+
 #ifndef PATH_MAX
 #define PATH_MAX 4096
 #endif
@@ -65,11 +69,9 @@ extern char *strsep(char **stringp, const char *delim);
 
 #else /* !defined WINDOWS */
 
-#ifndef __HAIKU__
 #ifndef O_BINARY
 #define O_BINARY               0               /* unix is binary by default */
 #endif
-#endif
 
 #endif /* defined WINDOWS */
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/compress.c 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/compress.c
index 69b39ed09b..2c0c260a14 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/compress.c
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/compress.c
@@ -5,7 +5,8 @@
  * Copyright (c) 2004-2005 Anton Altaparmakov
  * Copyright (c) 2004-2006 Szabolcs Szakacsits
  * Copyright (c)      2005 Yura Pakhuchiy
- * Copyright (c) 2009-2013 Jean-Pierre Andre
+ * Copyright (c) 2009-2014 Jean-Pierre Andre
+ * Copyright (c)      2014 Eric Biggers
  *
  * 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
@@ -21,17 +22,6 @@
  * 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
- *
- * A part of the compression algorithm is based on lzhuf.c whose header
- * describes the roles of the original authors (with no apparent copyright
- * notice, and according to http://home.earthlink.net/~neilbawd/pall.html
- * this was put into public domain in 1988 by Haruhiko OKUMURA).
- *
- * LZHUF.C English version 1.0
- * Based on Japanese version 29-NOV-1988   
- * LZSS coded by Haruhiko OKUMURA
- * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
- * Edited and translated to English by Kenji RIKITAKE
  */
 
 #ifdef HAVE_CONFIG_H
@@ -81,96 +71,191 @@ typedef enum {
        NTFS_SB_IS_COMPRESSED   =       0x8000,
 } ntfs_compression_constants;
 
+/* Match length at or above which ntfs_best_match() will stop searching for
+ * longer matches.  */
+#define NICE_MATCH_LEN 18
+
+/* Maximum number of potential matches that ntfs_best_match() will consider at
+ * each position.  */
+#define MAX_SEARCH_DEPTH 24
+
+/* log base 2 of the number of entries in the hash table for match-finding.  */
+#define HASH_SHIFT 14
+
+/* Constant for the multiplicative hash function.  */
+#define HASH_MULTIPLIER 0x1E35A7BD
+
 struct COMPRESS_CONTEXT {
        const unsigned char *inbuf;
        int bufsize;
        int size;
        int rel;
        int mxsz;
-       s16 head[256];
-       s16 lson[NTFS_SB_SIZE];
-       s16 rson[NTFS_SB_SIZE];
+       s16 head[1 << HASH_SHIFT];
+       s16 prev[NTFS_SB_SIZE];
 } ;
 
+/*
+ *             Hash the next 3-byte sequence in the input buffer
+ */
+static inline unsigned int ntfs_hash(const u8 *p)
+{
+       u32 str;
+       u32 hash;
+
+#if defined(__i386__) || defined(__x86_64__)
+       /* Unaligned access allowed, and little endian CPU.
+        * Callers ensure that at least 4 (not 3) bytes are remaining.  */
+       str = *(const u32 *)p & 0xFFFFFF;
+#else
+       str = ((u32)p[0] << 0) | ((u32)p[1] << 8) | ((u32)p[2] << 16);
+#endif
+
+       hash = str * HASH_MULTIPLIER;
+
+       /* High bits are more random than the low bits.  */
+       return hash >> (32 - HASH_SHIFT);
+}
+
 /*
  *             Search for the longest sequence matching current position
  *
- *     A binary tree is maintained to locate all previously met sequences,
- *     and this function has to be called for all of them.
+ *     A hash table, each entry of which points to a chain of sequence
+ *     positions sharing the corresponding hash code, is maintained to speed up
+ *     searching for matches.  To maintain the hash table, either
+ *     ntfs_best_match() or ntfs_skip_position() has to be called for each
+ *     consecutive position.
+ *
+ *     This function is heavily used; it has to be optimized carefully.
+ *
+ *     This function sets pctx->size and pctx->rel to the length and offset,
+ *     respectively, of the longest match found.
+ *
+ *     The minimum match length is assumed to be 3, and the maximum match
+ *     length is assumed to be pctx->mxsz.  If this function produces
+ *     pctx->size < 3, then no match was found.
  *
- *     This function is heavily used, it has to be optimized carefully
+ *     Note: for the following reasons, this function is not guaranteed to find
+ *     *the* longest match up to pctx->mxsz:
  *
- *     Returns the size of the longest match,
- *             zero if no match is found.
+ *     (1) If this function finds a match of NICE_MATCH_LEN bytes or greater,
+ *         it ends early because a match this long is good enough and it's not
+ *         worth spending more time searching.
+ *
+ *     (2) If this function considers MAX_SEARCH_DEPTH matches with a single
+ *         position, it ends early and returns the longest match found so far.
+ *         This saves a lot of time on degenerate inputs.
  */
-
-static int ntfs_best_match(struct COMPRESS_CONTEXT *pctx, int i)
+static void ntfs_best_match(struct COMPRESS_CONTEXT *pctx, const int i,
+                           int best_len)
 {
-       s16 *prev;
-       int node;
-       register long j;
-       long maxpos;
-       long startj;
-       long bestj;
-       int bufsize;
-       int bestnode;
-       register const unsigned char *p1,*p2;
-
-       p1 = pctx->inbuf;
-       node = pctx->head[p1[i] & 255];
-       if (node >= 0) {
-               /* search the best match at current position */
-               bestnode = node;
-               bufsize = pctx->bufsize;
-               /* restrict matches to the longest allowed sequence */
-               maxpos = bufsize;
-               if ((i + pctx->mxsz) < maxpos)
-                       maxpos = i + pctx->mxsz;
-               startj = i + 1 - maxpos;
-               bestj = startj;
-               /* make indexes relative to end of allowed position */
-               p1 = &p1[maxpos];
-               if (startj < 0) {
-                       do {
-                       /* indexes are negative */
-                               p2 = &p1[node - i];
-                       /* no need to compare the first byte */
-                               j = startj;
-                       /* the second byte cannot lead to useful compression */
-                               if (p1[j] == p2[j]) {
-                                       j++;
-                                       if (j < 0) {
-                                               do {
-                                               } while ((p1[j] == p2[j])
-                                                               && (++j < 0));
-                                       }
-                                       /* remember the match, if better */
-                                       if (j > bestj) {
-                                               bestj = j;
-                                               bestnode = node;
-                                       }
+       const u8 * const inbuf = pctx->inbuf;
+       const u8 * const strptr = &inbuf[i]; /* String we're matching against */
+       s16 * const prev = pctx->prev;
+       const int max_len = min(pctx->bufsize - i, pctx->mxsz);
+       const int nice_len = min(NICE_MATCH_LEN, max_len);
+       int depth_remaining = MAX_SEARCH_DEPTH;
+       const u8 *best_matchptr = strptr;
+       unsigned int hash;
+       s16 cur_match;
+       const u8 *matchptr;
+       int len;
+
+       if (max_len < 4)
+               goto out;
+
+       /* Insert the current sequence into the appropriate hash chain.  */
+       hash = ntfs_hash(strptr);
+       cur_match = pctx->head[hash];
+       prev[i] = cur_match;
+       pctx->head[hash] = i;
+
+       if (best_len >= max_len) {
+               /* Lazy match is being attempted, but there aren't enough length
+                * bits remaining to code a longer match.  */
+               goto out;
+       }
+
+       /* Search the appropriate hash chain for matches.  */
+
+       for (; cur_match >= 0 && depth_remaining--;
+               cur_match = prev[cur_match])
+       {
+
+               matchptr = &inbuf[cur_match];
+
+               /* Considering the potential match at 'matchptr':  is it longer
+                * than 'best_len'?
+                *
+                * The bytes at index 'best_len' are the most likely to differ,
+                * so check them first.
+                *
+                * The bytes at indices 'best_len - 1' and '0' are less
+                * important to check separately.  But doing so still gives a
+                * slight performance improvement, at least on x86_64, probably
+                * because they create separate branches for the CPU to predict
+                * independently of the branches in the main comparison loops.
+                */
+               if (matchptr[best_len] != strptr[best_len] ||
+                   matchptr[best_len - 1] != strptr[best_len - 1] ||
+                   matchptr[0] != strptr[0])
+                       goto next_match;
+
+               for (len = 1; len < best_len - 1; len++)
+                       if (matchptr[len] != strptr[len])
+                               goto next_match;
+
+               /* The match is the longest found so far ---
+                * at least 'best_len' + 1 bytes.  Continue extending it.  */
+
+               best_matchptr = matchptr;
+
+               do {
+                       if (++best_len >= nice_len) {
+                               /* 'nice_len' reached; don't waste time
+                                * searching for longer matches.  Extend the
+                                * match as far as possible and terminate the
+                                * search.  */
+                               while (best_len < max_len &&
+                                       (best_matchptr[best_len] ==
+                                               strptr[best_len]))
+                               {
+                                       best_len++;
                                }
-                               /* walk in the tree in the right direction */
-                               if ((j < 0) && (p1[j] < p2[j]))
-                                       prev = &pctx->lson[node];
-                               else
-                                       prev = &pctx->rson[node];
-                               node = *prev;
-                               /* stop if reaching a leaf or maximum length */
-                       } while ((node >= 0) && (j < 0));
-                       /* put the node into the tree if we reached a leaf */
-                       if (node < 0)
-                               *prev = i;
-               }
-                       /* done, return the best match */
-               pctx->size = bestj + maxpos - i;
-               pctx->rel = bestnode - i;
-       } else {
-               pctx->head[p1[i] & 255] = i;
-               pctx->size = 0;
-               pctx->rel = 0;
+                               goto out;
+                       }
+               } while (best_matchptr[best_len] == strptr[best_len]);
+
+               /* Found a longer match, but 'nice_len' not yet reached.  */
+
+       next_match:
+               /* Continue to next match in the chain.  */
+               ;
        }
-       return (pctx->size);
+
+       /* Reached end of chain, or ended early due to reaching the maximum
+        * search depth.  */
+
+out:
+       /* Return the longest match we were able to find.  */
+       pctx->size = best_len;
+       pctx->rel = best_matchptr - strptr; /* given as a negative number! */
+}
+
+/*
+ *             Advance the match-finder, but don't search for matches.
+ */
+static void ntfs_skip_position(struct COMPRESS_CONTEXT *pctx, const int i)
+{
+       unsigned int hash;
+
+       if (pctx->bufsize - i < 4)
+               return;
+
+       /* Insert the current sequence into the appropriate hash chain.  */
+       hash = ntfs_hash(pctx->inbuf + i);
+       pctx->prev[i] = pctx->head[hash];
+       pctx->head[hash] = i;
 }
 
 /*
@@ -188,7 +273,7 @@ static int ntfs_best_match(struct COMPRESS_CONTEXT *pctx, 
int i)
  *             0 if an error has been met. 
  */
 
-static unsigned int ntfs_compress_block(const char *inbuf, int bufsize,
+static unsigned int ntfs_compress_block(const char *inbuf, const int bufsize,
                                char *outbuf)
 {
        struct COMPRESS_CONTEXT *pctx;
@@ -196,109 +281,168 @@ static unsigned int ntfs_compress_block(const char 
*inbuf, int bufsize,
        int j; /* end of best match from current position */
        int k; /* end of best match from next position */
        int offs; /* offset to best match */
-       int n;
        int bp; /* bits to store offset */
+       int bp_cur; /* saved bits to store offset at current position */
        int mxoff; /* max match offset : 1 << bp */
-       int mxsz2;
        unsigned int xout;
        unsigned int q; /* aggregated offset and size */
-       int done;
+       int have_match; /* do we have a match at the current position? */
        char *ptag; /* location reserved for a tag */
        int tag;    /* current value of tag */
        int ntag;   /* count of bits still undefined in tag */
 
-       pctx = (struct COMPRESS_CONTEXT*)ntfs_malloc(sizeof(struct 
COMPRESS_CONTEXT));
-       if (pctx) {
-               for (n=0; n<NTFS_SB_SIZE; n++)
-                       pctx->lson[n] = pctx->rson[n] = -1;
-               for (n=0; n<256; n++)
-                       pctx->head[n] = -1;
-               pctx->inbuf = (const unsigned char*)inbuf;
-               pctx->bufsize = bufsize;
-               xout = 2;
-               n = 0;
-               i = 0;
-               bp = 4;
-               mxoff = 1 << bp;
-               pctx->mxsz = (1 << (16 - bp)) + 2;
-               tag = 0;
-               done = -1;
-               ntag = 8;
-               ptag = &outbuf[xout++];
-               while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
-                  /* adjust the longest match we can output */
+       pctx = ntfs_malloc(sizeof(struct COMPRESS_CONTEXT));
+       if (!pctx) {
+               errno = ENOMEM;
+               return 0;
+       }
+
+       /* All hash chains start as empty.  The special value '-1' indicates the
+        * end of each hash chain.  */
+       memset(pctx->head, 0xFF, sizeof(pctx->head));
+
+       pctx->inbuf = (const unsigned char*)inbuf;
+       pctx->bufsize = bufsize;
+       xout = 2;
+       i = 0;
+       bp = 4;
+       mxoff = 1 << bp;
+       pctx->mxsz = (1 << (16 - bp)) + 2;
+       have_match = 0;
+       tag = 0;
+       ntag = 8;
+       ptag = &outbuf[xout++];
+
+       while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
+
+               /* This implementation uses "lazy" parsing: it always chooses
+                * the longest match, unless the match at the next position is
+                * longer.  This is the same strategy used by the high
+                * compression modes of zlib.  */
+
+               if (!have_match) {
+                       /* Find the longest match at the current position.  But
+                        * first adjust the maximum match length if needed.
+                        * (This loop might need to run more than one time in
+                        * the case that we just output a long match.)  */
                        while (mxoff < i) {
                                bp++;
                                mxoff <<= 1;
                                pctx->mxsz = (pctx->mxsz + 2) >> 1;
                        }
-               /* search the best match at current position */
-                       if (done < i)
-                               do {
-                                       ntfs_best_match(pctx,++done);
-                               } while (done < i);
+                       ntfs_best_match(pctx, i, 2);
+               }
+
+               if (pctx->size >= 3) {
+
+                       /* Found a match at the current position.  */
+
                        j = i + pctx->size;
-                       if ((j - i) > pctx->mxsz)
-                               j = i + pctx->mxsz;
-
-                       if ((j - i) > 2) {
-                               offs = pctx->rel;
-                 /* check whether there is a better run at i+1 */
-                               ntfs_best_match(pctx,i+1);
-                               done = i+1;
+                       bp_cur = bp;
+                       offs = pctx->rel;
+
+                       if (pctx->size >= NICE_MATCH_LEN) {
+
+                               /* Choose long matches immediately.  */
+
+                               q = (~offs << (16 - bp_cur)) + (j - i - 3);
+                               outbuf[xout++] = q & 255;
+                               outbuf[xout++] = (q >> 8) & 255;
+                               tag |= (1 << (8 - ntag));
+
+                               if (j == bufsize) {
+                                       /* Shortcut if the match extends to the
+                                        * end of the buffer.  */
+                                       i = j;
+                                       --ntag;
+                                       break;
+                               }
+                               i += 1;
+                               do {
+                                       ntfs_skip_position(pctx, i);
+                               } while (++i != j);
+                               have_match = 0;
+                       } else {
+                               /* Check for a longer match at the next
+                                * position.  */
+
+                               /* Doesn't need to be while() since we just
+                                * adjusted the maximum match length at the
+                                * previous position.  */
+                               if (mxoff < i + 1) {
+                                       bp++;
+                                       mxoff <<= 1;
+                                       pctx->mxsz = (pctx->mxsz + 2) >> 1;
+                               }
+                               ntfs_best_match(pctx, i + 1, pctx->size);
                                k = i + 1 + pctx->size;
-                               mxsz2 = pctx->mxsz;
-                               if (mxoff <= i)
-                                       mxsz2 = (pctx->mxsz + 2) >> 1;
-                               if ((k - i) > mxsz2)
-                                       k = i + mxsz2;
+
                                if (k > (j + 1)) {
-                                       /* issue a single byte */
-                                       outbuf[xout++] = inbuf[i];
-                                       i++;
+                                       /* Next match is longer.
+                                        * Output a literal.  */
+                                       outbuf[xout++] = inbuf[i++];
+                                       have_match = 1;
                                } else {
-                                       q = (~offs << (16 - bp))
-                                               + (j - i - 3);
+                                       /* Next match isn't longer.
+                                        * Output the current match.  */
+                                       q = (~offs << (16 - bp_cur)) +
+                                                       (j - i - 3);
                                        outbuf[xout++] = q & 255;
                                        outbuf[xout++] = (q >> 8) & 255;
                                        tag |= (1 << (8 - ntag));
-                                       i = j;
+
+                                       /* The minimum match length is 3, and
+                                        * we've run two bytes through the
+                                        * matchfinder already.  So the minimum
+                                        * number of positions we need to skip
+                                        * is 1.  */
+                                       i += 2;
+                                       do {
+                                               ntfs_skip_position(pctx, i);
+                                       } while (++i != j);
+                                       have_match = 0;
                                }
-                       } else {
-                               outbuf[xout++] = inbuf[i];
-                               i++;
-                       }
-                               /* store the tag if fully used */
-                       if (!--ntag) {
-                               *ptag = tag;
-                               ntag = 8;
-                               ptag = &outbuf[xout++];
-                               tag = 0;
                        }
+               } else {
+                       /* No match at current position.  Output a literal.  */
+                       outbuf[xout++] = inbuf[i++];
+                       have_match = 0;
                }
-                       /* store the last tag, if partially used */
-               if (ntag == 8)
-                       xout--;
-               else
+
+               /* Store the tag if fully used.  */
+               if (!--ntag) {
                        *ptag = tag;
-               /* uncompressed must be full size, accept if better */
-               if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
-                       outbuf[0] = (xout - 3) & 255;
-                       outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
-               } else {
-                       memcpy(&outbuf[2],inbuf,bufsize);
-                       if (bufsize < NTFS_SB_SIZE)
-                               memset(&outbuf[bufsize+2], 0,
-                                               NTFS_SB_SIZE - bufsize);
-                       outbuf[0] = 0xff;
-                       outbuf[1] = 0x3f;
-                       xout = NTFS_SB_SIZE + 2;
+                       ntag = 8;
+                       ptag = &outbuf[xout++];
+                       tag = 0;
                }
-               free(pctx);
+       }
+
+       /* Store the last tag if partially used.  */
+       if (ntag == 8)
+               xout--;
+       else
+               *ptag = tag;
+
+       /* Determine whether to store the data compressed or uncompressed.  */
+
+       if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
+               /* Compressed.  */
+               outbuf[0] = (xout - 3) & 255;
+               outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
        } else {
-               xout = 0;
-               errno = ENOMEM;
+               /* Uncompressed.  */
+               memcpy(&outbuf[2], inbuf, bufsize);
+               if (bufsize < NTFS_SB_SIZE)
+                       memset(&outbuf[bufsize + 2], 0, NTFS_SB_SIZE - bufsize);
+               outbuf[0] = 0xff;
+               outbuf[1] = 0x3f;
+               xout = NTFS_SB_SIZE + 2;
        }
+
+       /* Free the compression context and return the total number of bytes
+        * written to 'outbuf'.  */
+       free(pctx);
        return (xout);
 }
 
@@ -575,7 +719,7 @@ s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 
count, void *b)
        unsigned int nr_cbs, cb_clusters;
 
        ntfs_log_trace("Entering for inode 0x%llx, attr 0x%x, pos 0x%llx, count 
0x%llx.\n",
-                       (unsigned long long)na->ni->mft_no, na->type,
+                       (unsigned long long)na->ni->mft_no, 
le32_to_cpu(na->type),
                        (long long)pos, (long long)count);
        data_flags = na->data_flags;
        compression = na->ni->flags & FILE_ATTR_COMPRESSED;
@@ -987,6 +1131,7 @@ static s32 ntfs_comp_set(ntfs_attr *na, runlist_element 
*rl,
                        outbuf[compsz++] = 0;
                        /* write a full cluster, to avoid partial reading */
                        rounded = ((compsz - 1) | (clsz - 1)) + 1;
+                       memset(&outbuf[compsz], 0, rounded - compsz);
                        written = write_clusters(vol, rl, offs, rounded, 
outbuf);
                        if (written != rounded) {
                                /*
@@ -1417,6 +1562,7 @@ static int ntfs_compress_free(ntfs_attr *na, 
runlist_element *rl,
                ntfs_log_error("No cluster to free after compression\n");
                errno = EIO;
        }
+       NAttrSetRunlistDirty(na);
        return (res);
 }
 
diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/config.h 
b/src/add-ons/kernel/file_systems/ntfs/libntfs/config.h
index 6e58ab7283..ada5673c0c 100644
--- a/src/add-ons/kernel/file_systems/ntfs/libntfs/config.h
+++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/config.h
@@ -1,27 +1,70 @@
+/* Haiku-specific stuff */
+#ifdef __HAIKU__
+
+/* major part of a device */
+#define major(x)    (int)((unsigned)((x)>>8)&0x7F)
+#define bmajor(x)   (int)((unsigned)((x)>>8)&0x7F)
+
+/* minor part of a device */
+#define minor(x)    (int)((x)&0xFF)
+#endif
+
+/* config.h.  Generated from config.h.in by configure.  */
 /* config.h.in.  Generated from configure.ac by autoheader.  */
 
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define to 1 for disabling reparse plugins */
+/* #undef DISABLE_PLUGINS */
+
+/* Define this to 1 if you want to enable support of encrypted files in
+   libntfs and utilities. */
+/* #undef ENABLE_CRYPTO */
+
+/* Define to 1 if debug should be enabled */
+/* #undef ENABLE_DEBUG */
+
+/* Define this to 1 if you want to enable use of Windows compliant disk
+   geometry. */
+/* #undef ENABLE_HD */
+
+/* Define to 1 if the nfconv patch should be enabled */
+/* #undef ENABLE_NFCONV */
+
+/* Define this to 1 if you want to enable generation of DCE compliant UUIDs.
+   */
+/* #undef ENABLE_UUID */
+
+/* Define to 1 if using internal fuse */
+/* #undef FUSE_INTERNAL */
+
 /* Define to 1 if you have the `atexit' function. */
-#undef HAVE_ATEXIT
+#define HAVE_ATEXIT 1
 
 /* Define to 1 if you have the `basename' function. */
-#undef HAVE_BASENAME
+#define HAVE_BASENAME 1
 
 /* Define to 1 if you have the <byteswap.h> header file. */
-#undef HAVE_BYTESWAP_H
+/* #undef HAVE_BYTESWAP_H */
+
+/* Define to 1 if you have the `clock_gettime' function. */
+/* #undef HAVE_CLOCK_GETTIME */
 
 /* Define to 1 if you have the <ctype.h> header file. */
 #define HAVE_CTYPE_H 1
 
+/* Define to 1 if you have the `daemon' function. */
 #define HAVE_DAEMON 1
 
 /* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
+#define HAVE_DLFCN_H 1
 
 /* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
+/* #undef HAVE_DOPRNT */
 
 /* Define to 1 if you have the `dup2' function. */
-#undef HAVE_DUP2
+#define HAVE_DUP2 1
 
 /* Define to 1 if you have the <endian.h> header file. */
 #define HAVE_ENDIAN_H 1
@@ -33,103 +76,128 @@
 #define HAVE_FCNTL_H 1
 
 /* Define to 1 if you have the `fdatasync' function. */
-#undef HAVE_FDATASYNC
+/* #undef HAVE_FDATASYNC */
 
 /* Define to 1 if you have the <features.h> header file. */
-#undef HAVE_FEATURES_H
+/* #undef HAVE_FEATURES_H */
 
-/* Define to 1 if you have the <gcrypt.h> header file. */
-#undef HAVE_GCRYPT_H
+/* Define to 1 if you have the `ffs' function. */
+#define HAVE_FFS 1
+
+/* Define to 1 if you have the `fork' function. */
+/* #undef HAVE_FORK */
 
 /* Define to 1 if you have the `getmntent' function. */
-#undef HAVE_GETMNTENT
+/* #undef HAVE_GETMNTENT */
 
 /* Define to 1 if you have the <getopt.h> header file. */
-#undef HAVE_GETOPT_H
+#define HAVE_GETOPT_H 1
 
 /* Define to 1 if you have the `getopt_long' function. */
-#undef HAVE_GETOPT_LONG
+#define HAVE_GETOPT_LONG 1
 
-/* Define to 1 if you have the <gnutls/pkcs12.h> header file. */
-#undef HAVE_GNUTLS_PKCS12_H
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
 
 /* Define to 1 if you have the `hasmntopt' function. */
-#undef HAVE_HASMNTOPT
+/* #undef HAVE_HASMNTOPT */
 
 /* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `c' library (-lc). */
+/* #undef HAVE_LIBC */
 
 /* Define to 1 if you have the <libgen.h> header file. */
-#undef HAVE_LIBGEN_H
+#define HAVE_LIBGEN_H 1
 
 /* Define to 1 if you have the <libintl.h> header file. */
-#undef HAVE_LIBINTL_H
+/* #undef HAVE_LIBINTL_H */
 
 /* Define to 1 if you have the <limits.h> header file. */
-#undef HAVE_LIMITS_H
+#define HAVE_LIMITS_H 1
 
 /* Define to 1 if you have the <linux/fd.h> header file. */
-#undef HAVE_LINUX_FD_H
+/* #undef HAVE_LINUX_FD_H */
+
+/* Define to 1 if you have the <linux/fs.h> header file. */
+/* #undef HAVE_LINUX_FS_H */
 
 /* Define to 1 if you have the <linux/hdreg.h> header file. */
-#undef HAVE_LINUX_HDREG_H
+/* #undef HAVE_LINUX_HDREG_H */
 
 /* Define to 1 if you have the <linux/major.h> header file. */
-#undef HAVE_LINUX_MAJOR_H
+/* #undef HAVE_LINUX_MAJOR_H */
 
 /* Define to 1 if you have the <locale.h> header file. */
 #define HAVE_LOCALE_H 1
 
 /* Define to 1 if you have the <machine/endian.h> header file. */
-#undef HAVE_MACHINE_ENDIAN_H
+/* #undef HAVE_MACHINE_ENDIAN_H */
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#define HAVE_MALLOC_H 1
 
 /* Define to 1 if mbrtowc and mbstate_t are properly declared. */
-#undef HAVE_MBRTOWC
 #define HAVE_MBRTOWC 1
 
 /* Define to 1 if you have the `mbsinit' function. */
-#undef HAVE_MBSINIT
-//#define HAVE_MBSINIT 1
+/* #undef HAVE_MBSINIT */
+
+/* Define to 1 if you have the `memcpy' function. */
+#define HAVE_MEMCPY 1
 
 /* Define to 1 if you have the `memmove' function. */
-#undef HAVE_MEMMOVE
+#define HAVE_MEMMOVE 1
 
 /* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
+#define HAVE_MEMORY_H 1
 
 /* Define to 1 if you have the `memset' function. */
-#undef HAVE_MEMSET
+#define HAVE_MEMSET 1
 
 /* Define to 1 if you have the <mntent.h> header file. */
-#undef HAVE_MNTENT_H
+/* #undef HAVE_MNTENT_H */
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `random' function. */
+#define HAVE_RANDOM 1
 
 /* Define to 1 if you have the `realpath' function. */
-#undef HAVE_REALPATH
+#define HAVE_REALPATH 1
 
 /* Define to 1 if you have the `regcomp' function. */
-#undef HAVE_REGCOMP
+#define HAVE_REGCOMP 1
+
+/* Define to 1 if you have the <regex.h> header file. */
+#define HAVE_REGEX_H 1
 
 /* Define to 1 if you have the `setlocale' function. */
-#undef HAVE_SETLOCALE
+/* #undef HAVE_SETLOCALE */
 
 /* Define to 1 if you have the `setxattr' function. */
-#undef HAVE_SETXATTR
+/* #undef HAVE_SETXATTR */
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
 
 /* Define to 1 if `stat' has the bug that it succeeds when given the
    zero-length file name argument. */
-#undef HAVE_STAT_EMPTY_STRING_BUG
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
 
 /* Define to 1 if you have the <stdarg.h> header file. */
 #define HAVE_STDARG_H 1
 
 /* Define to 1 if stdbool.h conforms to C99. */
-#undef HAVE_STDBOOL_H

[ *** diff truncated: 7588 lines dropped *** ]


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

Commit:      e39df8a97c6b89fa3bcd7b4f1de5949d8566c0d9
URL:         https://git.haiku-os.org/haiku/commit/?id=e39df8a97c6b
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Wed Oct 17 21:54:57 2018 UTC

bios_ia32: Remove some extra debug info.

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

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

Revision:    hrev52407
Commit:      7deac31935900b7be3a61ad06b7924b2153dbfbc
URL:         https://git.haiku-os.org/haiku/commit/?id=7deac3193590
Author:      Augustin Cavalier <waddlesplash@xxxxxxxxx>
Date:        Wed Oct 17 22:05:06 2018 UTC

interface: Fix -Wuninitialized in RegionSupport.

Also trim trailing spaces...

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



Other related posts:

  • » [haiku-commits] haiku: hrev52407 - src/add-ons/kernel/file_systems/ntfs/libntfs - waddlesplash