From: Eric Biggers Date: Tue, 21 Aug 2012 17:31:29 +0000 (-0500) Subject: NTFS apply (IN PROGRESS) X-Git-Tag: v1.0.0~105 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=049d2a78dc4003ce70d44d373258ad7172812601 NTFS apply (IN PROGRESS) --- diff --git a/src/ntfs.c b/src/ntfs.c index fa3607c0..9074f44d 100644 --- a/src/ntfs.c +++ b/src/ntfs.c @@ -20,10 +20,13 @@ #include "config.h" #include "wimlib_internal.h" + #ifdef WITH_NTFS_3G #include "dentry.h" #include #include +#include +#include #include struct ntfs_apply_args { @@ -34,6 +37,57 @@ struct ntfs_apply_args { struct ntfs_inode *parent; }; +/* + * Initializations before calling ntfs_get_file_security() + * ntfs_set_file_security() and ntfs_read_directory() + * + * Returns an (obscured) struct SECURITY_API* needed for further calls + * NULL if device is mounted (EBUSY) + */ + +static struct SECURITY_API *_ntfs_initialize_file_security(const char *device, + unsigned long flags) +{ + ntfs_volume *vol; + unsigned long mntflag; + int mnt; + struct SECURITY_API *scapi; + struct SECURITY_CONTEXT *scx; + + scapi = (struct SECURITY_API*)NULL; + mnt = ntfs_check_if_mounted(device, &mntflag); + if (!mnt && !(mntflag & NTFS_MF_MOUNTED)) { + vol = ntfs_mount(device, flags); + if (vol) { + scapi = (struct SECURITY_API*) + ntfs_malloc(sizeof(struct SECURITY_API)); + if (!ntfs_volume_get_free_space(vol) + && scapi) { + scapi->magic = MAGIC_API; + scapi->seccache = (struct PERMISSIONS_CACHE*)NULL; + scx = &scapi->security; + scx->vol = vol; + scx->uid = 0; + scx->gid = 0; + scx->pseccache = &scapi->seccache; + scx->vol->secure_flags = (1 << SECURITY_DEFAULT) | + (1 << SECURITY_RAW); + ntfs_open_secure(vol); + ntfs_build_mapping(scx,(const char*)NULL,TRUE); + } else { + if (scapi) + free(scapi); + else + errno = ENOMEM; + mnt = ntfs_umount(vol,FALSE); + scapi = (struct SECURITY_API*)NULL; + } + } + } else + errno = EBUSY; + return (scapi); +} + static int ntfs_apply_dentry(struct dentry *dentry, void *arg) { struct ntfs_apply_args *args = arg; @@ -43,6 +97,9 @@ static int ntfs_apply_dentry(struct dentry *dentry, void *arg) int flags = args->flags; int ret = 0; ntfs_inode *dir_ni, *ni; + le32 secid; + + DEBUG("Applying `%s'", dentry->full_path_utf8); if (dentry_is_root(dentry)) return 0; @@ -56,9 +113,14 @@ static int ntfs_apply_dentry(struct dentry *dentry, void *arg) do { p--; } while (*p != '/'); + char orig = *p; *p = '\0'; - const char *dir_name = dentry->full_path_utf8; + const char *dir_name; + if (p == dentry->full_path_utf8) + dir_name = "/"; + else + dir_name = dentry->full_path_utf8; dir_ni = ntfs_pathname_to_inode(vol, NULL, dir_name); if (!dir_ni) { @@ -67,45 +129,94 @@ static int ntfs_apply_dentry(struct dentry *dentry, void *arg) dir_name); goto out; } + DEBUG("Found NTFS inode for `%s'", dir_name); + *p = orig; ret = 0; + secid = 0; if (dentry_is_regular_file(dentry)) { ni = ntfs_create(dir_ni, 0, (ntfschar*)dentry->file_name, - dentry->file_name_len, S_IFREG); + dentry->file_name_len / 2, S_IFREG); } else if (dentry_is_directory(dentry)) { ni = ntfs_create(dir_ni, 0, (ntfschar*)dentry->file_name, - dentry->file_name_len, S_IFDIR); + dentry->file_name_len / 2, S_IFDIR); } else { + wimlib_assert(0); goto out; } if (!ni) { + *p = orig; ERROR_WITH_ERRNO("Could not create NTFS object for `%s'", dentry->full_path_utf8); ret = WIMLIB_ERR_NTFS_3G; goto out; } + if (ntfs_inode_close_in_dir(ni, dir_ni) != 0) { + ERROR_WITH_ERRNO("Failed to close new inode"); + ret = WIMLIB_ERR_NTFS_3G; + goto out; + } else { + DEBUG("Closed inode `%s'", dentry->full_path_utf8); + } + if (ntfs_inode_close(dir_ni) != 0) { + ret = WIMLIB_ERR_NTFS_3G; + ERROR_WITH_ERRNO("Failed to close directory inode"); + goto out; + } else { + DEBUG("Closed parent inode"); + } + if (dentry->security_id != -1) { + wimlib_assert(dentry->security_id < sd->num_entries); + DEBUG("Applying security descriptor %d to `%s'", + dentry->security_id, dentry->full_path_utf8); + ret = ntfs_set_file_security(scapi, dentry->full_path_utf8, + ~0, + sd->descriptors[dentry->security_id]); + if (ret != 0) { + ERROR_WITH_ERRNO("Failed to set security data on `%s'", + dentry->full_path_utf8); + ret = WIMLIB_ERR_NTFS_3G; + goto out; + } + } + DEBUG("Setting file attributes 0x%x on `%s'", + dentry->attributes, dentry->full_path_utf8); + if (!ntfs_set_file_attributes(scapi, dentry->full_path_utf8, + dentry->attributes)) { + ERROR_WITH_ERRNO("Failed to set NTFS file attributes on `%s'", + dentry->full_path_utf8); + ret = WIMLIB_ERR_NTFS_3G; + goto out; + } out: - *p = orig; return ret; } static int do_ntfs_apply(WIMStruct *w, const char *device, int flags) { struct SECURITY_API *scapi; + int ret; - scapi = ntfs_initialize_file_security(device, 0); + scapi = _ntfs_initialize_file_security(device, 0); if (!scapi) { ERROR_WITH_ERRNO("Failed to initialize NTFS file security API " "on NTFS volume `%s'", device); + return WIMLIB_ERR_NTFS_3G; } struct ntfs_apply_args args = { .scapi = scapi, - .vol = scapi->security.vol, - .sd = wim_security_data(w), + .vol = scapi->security.vol, + .sd = wim_security_data(w), .flags = flags, }; - return for_dentry_in_tree(wim_root_dentry(w), ntfs_apply_dentry, - &args); + ret = for_dentry_in_tree(wim_root_dentry(w), ntfs_apply_dentry, + &args); +out: + if (!ntfs_leave_file_security(scapi)) { + ERROR_WITH_ERRNO("Failed to leave file security"); + ret = WIMLIB_ERR_NTFS_3G; + } + return ret; } WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image, @@ -129,14 +240,14 @@ WIMLIBAPI int wimlib_apply_image_to_ntfs_volume(WIMStruct *w, int image, if (ret != 0) return ret; - if (getuid() != 0) { - ERROR("We are not root, but NTFS-3g requires root privileges to set arbitrary"); - ERROR("security data on the NTFS filesystem. Please run this program as root"); - ERROR("if you want to extract a WIM image while preserving NTFS-specific"); - ERROR("information."); + /*if (getuid() != 0) {*/ + /*ERROR("We are not root, but NTFS-3g requires root privileges to set arbitrary");*/ + /*ERROR("security data on the NTFS filesystem. Please run this program as root");*/ + /*ERROR("if you want to extract a WIM image while preserving NTFS-specific");*/ + /*ERROR("information.");*/ - return WIMLIB_ERR_NOT_ROOT; - } + /*return WIMLIB_ERR_NOT_ROOT;*/ + /*}*/ return do_ntfs_apply(w, device, flags); }