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)
signature.asc
Description: OpenPGP digital signature