hrev46483 adds 3 changesets to branch 'master' old head: 9e47d4f714a395d060ecb4113042532bdb82ebcb new head: 5287b8a778715de8320fe2bd932ceab5c185cc41 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=5287b8a+%5E9e47d4f ---------------------------------------------------------------------------- da0906f: ntfs: Update ntfs3g 0d4e157: ntfs: Fix several warnings 5287b8a: ntfs: Directory position must be signed [ Gerasim Troeglazov <3dEyes@xxxxxxxxx> ] ---------------------------------------------------------------------------- 25 files changed, 728 insertions(+), 460 deletions(-) src/add-ons/kernel/file_systems/ntfs/fs_func.c | 6 +- .../kernel/file_systems/ntfs/libntfs/acls.c | 170 ++++++++++++---- .../kernel/file_systems/ntfs/libntfs/acls.h | 3 +- .../kernel/file_systems/ntfs/libntfs/attrib.c | 38 ++-- .../kernel/file_systems/ntfs/libntfs/attrib.h | 15 +- .../kernel/file_systems/ntfs/libntfs/bootsect.c | 4 +- .../kernel/file_systems/ntfs/libntfs/compat.h | 6 + .../kernel/file_systems/ntfs/libntfs/dir.c | 173 ++++++++++++++--- .../kernel/file_systems/ntfs/libntfs/dir.h | 13 +- .../kernel/file_systems/ntfs/libntfs/layout.h | 25 +-- .../kernel/file_systems/ntfs/libntfs/list.h | 192 ------------------- .../kernel/file_systems/ntfs/libntfs/logfile.c | 20 +- .../kernel/file_systems/ntfs/libntfs/logging.c | 18 +- .../kernel/file_systems/ntfs/libntfs/logging.h | 4 +- .../kernel/file_systems/ntfs/libntfs/object_id.c | 1 + .../kernel/file_systems/ntfs/libntfs/param.h | 10 + .../kernel/file_systems/ntfs/libntfs/reparse.c | 54 ++++-- .../kernel/file_systems/ntfs/libntfs/security.c | 169 ++++++++++++++-- .../kernel/file_systems/ntfs/libntfs/security.h | 2 + .../kernel/file_systems/ntfs/libntfs/unistr.c | 6 +- .../kernel/file_systems/ntfs/libntfs/volume.c | 139 +++++++++++--- .../kernel/file_systems/ntfs/libntfs/volume.h | 44 ++--- src/add-ons/kernel/file_systems/ntfs/ntfsdir.h | 2 +- .../kernel/file_systems/ntfs/utils/utils.c | 73 +------ .../kernel/file_systems/ntfs/utils/utils.h | 1 - ############################################################################ Commit: da0906f232bbb77a42c8ef4bcce42fec93f7e7c4 URL: http://cgit.haiku-os.org/haiku/commit/?id=da0906f Author: Gerasim Troeglazov <3dEyes@xxxxxxxxx> Date: Wed Dec 4 12:20:24 2013 UTC ntfs: Update ntfs3g ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/ntfs/fs_func.c b/src/add-ons/kernel/file_systems/ntfs/fs_func.c index 430922d..a6919ce 100644 --- a/src/add-ons/kernel/file_systems/ntfs/fs_func.c +++ b/src/add-ons/kernel/file_systems/ntfs/fs_func.c @@ -264,7 +264,7 @@ fs_identify_partition(int fd, partition_data *partition, void **_cookie) // get path for device if (ioctl(fd, B_GET_PATH_FOR_DEVICE, devpath) != 0) { // try mount - ntVolume = utils_mount_volume(devpath, MS_RDONLY | MS_RECOVER); + ntVolume = utils_mount_volume(devpath, NTFS_MNT_RDONLY | NTFS_MNT_RECOVER); if (ntVolume != NULL) { if (ntVolume->vol_name && ntVolume->vol_name[0] != '\0') strcpy(cookie->label, ntVolume->vol_name); @@ -384,7 +384,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args, if (ns->ro || (flags & B_MOUNT_READ_ONLY) != 0 || is_device_read_only(device)) { - mountFlags |= MS_RDONLY; + mountFlags |= NTFS_MNT_RDONLY; ns->flags |= B_FS_IS_READONLY; } @@ -418,7 +418,7 @@ fs_mount(fs_volume *_vol, const char *device, ulong flags, const char *args, gNTFSVnodeOps.remove_attr = fs_remove_attrib; } - ns->ntvol = utils_mount_volume(device, mountFlags | MS_RECOVER); + ns->ntvol = utils_mount_volume(device, mountFlags | NTFS_MNT_RECOVER); if (ns->ntvol != NULL) result = B_NO_ERROR; else 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 788ed03..fb6e877 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-2010 Jean-Pierre Andre + * Copyright (c) 2007-2012 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 @@ -108,7 +108,6 @@ #include "secaudit.h" #endif /* HAVE_CONFIG_H */ - #ifdef __HAIKU__ #define getgrnam(x) NULL #define getpwnam(x) NULL @@ -142,6 +141,19 @@ static const char worldsidbytes[] = { 0, 0, 0, 0 /* 1st level */ } ; +/* + * SID for authenticated user (S-1-5-11) + */ + +static const char authsidbytes[] = { + 1, /* revision */ + 1, /* auth count */ + 0, 0, 0, 0, 0, 5, /* base */ + 11, 0, 0, 0 /* 1st level */ +}; + +static const SID *authsid = (const SID*)authsidbytes; + const SID *worldsid = (const SID*)worldsidbytes; /* @@ -241,6 +253,12 @@ static int is_world_sid(const SID * usid) && (usid->identifier_authority.low_part == const_cpu_to_be32(5)) && (usid->sub_authority[0] == const_cpu_to_le32(32)) && (usid->sub_authority[1] == const_cpu_to_le32(545))) + + /* check whether S-1-5-11 : authenticated 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(11))) ); } @@ -629,7 +647,7 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz) && (offdacl+sizeof(ACL) < attrsz))) && (!offsacl || ((offsacl >= sizeof(SECURITY_DESCRIPTOR_RELATIVE)) - && (offsacl+sizeof(ACL) < attrsz))) + && (offsacl+sizeof(ACL) <= attrsz))) && !(phead->owner & const_cpu_to_le32(3)) && !(phead->group & const_cpu_to_le32(3)) && !(phead->dacl & const_cpu_to_le32(3)) @@ -670,7 +688,8 @@ BOOL ntfs_valid_descr(const char *securattr, unsigned int attrsz) */ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, - const SID *usid, const SID *gsid, BOOL fordir) + const SID *usid, const SID *gsid, BOOL fordir, + le16 inherited) { unsigned int src; unsigned int dst; @@ -683,7 +702,9 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, int gsidsz; const ACCESS_ALLOWED_ACE *poldace; ACCESS_ALLOWED_ACE *pnewace; + ACCESS_ALLOWED_ACE *pauthace; + pauthace = (ACCESS_ALLOWED_ACE*)NULL; usidsz = ntfs_sid_size(usid); gsidsz = ntfs_sid_size(gsid); @@ -700,25 +721,19 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, for (nace = 0; nace < oldcnt; nace++) { poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src); acesz = le16_to_cpu(poldace->size); - /* inheritance for access */ - if (poldace->flags & selection) { + src += acesz; + /* + * Inheritance for access, unless this is inheriting + * an inherited ACL to a directory. + */ + if ((poldace->flags & selection) + && !(fordir && inherited) + && !ntfs_same_sid(&poldace->sid, ownersid) + && !ntfs_same_sid(&poldace->sid, groupsid)) { pnewace = (ACCESS_ALLOWED_ACE*) ((char*)newacl + dst); memcpy(pnewace,poldace,acesz); - /* - * Replace generic creator-owner and - * creator-group by owner and group - */ - if (ntfs_same_sid(&pnewace->sid, ownersid)) { - memcpy(&pnewace->sid, usid, usidsz); - acesz = usidsz + 8; - pnewace->size = cpu_to_le16(acesz); - } - if (ntfs_same_sid(&pnewace->sid, groupsid)) { - memcpy(&pnewace->sid, gsid, gsidsz); - acesz = gsidsz + 8; - pnewace->size = cpu_to_le16(acesz); - } + /* reencode GENERIC_ALL */ if (pnewace->mask & GENERIC_ALL) { pnewace->mask &= ~GENERIC_ALL; if (fordir) @@ -737,16 +752,70 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, | FILE_EXEC | cpu_to_le32(0x40); } + /* reencode GENERIC_READ (+ EXECUTE) */ + if (pnewace->mask & GENERIC_READ) { + if (fordir) + pnewace->mask |= OWNER_RIGHTS + | DIR_READ + | DIR_EXEC; + else + pnewace->mask |= OWNER_RIGHTS + | FILE_READ + | FILE_EXEC; + pnewace->mask &= ~(GENERIC_READ + | GENERIC_EXECUTE + | WRITE_DAC + | WRITE_OWNER + | DELETE | FILE_WRITE_EA + | FILE_WRITE_ATTRIBUTES); + } + /* reencode GENERIC_WRITE */ + if (pnewace->mask & GENERIC_WRITE) { + if (fordir) + pnewace->mask |= OWNER_RIGHTS + | DIR_WRITE; + else + pnewace->mask |= OWNER_RIGHTS + | FILE_WRITE; + pnewace->mask &= ~(GENERIC_WRITE + | WRITE_DAC + | WRITE_OWNER + | FILE_DELETE_CHILD); + } /* remove inheritance flags */ pnewace->flags &= ~(OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE); - dst += acesz; - newcnt++; + /* + * Group similar ACE for authenticated users + * (should probably be done for other SIDs) + */ + if (!fordir + && (poldace->type == ACCESS_ALLOWED_ACE_TYPE) + && ntfs_same_sid(&poldace->sid, authsid)) { + if (pauthace) { + pauthace->flags |= pnewace->flags; + pauthace->mask |= pnewace->mask; + } else { + pauthace = pnewace; + if (inherited) + pnewace->flags |= INHERITED_ACE; + dst += acesz; + newcnt++; + } + } else { + if (inherited) + pnewace->flags |= INHERITED_ACE; + dst += acesz; + newcnt++; + } } - /* inheritance for further inheritance */ - if (fordir - && (poldace->flags + /* + * Inheritance for access, specific to + * creator-owner (and creator-group) + */ + if (fordir || !inherited + || (poldace->flags & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) { pnewace = (ACCESS_ALLOWED_ACE*) ((char*)newacl + dst); @@ -754,19 +823,46 @@ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, /* * Replace generic creator-owner and * creator-group by owner and group + * (but keep for further inheritance) */ if (ntfs_same_sid(&pnewace->sid, ownersid)) { memcpy(&pnewace->sid, usid, usidsz); - acesz = usidsz + 8; + pnewace->size = cpu_to_le16(usidsz + 8); + /* remove inheritance flags */ + pnewace->flags &= ~(OBJECT_INHERIT_ACE + | CONTAINER_INHERIT_ACE + | INHERIT_ONLY_ACE); + if (inherited) + pnewace->flags |= INHERITED_ACE; + dst += usidsz + 8; + newcnt++; } if (ntfs_same_sid(&pnewace->sid, groupsid)) { memcpy(&pnewace->sid, gsid, gsidsz); - acesz = gsidsz + 8; + pnewace->size = cpu_to_le16(gsidsz + 8); + /* remove inheritance flags */ + pnewace->flags &= ~(OBJECT_INHERIT_ACE + | CONTAINER_INHERIT_ACE + | INHERIT_ONLY_ACE); + if (inherited) + pnewace->flags |= INHERITED_ACE; + dst += gsidsz + 8; + newcnt++; } + } + + /* inheritance for further inheritance */ + if (fordir + && (poldace->flags + & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))) { + pnewace = (ACCESS_ALLOWED_ACE*) + ((char*)newacl + dst); + memcpy(pnewace,poldace,acesz); + if (inherited) + pnewace->flags |= INHERITED_ACE; dst += acesz; newcnt++; } - src += acesz; } /* * Adjust header if something was inherited @@ -3065,6 +3161,7 @@ static int build_owngrp_permissions(const char *securattr, int nace; le32 special; BOOL grppresent; + BOOL ownpresent; le32 allowown, allowgrp, allowall; le32 denyown, denygrp, denyall; @@ -3074,21 +3171,26 @@ static int build_owngrp_permissions(const char *securattr, special = const_cpu_to_le32(0); allowown = allowgrp = allowall = const_cpu_to_le32(0); denyown = denygrp = denyall = const_cpu_to_le32(0); + ownpresent = FALSE; grppresent = FALSE; if (offdacl) { acecnt = le16_to_cpu(pacl->ace_count); offace = offdacl + sizeof(ACL); - } else + } else { acecnt = 0; + offace = 0; + } for (nace = 0; nace < acecnt; nace++) { pace = (const ACCESS_ALLOWED_ACE*)&securattr[offace]; if (!(pace->flags & INHERIT_ONLY_ACE)) { if ((ntfs_same_sid(usid, &pace->sid) || ntfs_same_sid(ownersid, &pace->sid)) && (pace->mask & WRITE_OWNER)) { - if (pace->type == ACCESS_ALLOWED_ACE_TYPE) + if (pace->type == ACCESS_ALLOWED_ACE_TYPE) { allowown |= pace->mask; - } else + ownpresent = TRUE; + } + } else if (ntfs_same_sid(usid, &pace->sid) && (!(pace->mask & WRITE_OWNER))) { if (pace->type == ACCESS_ALLOWED_ACE_TYPE) { @@ -3109,6 +3211,8 @@ static int build_owngrp_permissions(const char *securattr, } offace += le16_to_cpu(pace->size); } + if (!ownpresent) + allowown = allowall; if (!grppresent) allowgrp = allowall; return (merge_permissions(isdir, @@ -3711,7 +3815,7 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix( pxace->perms |= POSIX_PERM_DENIAL; else if (pxace->tag == POSIX_ACL_OTHER) - pctx->permswrld = pxace->perms; + pctx->permswrld |= pxace->perms; pctx->tagsset |= pxace->tag; if (pace->flags & INHERIT_ONLY_ACE) { l--; @@ -3901,7 +4005,6 @@ 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 ! */ @@ -3914,7 +4017,6 @@ static unsigned long atoul(const char *p) } #endif - /* * Build an internal representation of a SID * Returns a copy in allocated memory if it succeeds 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 8a83d32..4b08388 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/acls.h @@ -185,7 +185,8 @@ char *ntfs_build_descr_posix(struct MAPPING* const mapping[], #endif /* POSIXACLS */ int ntfs_inherit_acl(const ACL *oldacl, ACL *newacl, - const SID *usid, const SID *gsid, BOOL fordir); + const SID *usid, const SID *gsid, + BOOL fordir, le16 inherited); int ntfs_build_permissions(const char *securattr, const SID *usid, const SID *gsid, BOOL isdir); char *ntfs_build_descr(mode_t mode, 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 281a620..c116d9a 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.c @@ -1849,6 +1849,13 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b) ntfs_log_perror("Failed to enlarge attribute"); goto errno_set; } + /* + * If we avoided updating the runlist, we must be sure + * to cancel the enlargement and put back the runlist to + * a clean state if we get into some error. + */ + if (NAttrDataAppending(na)) + need_to.undo_data_size = 1; #else if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) { ntfs_log_perror("Failed to enlarge attribute"); @@ -3732,8 +3739,8 @@ int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size) * EIO - I/O error occurred or damaged filesystem. */ int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, u32 size, - ATTR_FLAGS data_flags) + const ntfschar *name, u8 name_len, const u8 *val, + u32 size, ATTR_FLAGS data_flags) { ntfs_attr_search_ctx *ctx; u32 length; @@ -3864,7 +3871,7 @@ put_err_out: * EIO - I/O error occurred or damaged filesystem. */ int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, + const ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, ATTR_FLAGS flags) { ntfs_attr_search_ctx *ctx; @@ -4147,7 +4154,7 @@ int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx) * On success return 0. On error return -1 with errno set to the error code. */ int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, s64 size) + ntfschar *name, u8 name_len, const u8 *val, s64 size) { u32 attr_rec_size; int err, i, offset; @@ -4342,8 +4349,8 @@ err_out: * Change an attribute flag */ -int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask) +int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, const ntfschar *name, + u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask) { ntfs_attr_search_ctx *ctx; int res; @@ -6232,10 +6239,18 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize, /* Prepare to mapping pairs update. */ na->allocated_size = first_free_vcn << vol->cluster_size_bits; - /* Write mapping pairs for new runlist. */ #if PARTIAL_RUNLIST_UPDATING - if (ntfs_attr_update_mapping_pairs_i(na, start_update, holes)) { + /* + * Write mapping pairs for new runlist, unless this is + * a temporary state before appending data. + * If the update is not done, we must be sure to do + * it later, and to get to a clean state even on errors. + */ + if ((holes != HOLES_DELAY) + && ntfs_attr_update_mapping_pairs_i(na, start_update, + holes)) { #else + /* Write mapping pairs for new runlist. */ if (ntfs_attr_update_mapping_pairs(na, 0)) { #endif err = errno; @@ -6646,9 +6661,8 @@ exit: * Returns the amount of data written, negative if there was an error */ -int ntfs_attr_data_write(ntfs_inode *ni, - ntfschar *stream_name, int stream_name_len, - char *buf, size_t size, off_t offset) +int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name, + int stream_name_len, const char *buf, size_t size, off_t offset) { ntfs_attr *na = NULL; int res, total = 0; @@ -6680,7 +6694,7 @@ exit: } -int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, +int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, const ntfschar *name, u32 name_len) { ntfs_attr_search_ctx *ctx; 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 67fb957..1979ba6 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/attrib.h @@ -320,17 +320,18 @@ int ntfs_attr_force_non_resident(ntfs_attr *na); extern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size); extern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, u32 size, + const ntfschar *name, u8 name_len, const u8 *val, u32 size, ATTR_FLAGS flags); extern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size, - ATTR_FLAGS flags); + const ntfschar *name, u8 name_len, VCN lowest_vcn, + int dataruns_size, ATTR_FLAGS flags); extern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx); extern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, u8 *val, s64 size); + ntfschar *name, u8 name_len, const u8 *val, s64 size); extern int ntfs_attr_set_flags(ntfs_inode *ni, ATTR_TYPES type, - ntfschar *name, u8 name_len, ATTR_FLAGS flags, ATTR_FLAGS mask); + const ntfschar *name, u8 name_len, ATTR_FLAGS flags, + ATTR_FLAGS mask); extern int ntfs_attr_rm(ntfs_attr *na); extern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size); @@ -379,7 +380,7 @@ extern s64 ntfs_get_attribute_value(const ntfs_volume *vol, extern void ntfs_attr_name_free(char **name); extern char *ntfs_attr_name_get(const ntfschar *uname, const int uname_len); extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, - ntfschar *name, u32 name_len); + const ntfschar *name, u32 name_len); extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, u32 name_len); extern s64 ntfs_attr_get_free_bits(ntfs_attr *na); @@ -388,7 +389,7 @@ extern int ntfs_attr_data_read(ntfs_inode *ni, char *buf, size_t size, off_t offset); extern int ntfs_attr_data_write(ntfs_inode *ni, ntfschar *stream_name, int stream_name_len, - char *buf, size_t size, off_t offset); + const char *buf, size_t size, off_t offset); #endif /* defined _NTFS_ATTRIB_H */ 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 e9bea37..e9be072 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/bootsect.c @@ -215,8 +215,8 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) vol->mftmirr_lcn = sle64_to_cpu(bs->mftmirr_lcn); ntfs_log_debug("MFT LCN = %lld\n", (long long)vol->mft_lcn); ntfs_log_debug("MFTMirr LCN = %lld\n", (long long)vol->mftmirr_lcn); - if (vol->mft_lcn > vol->nr_clusters || - vol->mftmirr_lcn > vol->nr_clusters) { + if ((vol->mft_lcn < 0 || vol->mft_lcn > vol->nr_clusters) || + (vol->mftmirr_lcn < 0 || vol->mftmirr_lcn > vol->nr_clusters)) { ntfs_log_error("$MFT LCN (%lld) or $MFTMirr LCN (%lld) is " "greater than the number of clusters (%lld).\n", (long long)vol->mft_lcn, (long long)vol->mftmirr_lcn, 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 04767b0..cc84670 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/compat.h @@ -31,6 +31,12 @@ #include <sys/param.h> #endif +#include <errno.h> /* ENODATA */ + +#ifndef ENODATA +#define ENODATA ENOENT +#endif + #ifndef PATH_MAX #define PATH_MAX 4096 #endif diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c index ccae47c..d5f08f2 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.c @@ -867,6 +867,87 @@ typedef enum { INDEX_TYPE_ALLOCATION, /* index allocation */ } INDEX_TYPE; +/* + * Decode Interix file types + * + * Non-Interix types are returned as plain files, because a + * Windows user may force patterns very similar to Interix, + * and most metadata files have such similar patters. + */ + +static u32 ntfs_interix_types(ntfs_inode *ni) +{ + ntfs_attr *na; + u32 dt_type; + le64 magic; + + dt_type = NTFS_DT_UNKNOWN; + na = ntfs_attr_open(ni, AT_DATA, NULL, 0); + if (na) { + /* Unrecognized patterns (eg HID + SYST) are plain files */ + dt_type = NTFS_DT_REG; + if (na->data_size <= 1) { + if (!(ni->flags & FILE_ATTR_HIDDEN)) + dt_type = (na->data_size ? + NTFS_DT_SOCK : NTFS_DT_FIFO); + } else { + if ((na->data_size >= (s64)sizeof(magic)) + && (ntfs_attr_pread(na, 0, sizeof(magic), &magic) + == sizeof(magic))) { + if (magic == INTX_SYMBOLIC_LINK) + dt_type = NTFS_DT_LNK; + else if (magic == INTX_BLOCK_DEVICE) + dt_type = NTFS_DT_BLK; + else if (magic == INTX_CHARACTER_DEVICE) + dt_type = NTFS_DT_CHR; + } + } + ntfs_attr_close(na); + } + return (dt_type); +} + +/* + * Decode file types + * + * Better only use for Interix types and junctions, + * unneeded complexity when used for plain files or directories + * + * Error cases are logged and returned as unknown. + */ + +static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref, + FILE_ATTR_FLAGS attributes) +{ + ntfs_inode *ni; + u32 dt_type; + + dt_type = NTFS_DT_UNKNOWN; + ni = ntfs_inode_open(dir_ni->vol, mref); + if (ni) { + if ((attributes & FILE_ATTR_REPARSE_POINT) + && ntfs_possible_symlink(ni)) + dt_type = NTFS_DT_LNK; + else + if ((attributes & FILE_ATTR_SYSTEM) + && !(attributes & FILE_ATTR_I30_INDEX_PRESENT)) + dt_type = ntfs_interix_types(ni); + else + dt_type = (attributes + & FILE_ATTR_I30_INDEX_PRESENT + ? NTFS_DT_DIR : NTFS_DT_REG); + if (ntfs_inode_close(ni)) { + /* anything special worth doing ? */ + ntfs_log_error("Failed to close inode %lld\n", + (long long)MREF(mref)); + } + } + if (dt_type == NTFS_DT_UNKNOWN) + ntfs_log_error("Could not decode the type of inode %lld\n", + (long long)MREF(mref)); + return (dt_type); +} + /** * ntfs_filldir - ntfs specific filldir method * @dir_ni: ntfs inode of current directory @@ -901,19 +982,23 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits, dir_ni->vol->mft_record_size; else /* if (index_type == INDEX_TYPE_ROOT) */ *pos = (u8*)ie - (u8*)iu.ir; + mref = le64_to_cpu(ie->indexed_file); + metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); /* Skip root directory self reference entry. */ if (MREF_LE(ie->indexed_file) == FILE_root) return 0; - if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT) + if ((ie->key.file_name.file_attributes + & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM)) + && !metadata) + dt_type = ntfs_dir_entry_type(dir_ni, mref, + ie->key.file_name.file_attributes); + else if (ie->key.file_name.file_attributes + & FILE_ATTR_I30_INDEX_PRESENT) dt_type = NTFS_DT_DIR; - else if (fn->file_attributes & FILE_ATTR_SYSTEM) - dt_type = NTFS_DT_UNKNOWN; else dt_type = NTFS_DT_REG; /* return metadata files and hidden files if requested */ - mref = le64_to_cpu(ie->indexed_file); - metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user); if ((!metadata && (NVolShowHidFiles(dir_ni->vol) || !(fn->file_attributes & FILE_ATTR_HIDDEN))) || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol) @@ -962,7 +1047,7 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits, * Return the mft reference of the parent directory on success or -1 on error * with errno set to the error code. */ -static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) +MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) { MFT_REF mref; ntfs_attr_search_ctx *ctx; @@ -1397,8 +1482,8 @@ err_out: * on error with errno set to the error code. */ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, mode_t type, dev_t dev, - ntfschar *target, int target_len) + const ntfschar *name, u8 name_len, mode_t type, dev_t dev, + const ntfschar *target, int target_len) { ntfs_inode *ni; int rollback_data = 0, rollback_sd = 0; @@ -1667,7 +1752,7 @@ err_out: * Some wrappers around __ntfs_create() ... */ -ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name, +ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name, u8 name_len, mode_t type) { if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO && @@ -1679,7 +1764,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name, } ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, mode_t type, dev_t dev) + const ntfschar *name, u8 name_len, mode_t type, dev_t dev) { if (type != S_IFCHR && type != S_IFBLK) { ntfs_log_error("Invalid arguments.\n"); @@ -1689,7 +1774,8 @@ ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, } ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, ntfschar *target, int target_len) + const ntfschar *name, u8 name_len, const ntfschar *target, + int target_len) { if (!target || !target_len) { ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__, @@ -1764,7 +1850,8 @@ no_hardlink: * Return 0 on success or -1 on error with errno set to the error code. */ int ntfs_delete(ntfs_volume *vol, const char *pathname, - ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) + ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, + u8 name_len) { ntfs_attr_search_ctx *actx = NULL; FILE_NAME_ATTR *fn = NULL; @@ -1878,8 +1965,18 @@ search: if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length))) goto err_out; - if (ntfs_attr_record_rm(actx)) - goto err_out; + /* + * Keep the last name in place, this is useful for undeletion + * (Windows also does so), however delete the name if it were + * in an extent, to avoid leaving an attribute list. + */ + if ((ni->mrec->link_count == cpu_to_le16(1)) && !actx->base_ntfs_ino) { + /* make sure to not loop to another search */ + looking_for_dos_name = FALSE; + } else { + if (ntfs_attr_record_rm(actx)) + goto err_out; + } ni->mrec->link_count = cpu_to_le16(le16_to_cpu( ni->mrec->link_count) - 1); @@ -2002,6 +2099,7 @@ search: "Leaving inconsistent metadata.\n"); } #endif + debug_double_inode(ni->mft_no,0); if (ntfs_mft_record_free(ni->vol, ni)) { err = errno; ntfs_log_error("Failed to free base MFT record. " @@ -2044,7 +2142,7 @@ err_out: * * Return 0 on success or -1 on error with errno set to the error code. */ -static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, +static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, u8 name_len, FILE_NAME_TYPE_FLAGS nametype) { FILE_NAME_ATTR *fn = NULL; @@ -2064,6 +2162,15 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, err = EOPNOTSUPP; goto err_out; } + if (NVolHideDotFiles(dir_ni->vol)) { + /* Set hidden flag according to the latest name */ + if ((name_len > 1) + && (name[0] == const_cpu_to_le16('.')) + && (name[1] != const_cpu_to_le16('.'))) + ni->flags |= FILE_ATTR_HIDDEN; + else + ni->flags &= ~FILE_ATTR_HIDDEN; + } /* Create FILE_NAME attribute. */ fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); @@ -2121,7 +2228,8 @@ err_out: return -1; } -int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len) +int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, + u8 name_len) { return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX)); } @@ -2172,6 +2280,8 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni) /* * Get a DOS name for a file in designated directory * + * Not allowed if there are several non-dos names (EMLINK) + * * Returns size if found * 0 if not found * -1 if there was an error (described by errno) @@ -2180,6 +2290,7 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni) static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) { size_t outsize = 0; + int namecount = 0; FILE_NAME_ATTR *fn; ntfs_attr_search_ctx *ctx; @@ -2194,6 +2305,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); + if (fn->file_name_type != FILE_NAME_DOS) + namecount++; if ((fn->file_name_type & FILE_NAME_DOS) && (MREF_LE(fn->parent_directory) == dnum)) { /* @@ -2208,6 +2321,10 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) } } ntfs_attr_put_search_ctx(ctx); + if ((outsize > 0) && (namecount > 1)) { + outsize = -1; + errno = EMLINK; /* this error implies there is a dos name */ + } return (outsize); } @@ -2215,6 +2332,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) /* * Get a long name for a file in designated directory * + * Not allowed if there are several non-dos names (EMLINK) + * * Returns size if found * 0 if not found * -1 if there was an error (described by errno) @@ -2223,6 +2342,7 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname) static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname) { size_t outsize = 0; + int namecount = 0; FILE_NAME_ATTR *fn; ntfs_attr_search_ctx *ctx; @@ -2238,6 +2358,8 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname) fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + le16_to_cpu(ctx->attr->value_offset)); + if (fn->file_name_type != FILE_NAME_DOS) + namecount++; if ((fn->file_name_type & FILE_NAME_WIN32) && (MREF_LE(fn->parent_directory) == dnum)) { /* @@ -2248,6 +2370,11 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname) memcpy(longname,fn->file_name,outsize*sizeof(ntfschar)); } } + if (namecount > 1) { + ntfs_attr_put_search_ctx(ctx); + errno = EMLINK; + return -1; + } /* if not found search for POSIX names */ if (!outsize) { ntfs_attr_reinit_search_ctx(ctx); @@ -2324,7 +2451,7 @@ int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, */ static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni, - ntfschar *name, int len, + const ntfschar *name, int len, FILE_NAME_TYPE_FLAGS nametype) { ntfs_attr_search_ctx *actx; @@ -2398,9 +2525,9 @@ static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni, */ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, - ntfschar *shortname, int shortlen, - ntfschar *longname, int longlen, - ntfschar *deletename, int deletelen, BOOL existed) + const ntfschar *shortname, int shortlen, + const ntfschar *longname, int longlen, + const ntfschar *deletename, int deletelen, BOOL existed) { unsigned int linkcount; ntfs_volume *vol; @@ -2568,7 +2695,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, res = -1; } else { res = -1; - errno = ENOENT; + if (!longlen) + errno = ENOENT; } free(shortname); if (!closed) { @@ -2644,7 +2772,8 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni) } } } else { - errno = ENOENT; + if (!longlen) + errno = ENOENT; res = -1; } if (!deleted) { diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h index 02ada58..66c8782 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h @@ -74,17 +74,18 @@ extern void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, extern ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent, const char *pathname); extern ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, mode_t type); + const ntfschar *name, u8 name_len, mode_t type); extern ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, mode_t type, dev_t dev); + const ntfschar *name, u8 name_len, mode_t type, dev_t dev); extern ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid, - ntfschar *name, u8 name_len, ntfschar *target, int target_len); + const ntfschar *name, u8 name_len, const ntfschar *target, + int target_len); extern int ntfs_check_empty_dir(ntfs_inode *ni); extern int ntfs_delete(ntfs_volume *vol, const char *path, - ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, + ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, u8 name_len); -extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, +extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, u8 name_len); /* diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h index c167135..427f152 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/layout.h @@ -2398,18 +2398,19 @@ typedef enum { IO_REPARSE_TAG_RESERVED_ONE = const_cpu_to_le32(0x00000001), IO_REPARSE_TAG_RESERVED_RANGE = const_cpu_to_le32(0x00000001), - IO_REPARSE_TAG_NSS = const_cpu_to_le32(0x68000005), - IO_REPARSE_TAG_NSS_RECOVER = const_cpu_to_le32(0x68000006), - IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x68000007), - IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x68000008), - - IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0x88000003), - - IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xa8000004), - - IO_REPARSE_TAG_SYMBOLIC_LINK = const_cpu_to_le32(0xe8000000), - - IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xe000ffff), + IO_REPARSE_TAG_CSV = const_cpu_to_le32(0x80000009), + IO_REPARSE_TAG_DEDUP = const_cpu_to_le32(0x80000013), + IO_REPARSE_TAG_DFS = const_cpu_to_le32(0x8000000A), + IO_REPARSE_TAG_DFSR = const_cpu_to_le32(0x80000012), + IO_REPARSE_TAG_HSM = const_cpu_to_le32(0xC0000004), + IO_REPARSE_TAG_HSM2 = const_cpu_to_le32(0x80000006), + IO_REPARSE_TAG_MOUNT_POINT = const_cpu_to_le32(0xA0000003), + IO_REPARSE_TAG_NFS = const_cpu_to_le32(0x80000014), + IO_REPARSE_TAG_SIS = const_cpu_to_le32(0x80000007), + IO_REPARSE_TAG_SYMLINK = const_cpu_to_le32(0xA000000C), + IO_REPARSE_TAG_WIM = const_cpu_to_le32(0x80000008), + + IO_REPARSE_TAG_VALID_VALUES = const_cpu_to_le32(0xf000ffff), } PREDEFINED_REPARSE_TAGS; /** diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h deleted file mode 100644 index 415e03c..0000000 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/list.h +++ /dev/null @@ -1,192 +0,0 @@ -/* - * list.h - Linked list implementation. Originated from the Linux-NTFS project. - * - * Copyright (c) 2000-2002 Anton Altaparmakov and others - * - * 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 - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program/include file is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * 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 - */ - -#ifndef _NTFS_LIST_H -#define _NTFS_LIST_H - -/** - * struct list_head - Simple doubly linked list implementation. - * - * Copied from Linux kernel 2.4.2-ac18 into Linux-NTFS (with minor - * modifications). - AIA - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/** - * __list_add - Insert a new entry between two known consecutive entries. - * @new: - * @prev: - * @next: - * - * This is only for internal list manipulation where we know the prev/next - * entries already! - */ -static void __list_add(struct list_head * new, - struct list_head * prev, struct list_head * next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static __inline__ void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/** - * __list_del - - * @prev: - * @next: - * - * Delete a list entry by making the prev/next entries point to each other. - * - * This is only for internal list manipulation where we know the prev/next - * entries already! - */ -static __inline__ void __list_del(struct list_head * prev, - struct list_head * next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * - * Note: list_empty on entry does not return true after this, the entry is in - * an undefined state. - */ -static __inline__ void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static __inline__ void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static __inline__ int list_empty(struct list_head *head) -{ - return head->next == head; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static void list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - - if (first != list) { - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -#endif /* defined _NTFS_LIST_H */ - diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c index a4f00d5..336bdd2 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logfile.c @@ -84,13 +84,21 @@ static BOOL ntfs_check_restart_page_header(RESTART_PAGE_HEADER *rp, s64 pos) "position in $LogFile.\n"); return FALSE; } - /* We only know how to handle version 1.1. */ - if (sle16_to_cpu(rp->major_ver) != 1 || - sle16_to_cpu(rp->minor_ver) != 1) { + /* + * We only know how to handle version 1.1 and 2.0, though + * version 2.0 is probably related to cached metadata in + * Windows 8, and we will refuse to mount. + * Nevertheless, do all the relevant checks before rejecting. + */ + if (((rp->major_ver != const_cpu_to_le16(1)) + || (rp->minor_ver != const_cpu_to_le16(1))) + && ((rp->major_ver != const_cpu_to_le16(2)) + || (rp->minor_ver != const_cpu_to_le16(0)))) { ntfs_log_error("$LogFile version %i.%i is not " - "supported. (This driver supports version " - "1.1 only.)\n", (int)sle16_to_cpu(rp->major_ver), - (int)sle16_to_cpu(rp->minor_ver)); + "supported.\n (This driver supports version " + "1.1 and 2.0 only.)\n", + (int)sle16_to_cpu(rp->major_ver), + (int)sle16_to_cpu(rp->minor_ver)); return FALSE; } /* diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c index af672dc..f781ee1 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c @@ -188,7 +188,6 @@ u32 ntfs_log_clear_flags(u32 flags) return old; } -#ifndef __HAIKU__ /** * ntfs_log_get_stream - Default output streams for logging levels * @level: Log level @@ -198,6 +197,7 @@ u32 ntfs_log_clear_flags(u32 flags) * * Returns: "string" Prefix to be used */ +#ifndef __HAIKU__ static FILE * ntfs_log_get_stream(u32 level) { FILE *stream; @@ -276,8 +276,7 @@ static const char * ntfs_log_get_prefix(u32 level) return prefix; } -#endif - +#endif //__HAIKU___ /** * ntfs_log_set_handler - Provide an alternate logging handler @@ -399,7 +398,7 @@ out: void ntfs_log_early_error(const char *format, ...) { -#ifndef __HAIKU__ +#ifndef __HAIKU__ va_list args; va_start(args, format); @@ -412,10 +411,9 @@ void ntfs_log_early_error(const char *format, ...) vfprintf(stderr,format,args); #endif va_end(args); -#endif +#endif //__HAIKU__ } -#ifndef __HAIKU__ /** * ntfs_log_handler_fprintf - Basic logging handler * @function: Function in which the log line occurred @@ -437,6 +435,7 @@ void ntfs_log_early_error(const char *format, ...) * 0 Message wasn't logged * num Number of output characters */ +#ifndef __HAIKU__ int ntfs_log_handler_fprintf(const char *function, const char *file, int line, u32 level, void *data, const char *format, va_list args) { @@ -491,7 +490,6 @@ int ntfs_log_handler_fprintf(const char *function, const char *file, errno = olderr; return ret; } - #endif // __HAIKU__ /** @@ -516,8 +514,6 @@ int ntfs_log_handler_null(const char *function __attribute__((unused)), const ch return 0; } -#ifndef __HAIKU__ - /** * ntfs_log_handler_stdout - All logs go to stdout * @function: Function in which the log line occurred @@ -539,6 +535,7 @@ int ntfs_log_handler_null(const char *function __attribute__((unused)), const ch * 0 Message wasn't logged * num Number of output characters */ +#ifndef __HAIKU__ int ntfs_log_handler_stdout(const char *function, const char *file, int line, u32 level, void *data, const char *format, va_list args) { @@ -608,8 +605,7 @@ int ntfs_log_handler_stderr(const char *function, const char *file, return ntfs_log_handler_fprintf(function, file, line, level, data, format, args); } - -#endif // __HAIKU__ +#endif //__HAIKU__ /** * ntfs_log_parse_option - Act upon command line options diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h index c68cd4c..1f55fda 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.h @@ -37,11 +37,11 @@ typedef int (ntfs_log_handler)(const char *function, const char *file, int line, u32 level, void *data, const char *format, va_list args); -#ifndef __HAIKU__ /* Set the logging handler from one of the functions, below. */ +#ifndef __HAIKU__ void ntfs_log_set_handler(ntfs_log_handler *handler __attribute__((format(printf, 6, 0)))); -#endif +#endif /* Logging handlers */ ntfs_log_handler ntfs_log_handler_syslog __attribute__((format(printf, 6, 0))); diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c index 059e882..299357e 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/object_id.c @@ -46,6 +46,7 @@ #include <sys/sysmacros.h> #endif +#include "compat.h" #include "types.h" #include "debug.h" #include "attrib.h" diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h index 5d96b1c..da794ab 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/param.h @@ -51,6 +51,12 @@ enum { #define MAX_COMPRESSION_CLUSTER_SIZE 4096 /* + * Parameters for default options + */ + +#define DEFAULT_DMTIME 60 /* default 1mn for delay_mtime */ + +/* * Use of big write buffers * * With small volumes, the cluster allocator may fail to allocate @@ -109,7 +115,11 @@ enum { * of 6 is added in the mount report. */ +#if defined(__sun) && defined(__SVR4) +#define HPERMSCONFIG 4 /* access control by kernel is broken on OpenIndiana */ +#else #define HPERMSCONFIG 1 +#endif #if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28) #define LPERMSCONFIG 5 #else diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c index 05490bf..dc44bcd 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/reparse.c @@ -3,7 +3,7 @@ * * This module is part of ntfs-3g library * - * Copyright (c) 2008-2009 Jean-Pierre Andre + * Copyright (c) 2008-2012 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 @@ -46,8 +46,10 @@ #include <sys/sysmacros.h> #endif +#include "compat.h" #include "types.h" #include "debug.h" +#include "layout.h" #include "attrib.h" #include "inode.h" #include "dir.h" @@ -59,18 +61,6 @@ #include "misc.h" #include "reparse.h" -/* the definitions in layout.h are wrong, we use names defined in - http://msdn.microsoft.com/en-us/library/aa365740(VS.85).aspx -*/ - -#define IO_REPARSE_TAG_DFS const_cpu_to_le32(0x8000000A) -#define IO_REPARSE_TAG_DFSR const_cpu_to_le32(0x80000012) -#define IO_REPARSE_TAG_HSM const_cpu_to_le32(0xC0000004) -#define IO_REPARSE_TAG_HSM2 const_cpu_to_le32(0x80000006) -#define IO_REPARSE_TAG_MOUNT_POINT const_cpu_to_le32(0xA0000003) -#define IO_REPARSE_TAG_SIS const_cpu_to_le32(0x80000007) -#define IO_REPARSE_TAG_SYMLINK const_cpu_to_le32(0xA000000C) - struct MOUNT_POINT_REPARSE_DATA { /* reparse data for junctions */ le16 subst_name_offset; le16 subst_name_length; @@ -235,6 +225,17 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path, ni = ntfs_inode_open(vol, (MFT_REF)FILE_root); if (ni) { start = 0; + /* + * Examine and translate the path, until we reach either + * - the end, + * - an unknown item + * - a non-directory + * - another reparse point, + * A reparse point is not dereferenced, it will be + * examined later when the translated path is dereferenced, + * however the final part of the path will not be adjusted + * to correct case. + */ do { len = 0; while (((start + len) < count) @@ -252,9 +253,11 @@ static char *search_absolute(ntfs_volume *vol, ntfschar *path, } } while (ni && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) + && !(ni->flags & FILE_ATTR_REPARSE_POINT) && (start < count)); if (ni - && (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir)) + && ((ni->mrec->flags & MFT_RECORD_IS_DIRECTORY ? isdir : !isdir) + || (ni->flags & FILE_ATTR_REPARSE_POINT))) if (ntfs_ucstombs(path, count, &target, 0) < 0) { if (target) { free(target); @@ -288,12 +291,25 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) int pos; int lth; BOOL ok; + BOOL morelinks; int max = 32; /* safety */ pos = 0; ok = TRUE; + morelinks = FALSE; curni = ntfs_dir_parent_inode(ni); - while (curni && ok && (pos < (count - 1)) && --max) { + /* + * Examine and translate the path, until we reach either + * - the end, + * - an unknown item + * - a non-directory + * - another reparse point, + * A reparse point is not dereferenced, it will be + * examined later when the translated path is dereferenced, + * however the final part of the path will not be adjusted + * to correct case. + */ + while (curni && ok && !morelinks && (pos < (count - 1)) && --max) { if ((count >= (pos + 2)) && (path[pos] == const_cpu_to_le16('.')) && (path[pos+1] == const_cpu_to_le16('\\'))) { @@ -331,12 +347,18 @@ static char *search_relative(ntfs_inode *ni, ntfschar *path, int count) if (!curni) ok = FALSE; else { + if (curni->flags & FILE_ATTR_REPARSE_POINT) + morelinks = TRUE; if (ok && ((pos + lth) < count)) { path[pos + lth] = const_cpu_to_le16('/'); pos += lth + 1; + if (morelinks + && ntfs_inode_close(curni)) + ok = FALSE; } else { pos += lth; - if ((ni->mrec->flags ^ curni->mrec->flags) + if (!morelinks + && (ni->mrec->flags ^ curni->mrec->flags) & MFT_RECORD_IS_DIRECTORY) ok = FALSE; if (ntfs_inode_close(curni)) diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c index 7075ca2..4fcf4c1 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c @@ -4,7 +4,7 @@ * Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2005-2006 Szabolcs Szakacsits * Copyright (c) 2006 Yura Pakhuchiy - * Copyright (c) 2007-2010 Jean-Pierre Andre + * Copyright (c) 2007-2012 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 @@ -52,6 +52,7 @@ #include <pwd.h> #include <grp.h> +#include "compat.h" #include "param.h" #include "types.h" #include "layout.h" @@ -69,6 +70,7 @@ #define getpwuid(a) NULL #endif + /* * JPA NTFS constants or structs * should be moved to layout.h @@ -1133,10 +1135,93 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid return (ingroup); } +#if defined(__sun) && defined (__SVR4) /* * Check whether current thread owner is member of file group + * Solaris/OpenIndiana version + * Should not be called for user root, however the group may be root + * + * The group list is available in "/proc/$PID/cred" * + */ + +static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) +{ + typedef struct prcred { + uid_t pr_euid; /* effective user id */ + uid_t pr_ruid; /* real user id */ + uid_t pr_suid; /* saved user id (from exec) */ + gid_t pr_egid; /* effective group id */ + gid_t pr_rgid; /* real group id */ + gid_t pr_sgid; /* saved group id (from exec) */ + int pr_ngroups; /* number of supplementary groups */ + gid_t pr_groups[1]; /* array of supplementary groups */ + } prcred_t; + enum { readset = 16 }; + + prcred_t basecreds; + gid_t groups[readset]; + char filename[64]; + int fd; + int k; + int cnt; + gid_t *p; + BOOL ismember; + int got; + pid_t tid; + + if (scx->vol->secure_flags & (1 << SECURITY_STATICGRPS)) + ismember = staticgroupmember(scx, uid, gid); + else { + ismember = FALSE; /* default return */ + tid = scx->tid; + sprintf(filename,"/proc/%u/cred",tid); + fd = open(filename,O_RDONLY); + if (fd >= 0) { + got = read(fd, &basecreds, sizeof(prcred_t)); + if (got == sizeof(prcred_t)) { + if (basecreds.pr_egid == gid) + ismember = TRUE; + p = basecreds.pr_groups; + cnt = 1; + k = 0; + while (!ismember + && (k < basecreds.pr_ngroups) + && (cnt > 0) + && (*p != gid)) { + k++; + cnt--; + p++; + if (cnt <= 0) { + got = read(fd, groups, + readset*sizeof(gid_t)); + cnt = got/sizeof(gid_t); + p = groups; + } + } + if ((cnt > 0) + && (k < basecreds.pr_ngroups)) + ismember = TRUE; + } + close(fd); + } + } + return (ismember); +} + +#elif defined(__HAIKU__) + +static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) +{ + return TRUE; +} + +#else /* defined(__sun) && defined (__SVR4) */ + +/* + * Check whether current thread owner is member of file group + * Linux version * Should not be called for user root, however the group may be root * * As indicated by Miklos Szeredi : @@ -1155,12 +1240,6 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid * contains the same data. */ -#ifdef __HAIKU__ -static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) -{ - return TRUE; -} -#else static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) { static char key[] = "\nGroups:"; @@ -1244,7 +1323,8 @@ static BOOL groupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) } return (ismember); } -#endif + +#endif /* defined(__sun) && defined (__SVR4) */ /* * Cacheing is done two-way : @@ -1809,7 +1889,7 @@ static int access_check_posix(struct SECURITY_CONTEXT *scx, if (!scx->uid) { /* root access if owner or other execution */ if (perms & 0101) - perms = 07777; + perms |= 01777; else { /* root access if some group execution */ groupperms = 0; @@ -2225,7 +2305,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx, if (!scx->uid) { /* root access and execution */ if (perm & 0111) - perm = 07777; + perm |= 01777; else perm = 0; } else @@ -3328,6 +3408,56 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, return (allow); } +/* + * Check whether user can create a file (or directory) + * + * Returns TRUE if access is allowed, + * Also returns the gid and dsetgid applicable to the created file + */ + +int ntfs_allowed_create(struct SECURITY_CONTEXT *scx, + ntfs_inode *dir_ni, gid_t *pgid, mode_t *pdsetgid) +{ + int perm; + int res; + int allow; + struct stat stbuf; + + /* + * Always allow for root. + * Also always allow if no mapping has been defined + */ + if (!scx->mapping[MAPUSERS]) + perm = 0777; + else + perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC); + if (!scx->mapping[MAPUSERS] + || !scx->uid) { + allow = 1; + } else { + perm = ntfs_get_perm(scx, dir_ni, S_IWRITE + S_IEXEC); + if (perm >= 0) { + res = EACCES; + allow = ((perm & (S_IWUSR | S_IWGRP | S_IWOTH)) != 0) + && ((perm & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0); + if (!allow) + errno = res; + } else + allow = 0; + } + *pgid = scx->gid; + *pdsetgid = 0; + /* return directory group if S_ISGID is set */ + if (allow && (perm & S_ISGID)) { + if (ntfs_get_owner_mode(scx, dir_ni, &stbuf) >= 0) { + *pdsetgid = stbuf.st_mode & S_ISGID; + if (perm & S_ISGID) + *pgid = stbuf.st_gid; + } + } + return (allow); +} + #if 0 /* not needed any more */ /* @@ -3479,10 +3609,12 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, uid = fileuid; if ((int)gid < 0) gid = filegid; +#if !defined(__sun) || !defined (__SVR4) /* clear setuid and setgid if owner has changed */ /* unless request originated by root */ if (uid && (fileuid != uid)) mode &= 01777; +#endif #if POSIXACLS res = ntfs_set_owner_mode(scx, ni, uid, gid, mode, pxdesc); @@ -3691,7 +3823,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, pnhead = (SECURITY_DESCRIPTOR_RELATIVE*)newattr; pnhead->revision = SECURITY_DESCRIPTOR_REVISION; pnhead->alignment = 0; - pnhead->control = SE_SELF_RELATIVE; + pnhead->control = (pphead->control + & (SE_DACL_AUTO_INHERITED | SE_SACL_AUTO_INHERITED)) + | SE_SELF_RELATIVE; pos = sizeof(SECURITY_DESCRIPTOR_RELATIVE); /* * locate and inherit DACL @@ -3702,7 +3836,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, offpacl = le32_to_cpu(pphead->dacl); ppacl = (const ACL*)&parentattr[offpacl]; pnacl = (ACL*)&newattr[pos]; - aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, + fordir, pphead->control + & SE_DACL_AUTO_INHERITED); if (aclsz) { pnhead->dacl = cpu_to_le32(pos); pos += aclsz; @@ -3717,7 +3853,9 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, offpacl = le32_to_cpu(pphead->sacl); ppacl = (const ACL*)&parentattr[offpacl]; pnacl = (ACL*)&newattr[pos]; - aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, fordir); + aclsz = ntfs_inherit_acl(ppacl, pnacl, usid, gsid, + fordir, pphead->control + & SE_SACL_AUTO_INHERITED); if (aclsz) { pnhead->sacl = cpu_to_le32(pos); pos += aclsz; @@ -3735,7 +3873,7 @@ static le32 build_inherited_id(struct SECURITY_CONTEXT *scx, */ memcpy(&newattr[pos],gsid,gsidsz); pnhead->group = cpu_to_le32(pos); - pos += usidsz; + pos += gsidsz; securid = setsecurityattr(scx->vol, (SECURITY_DESCRIPTOR_RELATIVE*)newattr, pos); free(newattr); diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h index 9d7dd33..8875c9c 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.h @@ -255,6 +255,8 @@ int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode); BOOL ntfs_allowed_as_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni); int ntfs_allowed_access(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, int accesstype); +int ntfs_allowed_create(struct SECURITY_CONTEXT *scx, + ntfs_inode *ni, gid_t *pgid, mode_t *pdsetgid); BOOL old_ntfs_allowed_dir_access(struct SECURITY_CONTEXT *scx, const char *path, int accesstype); diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c index a5e88e8..72dd3b0 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/unistr.c @@ -719,9 +719,9 @@ static int utf8_to_unicode(u32 *wc, const char *s) | ((u32)(s[1] & 0x3F) << 12) | ((u32)(s[2] & 0x3F) << 6) | ((u32)(s[3] & 0x3F)); - /* Check valid ranges */ - if ((*wc <= 0x10ffff) && (*wc >= 0x10000)) - return 4; + /* Check valid ranges */ + if ((*wc <= 0x10ffff) && (*wc >= 0x10000)) + return 4; } goto fail; } diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c index 3f19879..6acef48 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.c @@ -54,6 +54,10 @@ #include <locale.h> #endif +#if defined(__sun) && defined (__SVR4) +#include <sys/mnttab.h> +#endif + #include "param.h" #include "compat.h" #include "volume.h" @@ -89,13 +93,9 @@ static const char *corrupt_volume_msg = "for more details.\n"; static const char *hibernated_volume_msg = -"The NTFS partition is hibernated. Please resume and shutdown Windows\n" -"properly, or mount the volume read-only with the 'ro' mount option, or\n" -"mount the volume read-write with the 'remove_hiberfile' mount option.\n" -"For example type on the command line:\n" -"\n" -" mount -t ntfs-3g -o remove_hiberfile %s %s\n" -"\n"; +"The NTFS partition is in an unsafe state. Please resume and shutdown\n" +"Windows fully (no hibernation or fast restarting), or mount the volume\n" +"read-only with the 'ro' mount option.\n"; static const char *unclean_journal_msg = "Write access is denied because the disk wasn't safely powered\n" @@ -466,7 +466,8 @@ error_exit: * Return the allocated volume structure on success and NULL on error with * errno set to the error code. */ -ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags) +ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, + ntfs_mount_flags flags) { LCN mft_zone_size, mft_lcn; s64 br; @@ -508,13 +509,25 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags) #else NVolClearCompression(vol); #endif - if (flags & MS_RDONLY) + if (flags & NTFS_MNT_RDONLY) NVolSetReadOnly(vol); /* ...->open needs bracketing to compile with glibc 2.7 */ if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) { - ntfs_log_perror("Error opening '%s'", dev->d_name); - goto error_exit; + if (!NVolReadOnly(vol) && (errno == EROFS)) { + if ((dev->d_ops->open)(dev, O_RDONLY)) { + ntfs_log_perror("Error opening read-only '%s'", + dev->d_name); + goto error_exit; + } else { + ntfs_log_info("Can only open '%s' as read-only\n", + dev->d_name); + NVolSetReadOnly(vol); + } + } else { + ntfs_log_perror("Error opening '%s'", dev->d_name); + goto error_exit; + } } /* Attach the device to the volume. */ vol->dev = dev; @@ -649,6 +662,24 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol) if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) err = EOPNOTSUPP; + /* + * If the latest restart page was identified as version + * 2.0, then Windows may have kept a cached copy of + * metadata for fast restarting, and we should not mount. + * Hibernation will be seen the same way on a non + * Windows-system partition, so we have to use the same + * error code (EPERM). + * The restart page may also be identified as version 2.0 + * when access to the file system is terminated abruptly + * by unplugging or power cut, so mounting is also rejected + * after such an event. + */ + if (rp + && (rp->major_ver == const_cpu_to_le16(2)) + && (rp->minor_ver == const_cpu_to_le16(0))) { + ntfs_log_error("Metadata kept in Windows cache, refused to mount.\n"); + err = EPERM; + } free(rp); ntfs_attr_close(na); out: @@ -762,7 +793,8 @@ int ntfs_volume_check_hiberfile(ntfs_volume *vol, int verbose) errno = EPERM; goto out; } - if (memcmp(buf, "hibr", 4) == 0) { + if ((memcmp(buf, "hibr", 4) == 0) + || (memcmp(buf, "HIBR", 4) == 0)) { if (verbose) ntfs_log_error("Windows is hibernated, refused to mount.\n"); errno = EPERM; @@ -856,7 +888,7 @@ static int fix_txf_data(ntfs_volume *vol) * @flags is an optional second parameter. The same flags are used as for * the mount system call (man 2 mount). Currently only the following flag * is implemented: - * MS_RDONLY - mount volume read-only + * NTFS_MNT_RDONLY - mount volume read-only * * The function opens the device @dev and verifies that it contains a valid * bootsector. Then, it allocates an ntfs_volume structure and initializes @@ -867,7 +899,7 @@ static int fix_txf_data(ntfs_volume *vol) * Return the allocated volume structure on success and NULL on error with * errno set to the error code. */ -ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags) +ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags) { s64 l; ntfs_volume *vol; @@ -1195,12 +1227,13 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags) * Check for dirty logfile and hibernated Windows. * We care only about read-write mounts. */ - if (!(flags & (MS_RDONLY | MS_FORENSIC))) { - if (!(flags & MS_IGNORE_HIBERFILE) && + if (!(flags & (NTFS_MNT_RDONLY | NTFS_MNT_FORENSIC))) { + if (!(flags & NTFS_MNT_IGNORE_HIBERFILE) && ntfs_volume_check_hiberfile(vol, 1) < 0) goto error_exit; if (ntfs_volume_check_logfile(vol) < 0) { - if (!(flags & MS_RECOVER)) + /* Always reject cached metadata for now */ + if (!(flags & NTFS_MNT_RECOVER) || (errno == EPERM)) goto error_exit; ntfs_log_info("The file system wasn't safely " "closed on Windows. Fixing.\n"); @@ -1289,7 +1322,7 @@ int ntfs_set_ignore_case(ntfs_volume *vol) * @flags is an optional second parameter. The same flags are used as for * the mount system call (man 2 mount). Currently only the following flags * is implemented: - * MS_RDONLY - mount volume read-only + * NTFS_MNT_RDONLY - mount volume read-only * * The function opens the device or file @name and verifies that it contains a * valid bootsector. Then, it allocates an ntfs_volume structure and initializes @@ -1304,7 +1337,7 @@ int ntfs_set_ignore_case(ntfs_volume *vol) * soon as the function returns. */ ntfs_volume *ntfs_mount(const char *name __attribute__((unused)), - unsigned long flags __attribute__((unused))) + ntfs_mount_flags flags __attribute__((unused))) { #ifndef NO_NTFS_DEVICE_DEFAULT_IO_OPS struct ntfs_device *dev; @@ -1429,6 +1462,60 @@ exit: } return 0; } + +#else /* HAVE_MNTENT_H */ + +#if defined(__sun) && defined (__SVR4) + +static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags) +{ + struct mnttab *mnt = NULL; + char *real_file = NULL, *real_fsname = NULL; + FILE *f; + int err = 0; + + real_file = (char*)ntfs_malloc(PATH_MAX + 1); + if (!real_file) + return -1; + real_fsname = (char*)ntfs_malloc(PATH_MAX + 1); + mnt = (struct mnttab*)ntfs_malloc(MNT_LINE_MAX + 1); + if (!real_fsname || !mnt) { + err = errno; + goto exit; + } + if (!ntfs_realpath_canonicalize(file, real_file)) { + err = errno; + goto exit; + } + if (!(f = fopen(MNTTAB, "r"))) { + err = errno; + goto exit; + } + while (!getmntent(f, mnt)) { + if (!ntfs_realpath_canonicalize(mnt->mnt_special, real_fsname)) + continue; + if (!strcmp(real_file, real_fsname)) { + *mnt_flags = NTFS_MF_MOUNTED; + if (!strcmp(mnt->mnt_mountp, "/")) + *mnt_flags |= NTFS_MF_ISROOT; + if (hasmntopt(mnt, "ro") && !hasmntopt(mnt, "rw")) + *mnt_flags |= NTFS_MF_READONLY; + break; + } + } + fclose(f); +exit: + free(mnt); + free(real_file); + free(real_fsname); + if (err) { + errno = err; + return -1; + } + return 0; +} + +#endif /* defined(__sun) && defined (__SVR4) */ #endif /* HAVE_MNTENT_H */ /** @@ -1460,7 +1547,7 @@ int ntfs_check_if_mounted(const char *file __attribute__((unused)), unsigned long *mnt_flags) { *mnt_flags = 0; -#ifdef HAVE_MNTENT_H +#if defined(HAVE_MNTENT_H) || (defined(__sun) && defined (__SVR4)) return ntfs_mntent_check(file, mnt_flags); #else return 0; @@ -1642,6 +1729,10 @@ int ntfs_volume_error(int err) ret = NTFS_VOLUME_CORRUPT; break; case EPERM: + /* + * Hibernation and fast restarting are seen the + * same way on a non Windows-system partition. + */ ret = NTFS_VOLUME_HIBERNATED; break; case EOPNOTSUPP: @@ -1693,7 +1784,7 @@ void ntfs_mount_error(const char *volume, const char *mntpoint, int err) int ntfs_set_locale(void) { -#ifndef __HAIKU__ +#ifndef __HAIKU__ const char *locale; locale = setlocale(LC_ALL, ""); @@ -1703,7 +1794,7 @@ int ntfs_set_locale(void) "'%s'.\n", locale); return 1; } -#endif +#endif return 0; } @@ -1744,7 +1835,7 @@ int ntfs_volume_get_free_space(ntfs_volume *vol) * * Change the label on the volume @vol to @label. */ -int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len) +int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, int label_len) { ntfs_attr *na; char *old_vol_name; @@ -1779,7 +1870,7 @@ int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len) /* The volume name attribute does not exist. Need to add it. */ if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0, - (u8*) label, label_len)) + (const u8*) label, label_len)) { err = errno; ntfs_log_perror("Encountered error while adding " diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h index 9d62d66..a181ccc 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/volume.h @@ -43,23 +43,6 @@ #include <mntent.h> #endif -/* - * Under Cygwin, DJGPP and FreeBSD we do not have MS_RDONLY, - * so we define them ourselves. - */ -#ifndef MS_RDONLY -#define MS_RDONLY 1 -#endif - -#define MS_EXCLUSIVE 0x08000000 - -#ifndef MS_RECOVER -#define MS_RECOVER 0x10000000 -#endif - -#define MS_IGNORE_HIBERFILE 0x20000000 -#define MS_FORENSIC 0x04000000 /* No modification during mount */ - /* Forward declaration */ typedef struct _ntfs_volume ntfs_volume; @@ -74,13 +57,29 @@ typedef struct _ntfs_volume ntfs_volume; /** * enum ntfs_mount_flags - * + * Flags for the ntfs_mount() function. + */ +enum { + NTFS_MNT_NONE = 0x00000000, + NTFS_MNT_RDONLY = 0x00000001, + NTFS_MNT_FORENSIC = 0x04000000, /* No modification during + * mount. */ + NTFS_MNT_EXCLUSIVE = 0x08000000, + NTFS_MNT_RECOVER = 0x10000000, + NTFS_MNT_IGNORE_HIBERFILE = 0x20000000, +}; +typedef unsigned long ntfs_mount_flags; + +/** + * enum ntfs_mounted_flags - + * * Flags returned by the ntfs_check_if_mounted() function. */ typedef enum { NTFS_MF_MOUNTED = 1, /* Device is mounted. */ NTFS_MF_ISROOT = 2, /* Device is mounted as system root. */ NTFS_MF_READONLY = 4, /* Device is mounted read-only. */ -} ntfs_mount_flags; +} ntfs_mounted_flags; extern int ntfs_check_if_mounted(const char *file, unsigned long *mnt_flags); @@ -284,12 +283,12 @@ extern const char *ntfs_home; extern ntfs_volume *ntfs_volume_alloc(void); extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, - unsigned long flags); + ntfs_mount_flags flags); extern ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, - unsigned long flags); + ntfs_mount_flags flags); -extern ntfs_volume *ntfs_mount(const char *name, unsigned long flags); +extern ntfs_volume *ntfs_mount(const char *name, ntfs_mount_flags flags); extern int ntfs_umount(ntfs_volume *vol, const BOOL force); extern int ntfs_version_is_supported(ntfs_volume *vol); @@ -302,7 +301,8 @@ extern int ntfs_volume_error(int err); extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err); extern int ntfs_volume_get_free_space(ntfs_volume *vol); -extern int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len); +extern int ntfs_volume_rename(ntfs_volume *vol, const ntfschar *label, + int label_len); extern int ntfs_set_shown_files(ntfs_volume *vol, BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files); diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c index e224d5f..545c609 100644 --- a/src/add-ons/kernel/file_systems/ntfs/utils/utils.c +++ b/src/add-ons/kernel/file_systems/ntfs/utils/utils.c @@ -275,11 +275,11 @@ ntfs_volume * utils_mount_volume(const char *device, unsigned long flags) * * libntfs-3g only has safety check number 2. The dirty flag is simply * ignored because we are confident that we can handle a dirty volume. - * So we treat MS_RECOVER like NTFS_MNT_FORCE, knowing that the first - * check is always bypassed. + * So we treat NTFS_MNT_RECOVER like NTFS_MNT_FORCE, knowing that the + * first check is always bypassed. */ - if (!utils_valid_device(device, flags & MS_RECOVER)) + if (!utils_valid_device(device, flags & NTFS_MNT_RECOVER)) return NULL; vol = ntfs_mount(device, flags); @@ -305,7 +305,7 @@ ntfs_volume * utils_mount_volume(const char *device, unsigned long flags) * before mount, so we can only warn if the VOLUME_IS_DIRTY flag is set * in VOLUME_INFORMATION. */ if (vol->flags & VOLUME_IS_DIRTY) { - if (!(flags & MS_RECOVER)) { + if (!(flags & NTFS_MNT_RECOVER)) { ntfs_log_error("%s", dirty_volume_msg); ntfs_umount(vol, FALSE); return NULL; @@ -1122,69 +1122,4 @@ int mft_next_record(struct mft_search_ctx *ctx) return (ctx->inode == NULL); } -/** - * ntfs_mft_get_parent_ref - find mft reference of parent directory of an inode - * @ni: ntfs inode whose parent directory to find - * - * Find the parent directory of the ntfs inode @ni. To do this, find the first - * file name attribute in the mft record of @ni and return the parent mft - * reference from that. - * - * Note this only makes sense for directories, since files can be hard linked - * from multiple directories and there is no way for us to tell which one is - * being looked for. - * - * Technically directories can have hard links, too, but we consider that as - * illegal as Linux/UNIX do not support directory hard links. - * - * Return the mft reference of the parent directory on success or -1 on error - * with errno set to the error code. - */ -MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) -{ - MFT_REF mref; - ntfs_attr_search_ctx *ctx; - FILE_NAME_ATTR *fn; - int eo; - - ntfs_log_trace("Entering.\n"); - - if (!ni) { - errno = EINVAL; - return ERR_MREF(-1); - } - - ctx = ntfs_attr_get_search_ctx(ni, NULL); - if (!ctx) - return ERR_MREF(-1); - if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { - ntfs_log_error("No file name found in inode %lld\n", - (unsigned long long)ni->mft_no); - goto err_out; - } - if (ctx->attr->non_resident) { - ntfs_log_error("File name attribute must be resident (inode " - "%lld)\n", (unsigned long long)ni->mft_no); - goto io_err_out; - } - fn = (FILE_NAME_ATTR*)((u8*)ctx->attr + - le16_to_cpu(ctx->attr->value_offset)); - if ((u8*)fn + le32_to_cpu(ctx->attr->value_length) > - (u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) { - ntfs_log_error("Corrupt file name attribute in inode %lld.\n", - (unsigned long long)ni->mft_no); - goto io_err_out; - } - mref = le64_to_cpu(fn->parent_directory); - ntfs_attr_put_search_ctx(ctx); - return mref; -io_err_out: - errno = EIO; -err_out: - eo = errno; - ntfs_attr_put_search_ctx(ctx); - errno = eo; - return ERR_MREF(-1); -} - diff --git a/src/add-ons/kernel/file_systems/ntfs/utils/utils.h b/src/add-ons/kernel/file_systems/ntfs/utils/utils.h index 027a15a..3974da0 100644 --- a/src/add-ons/kernel/file_systems/ntfs/utils/utils.h +++ b/src/add-ons/kernel/file_systems/ntfs/utils/utils.h @@ -85,7 +85,6 @@ struct mft_search_ctx { struct mft_search_ctx * mft_get_search_ctx(ntfs_volume *vol); void mft_put_search_ctx(struct mft_search_ctx *ctx); int mft_next_record(struct mft_search_ctx *ctx); -MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni); // Flags for dump mem #define DM_DEFAULTS 0 ############################################################################ Commit: 0d4e157ba44dccb274f7b0d300a921d9d5cca8c4 URL: http://cgit.haiku-os.org/haiku/commit/?id=0d4e157 Author: Gerasim Troeglazov <3dEyes@xxxxxxxxx> Date: Wed Dec 4 12:34:49 2013 UTC ntfs: Fix several warnings ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h index 66c8782..43308d1 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/dir.h @@ -88,6 +88,8 @@ extern int ntfs_delete(ntfs_volume *vol, const char *path, extern int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, u8 name_len); +extern MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni); + /* * File types (adapted from include <linux/fs.h>) */ diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c index f781ee1..8102827 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/logging.c @@ -276,7 +276,6 @@ static const char * ntfs_log_get_prefix(u32 level) return prefix; } -#endif //__HAIKU___ /** * ntfs_log_set_handler - Provide an alternate logging handler @@ -296,6 +295,7 @@ void ntfs_log_set_handler(ntfs_log_handler *handler) } else ntfs_log.handler = ntfs_log_handler_null; } +#endif //__HAIKU___ /** * ntfs_log_redirect - Pass on the request to the real handler diff --git a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c index 4fcf4c1..2ff3306 100644 --- a/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c +++ b/src/add-ons/kernel/file_systems/ntfs/libntfs/security.c @@ -1112,7 +1112,7 @@ static int upgrade_secur_desc(ntfs_volume *vol, * Should not be called for user root, however the group may be root * */ - +#ifndef __HAIKU__ static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid) { BOOL ingroup; @@ -1134,6 +1134,7 @@ static BOOL staticgroupmember(struct SECURITY_CONTEXT *scx, uid_t uid, gid_t gid } return (ingroup); } +#endif //__HAIKU__ #if defined(__sun) && defined (__SVR4) ############################################################################ Revision: hrev46483 Commit: 5287b8a778715de8320fe2bd932ceab5c185cc41 URL: http://cgit.haiku-os.org/haiku/commit/?id=5287b8a Author: Gerasim Troeglazov <3dEyes@xxxxxxxxx> Date: Wed Dec 4 12:44:02 2013 UTC ntfs: Directory position must be signed ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h index 2fa305c..0b47031 100644 --- a/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h +++ b/src/add-ons/kernel/file_systems/ntfs/ntfsdir.h @@ -31,7 +31,7 @@ typedef struct cache_entry { typedef struct dircookie { - u64 pos; + s64 pos; dev_t dev_id; BOOL show_sys_files; cache_entry *cache_root;