OSDN Git Service

Fixed inserting a new ACL after they have been wiped out by chkdsk
authorJean-Pierre André <jpandre@users.sourceforge.net>
Wed, 23 Apr 2014 07:53:13 +0000 (09:53 +0200)
committerJean-Pierre André <jpandre@users.sourceforge.net>
Wed, 23 Apr 2014 07:53:13 +0000 (09:53 +0200)
chkdsk deletes the ACLs when they are bad or when they are not used any
more. This fixes inserting a new ACL after the previously last ACL (or
even all of them) was deleted.

include/ntfs-3g/attrib.h
libntfs-3g/attrib.c
libntfs-3g/security.c

index 846bc9e..b3752a6 100644 (file)
@@ -396,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 */
 
index 4b2be1b..77b1f03 100644 (file)
@@ -6735,6 +6735,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_le64(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)
index a42b38b..bf8fd6e 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2004 Anton Altaparmakov
  * Copyright (c) 2005-2006 Szabolcs Szakacsits
  * Copyright (c) 2006 Yura Pakhuchiy
- * Copyright (c) 2007-2012 Jean-Pierre Andre
+ * Copyright (c) 2007-2014 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
@@ -514,8 +514,18 @@ static int entersecurity_data(ntfs_volume *vol,
                        STREAM_SDS, 4, fullattr, fullsz,
                        offs - gap + ALIGN_SDS_BLOCK);
                if ((written1 == fullsz)
-                    && (written2 == written1))
-                       res = 0;
+                    && (written2 == written1)) {
+                       /*
+                        * Make sure the data size for $SDS marks the end
+                        * of the last security attribute. Windows uses
+                        * this to determine where the next attribute will
+                        * be written, which causes issues if chkdsk had
+                        * previously deleted the last entries without
+                        * adjusting the size.
+                        */
+                       res = ntfs_attr_shrink_size(vol->secure_ni,STREAM_SDS,
+                               4, offs - gap + ALIGN_SDS_BLOCK + fullsz);
+               }
                else
                        errno = ENOSPC;
                free(fullattr);
@@ -707,10 +717,24 @@ static le32 entersecurityattr(ntfs_volume *vol,
                                               sizeof(SII_INDEX_KEY), xsii);
                                if (!found && (errno != ENOENT)) {
                                        ntfs_log_perror("Index $SII is broken");
+                                       psii = (struct SII*)NULL;
                                } else {
                                                /* restore errno */
                                        errno = olderrno;
                                        entry = xsii->entry;
+                                       psii = (struct SII*)entry;
+                               }
+                               if (psii
+                                   && !(psii->flags & INDEX_ENTRY_END)) {
+                                               /* save first key and */
+                                               /* available position */
+                                       keyid = psii->keysecurid;
+                                       realign.parts.dataoffsh
+                                                        = psii->dataoffsh;
+                                       realign.parts.dataoffsl
+                                                        = psii->dataoffsl;
+                                       offs = le64_to_cpu(realign.all);
+                                       size = le32_to_cpu(psii->datasize);
                                }
                                retries++;
                        }
@@ -725,7 +749,8 @@ static le32 entersecurityattr(ntfs_volume *vol,
                securid = const_cpu_to_le32(0);
                na = ntfs_attr_open(vol->secure_ni,AT_INDEX_ROOT,sii_stream,4);
                if (na) {
-                       if ((size_t)na->data_size < sizeof(struct SII)) {
+                       if ((size_t)na->data_size < (sizeof(struct SII)
+                                       + sizeof(INDEX_ENTRY_HEADER))) {
                                ntfs_log_error("Creating the first security_id\n");
                                securid = const_cpu_to_le32(FIRST_SECURITY_ID);
                        }
@@ -1814,11 +1839,13 @@ static char *getsecurityattr(ntfs_volume *vol, ntfs_inode *ni)
                 * with a default security descriptor inserted in an
                 * attribute
                 */
-       if (test_nino_flag(ni, v3_Extensions)
-                       && vol->secure_ni && ni->security_id) {
-                       /* get v3.x descriptor in $Secure */
-               securid.security_id = ni->security_id;
-               securattr = retrievesecurityattr(vol,securid);
+       if (test_nino_flag(ni, v3_Extensions) && vol->secure_ni) {
+               if (ni->security_id) {
+                               /* get v3.x descriptor in $Secure */
+                       securid.security_id = ni->security_id;
+                       securattr = retrievesecurityattr(vol,securid);
+               } else
+                       securattr = (char*)NULL;
                if (!securattr)
                        ntfs_log_error("Bad security descriptor for 0x%lx\n",
                                        (long)le32_to_cpu(ni->security_id));