Package: ntfs-3g
Version: 1:2009.4.4-1ubuntu4
Severity: normal
Tags: patch

Here is a patch from LinuxDeepin, which can provide extended attributes
supported in ntfs-3g, the author is Jiahua Huang <jhuangjiahua (AT)
gmail (DOT) com> and licensed as the same as ntfs-3g package in Debian.
I don't know if this patch can be accepted to provide such a function in
Debian.

LinuxDeepin has tried to make it possible to install Linux on an ntfs
partition with ntfs-3g, I think it is a good feature at least for the
newer comers of Linux.

Regards,
Aron Xu


--- System information. ---
Architecture: i386
Kernel: Linux 2.6.31-16-generic

Debian Release: squeeze/sid
500 karmic-updates debian.nctu.edu.tw
500 karmic-security debian.nctu.edu.tw
500 karmic ppa.launchpad.net
500 karmic packages.medibuntu.org
500 karmic debian.nctu.edu.tw
500 karmic archive.canonical.com

--- Package information. ---
Depends (Version) | Installed
==============================-+-===========
libc6 (>= 2.4) | 2.10.1-0ubuntu15
libfuse2 (>= 2.6) | 2.7.4-1.1ubuntu4.3
libntfs-3g54 | 1:2009.4.4-1ubuntu4
initramfs-tools | 0.92bubuntu53


Package's Recommends field is empty.

Package's Suggests field is empty.



diff --git a/ntfs-3g-2009.1.1/src/ntfs-3g.c b/ntfs-3g-2009.1.1/src/ntfs-3g.c
index a7b2e57..047ebaf 100644
--- a/ntfs-3g-2009.1.1/src/ntfs-3g.c
+++ b/ntfs-3g-2009.1.1/src/ntfs-3g.c
@@ -400,6 +400,89 @@ int ntfs_macfuse_setcrtime(const char *path, const struct 
timespec *tv)
 }
 #endif /* defined(__APPLE__) || defined(__DARWIN__) */
 
+/* for linux ownership, permissions */
+static const char nf_ns_attr_linux_uid[]  = "user.linux.uid";
+static const char nf_ns_attr_linux_gid[]  = "user.linux.gid";
+static const char nf_ns_attr_linux_mode[] = "user.linux.mode";
+
+static int ntfs_fuse_in_getattr(ntfs_inode *ni, const char *name,
+                               char *value, size_t size)
+{
+       ntfs_attr *na = NULL;
+       ntfschar *lename = NULL;
+       int res, lename_len;
+
+       if (!ni)
+               return -errno;
+       lename_len = ntfs_mbstoucs(name, &lename);
+       if (lename_len == -1) {
+               res = -errno;
+               goto exit;
+       }
+       na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+       if (!na) {
+               res = -ENODATA;
+               goto exit;
+       }
+       if (size) {
+               if (size >= na->data_size) {
+                       res = ntfs_attr_pread(na, 0, na->data_size, value);
+                       if (res != na->data_size)
+                               res = -errno;
+               } else
+                       res = -ERANGE;
+       } else
+               res = na->data_size;
+exit:
+       if (na)
+               ntfs_attr_close(na);
+       free(lename);
+       return res;
+}
+
+static int ntfs_fuse_in_setattr(ntfs_inode *ni, const char *name,
+                               const char *value, size_t size)
+{
+       ntfs_attr *na = NULL;
+       ntfschar *lename = NULL;
+       int res, lename_len;
+
+       if (!ni)
+               return -errno;
+       lename_len = ntfs_mbstoucs(name, &lename);
+       if (lename_len == -1) {
+               res = -errno;
+               goto exit;
+       }
+       na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+       if (!na) {
+               if (ntfs_attr_add(ni, AT_DATA, lename, lename_len, NULL, 0)) {
+                       res = -errno;
+                       goto exit;
+               }
+               na = ntfs_attr_open(ni, AT_DATA, lename, lename_len);
+               if (!na) {
+                       res = -errno;
+                       goto exit;
+               }
+       } else {
+               if (ntfs_attr_truncate(na, (s64)size)) {
+                       res = -errno;
+                       goto exit;
+               }
+       }
+       res = ntfs_attr_pwrite(na, 0, size, value);
+       if (res != (s64) size)
+               res = -errno;
+       else
+               res = 0;
+exit:
+       if (na)
+               ntfs_attr_close(na);
+       free(lename);
+       return res;
+}
+
 static int ntfs_fuse_getattr(const char *org_path, struct stat *stbuf)
 {
        int res = 0;
@@ -409,6 +492,18 @@ static int ntfs_fuse_getattr(const char *org_path, struct 
stat *stbuf)
        ntfschar *stream_name;
        int stream_name_len;
 
+       char modec[10]="          ";
+       char uidc[10]="          ";
+       char gidc[10]="          ";
+
+       unsigned int modei;
+       unsigned int uid;
+       unsigned int gid;
+
+       modei |= (0777 & ~ctx->fmask);
+       uid = ctx->uid;
+       gid = ctx->gid;
+
        stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
        if (stream_name_len < 0)
                return stream_name_len;
@@ -510,8 +605,24 @@ static int ntfs_fuse_getattr(const char *org_path, struct 
stat *stbuf)
                }
                stbuf->st_mode |= (0777 & ~ctx->fmask);
        }
-       stbuf->st_uid = ctx->uid;
-       stbuf->st_gid = ctx->gid;
+       if (ntfs_fuse_in_getattr(ni, nf_ns_attr_linux_mode, modec, 65536) > 0){
+               sscanf(modec, "%o", &modei);
+               stbuf->st_mode = modei;
+       }
+
+       if (ntfs_fuse_in_getattr(ni, nf_ns_attr_linux_uid, uidc, 65536) > 0){
+               sscanf(uidc, "%u", &uid);
+               stbuf->st_uid = uid;
+       } else {
+               stbuf->st_uid = ctx->uid;
+       }
+       if (ntfs_fuse_in_getattr(ni, nf_ns_attr_linux_gid, gidc, 65536) > 0){
+               sscanf(gidc, "%u", &gid);
+               stbuf->st_gid = gid;
+       } else {
+               stbuf->st_gid = ctx->gid;
+       }
+
        stbuf->st_ino = ni->mft_no;
        stbuf->st_atime = ni->last_access_time;
        stbuf->st_ctime = ni->last_mft_change_time;
@@ -848,8 +959,18 @@ exit:
 static int ntfs_fuse_chmod(const char *path,
                mode_t mode __attribute__((unused)))
 {
+       ntfs_inode *ni;
+       char modec[10]="          ";
+       
        if (ntfs_fuse_is_named_data_stream(path))
                return -EINVAL; /* n/a for named data streams. */
+       ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+       if (!ni)
+               return -errno;
+       sprintf(modec, "%o", mode);
+       ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_mode, modec, strlen(modec));
+       ntfs_inode_close(ni);
+
        if (ctx->silent)
                return 0;
        return -EOPNOTSUPP;
@@ -857,8 +978,22 @@ static int ntfs_fuse_chmod(const char *path,
 
 static int ntfs_fuse_chown(const char *path, uid_t uid, gid_t gid)
 {
+       ntfs_inode *ni;
+       char uidc[10]="         0";
+       char gidc[10]="         0";
+
        if (ntfs_fuse_is_named_data_stream(path))
                return -EINVAL; /* n/a for named data streams. */
+
+       ni = ntfs_pathname_to_inode(ctx->vol, NULL, path);
+       if (!ni)
+               return -errno;
+       sprintf(uidc, "%d", uid);
+       sprintf(gidc, "%d", gid);
+       ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_gid, gidc, strlen(gidc));
+       ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_uid, uidc, strlen(uidc));
+       ntfs_inode_close(ni);
+
        if (ctx->silent)
                return 0;
        if (uid == ctx->uid && gid == ctx->gid)
@@ -875,6 +1010,17 @@ static int ntfs_fuse_create(const char *org_path, dev_t 
type, dev_t dev,
        char *path;
        int res = 0, uname_len, utarget_len;
 
+       char modec[10]="          ";
+       char uidc[10]="         0";
+       char gidc[10]="         0";
+
+       int mode, uid, gid;
+       struct fuse_context *mycontext = fuse_get_context();
+       uid = mycontext->uid;
+       gid = mycontext->gid;
+       mode = (type & 0777) ? type : ( type | 0777);
+       type = type & 0177000;
+
        path = strdup(org_path);
        if (!path)
                return -errno;
@@ -914,6 +1060,13 @@ static int ntfs_fuse_create(const char *org_path, dev_t 
type, dev_t dev,
                        break;
        }
        if (ni) {
+               sprintf(uidc, "%d", uid);
+               sprintf(gidc, "%d", gid);
+               ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_gid, gidc, 
strlen(gidc));
+               ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_uid, uidc, 
strlen(uidc));
+               sprintf(modec, "%o", mode);
+               ntfs_fuse_in_setattr(ni, nf_ns_attr_linux_mode, modec, 
strlen(modec));
+
                if (ntfs_inode_close(ni))
                        set_fuse_error(&res);
                ntfs_fuse_update_times(dir_ni, NTFS_UPDATE_MCTIME);
@@ -974,7 +1127,7 @@ static int ntfs_fuse_mknod_common(const char *org_path, 
mode_t mode, dev_t dev)
                goto exit;
        }
        if (!stream_name_len)
-               res = ntfs_fuse_create(path, mode & S_IFMT, dev, NULL);
+               res = ntfs_fuse_create(path, mode, dev, NULL);
        else
                res = ntfs_fuse_create_stream(path, stream_name,
                                stream_name_len);
@@ -1264,7 +1417,7 @@ static int ntfs_fuse_mkdir(const char *path,
 {
        if (ntfs_fuse_is_named_data_stream(path))
                return -EINVAL; /* n/a for named data streams. */
-       return ntfs_fuse_create(path, S_IFDIR, 0, NULL);
+       return ntfs_fuse_create(path, mode | S_IFDIR, 0, NULL);
 }
 
 static int ntfs_fuse_rmdir(const char *path)

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to