Adjusted to v 1.1030

N2009_11_14_FIXES
jpandre 2007-10-29 16:28:33 +00:00
parent 444f617e7f
commit a8dc8655d0
8 changed files with 270 additions and 216 deletions

View File

@ -205,30 +205,15 @@ typedef enum {
#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
#define GenNAttrIno(func_name,flag) \
static inline int NAttr##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
return (na->ni->flags & FILE_ATTR_##flag); \
return 0; \
} \
static inline void NAttrSet##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
na->ni->flags |= FILE_ATTR_##flag; \
else \
ntfs_log_trace("BUG! Should be called only for "\
"unnamed data attribute.\n"); \
} \
static inline void NAttrClear##func_name(ntfs_attr *na) \
{ \
if (na->type == AT_DATA && na->name == AT_UNNAMED) \
na->ni->flags &= ~FILE_ATTR_##flag; \
}
#define GenNAttrIno(func_name, flag) \
extern int NAttr##func_name(ntfs_attr *na); \
extern void NAttrSet##func_name(ntfs_attr *na); \
extern void NAttrClear##func_name(ntfs_attr *na);
GenNAttrIno(Compressed, COMPRESSED)
GenNAttrIno(Encrypted, ENCRYPTED)
GenNAttrIno(Sparse, SPARSE_FILE)
GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED)
GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
#undef GenNAttrIno
/**
* union attr_val - Union of all known attribute values
@ -358,6 +343,7 @@ extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
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);
#endif /* defined _NTFS_ATTRIB_H */

View File

@ -65,6 +65,37 @@ ntfschar STREAM_SDS[] = { const_cpu_to_le16('$'),
const_cpu_to_le16('S'),
const_cpu_to_le16('\0') };
static int NAttrFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
{
if (na->type == AT_DATA && na->name == AT_UNNAMED)
return (na->ni->flags & flag);
return 0;
}
static void NAttrSetFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
{
if (na->type == AT_DATA && na->name == AT_UNNAMED)
na->ni->flags |= flag;
else
ntfs_log_trace("Denied setting flag %d for not unnamed data "
"attribute\n", flag);
}
static void NAttrClearFlag(ntfs_attr *na, FILE_ATTR_FLAGS flag)
{
if (na->type == AT_DATA && na->name == AT_UNNAMED)
na->ni->flags &= ~flag;
}
#define GenNAttrIno(func_name, flag) \
int NAttr##func_name(ntfs_attr *na) { return NAttrFlag (na, flag); } \
void NAttrSet##func_name(ntfs_attr *na) { NAttrSetFlag (na, flag); } \
void NAttrClear##func_name(ntfs_attr *na){ NAttrClearFlag(na, flag); }
GenNAttrIno(Compressed, FILE_ATTR_COMPRESSED)
GenNAttrIno(Encrypted, FILE_ATTR_ENCRYPTED)
GenNAttrIno(Sparse, FILE_ATTR_SPARSE_FILE)
/**
* ntfs_get_attribute_value_length - Find the length of an attribute
* @a:
@ -4743,8 +4774,8 @@ static int ntfs_non_resident_attr_expand(ntfs_attr *na, const s64 newsize)
ntfs_log_perror("Cluster allocation failed "
"(%lld)",
(long long)first_free_vcn -
((long long)na->allocated_size
>> vol->cluster_size_bits));
((long long)na->allocated_size >>
vol->cluster_size_bits));
return -1;
}
}
@ -5017,3 +5048,30 @@ int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,
return ret;
}
s64 ntfs_attr_get_free_bits(ntfs_attr *na)
{
u8 *buf;
s64 nr_free = 0;
s64 br, total = 0;
buf = ntfs_malloc(na->ni->vol->cluster_size);
if (!buf)
return -1;
while (1) {
int i, j;
br = ntfs_attr_pread(na, total, na->ni->vol->cluster_size, buf);
if (br <= 0)
break;
total += br;
for (i = 0; i < br; i++)
for (j = 0; j < 8; j++)
if (!((buf[i] >> j) & 1))
nr_free++;
}
free(buf);
if (!total || br < 0)
return -1;
return nr_free;
}

View File

@ -1218,7 +1218,7 @@ static int ntfs_ir_truncate(ntfs_index_context *icx, int data_size)
icx->ir->index.allocated_size = cpu_to_le32(data_size);
} else
} else if (ret == STATUS_ERROR)
ntfs_log_perror("Failed to truncate INDEX_ROOT");
ntfs_attr_close(na);

View File

@ -500,8 +500,7 @@ int ntfs_inode_attach_all_extents(ntfs_inode *ni)
while ((u8*)ale < ni->attr_list + ni->attr_list_size) {
if (ni->mft_no != MREF_LE(ale->mft_reference) &&
prev_attached != MREF_LE(ale->mft_reference)) {
if (!ntfs_extent_inode_open(ni,
MREF_LE(ale->mft_reference))) {
if (!ntfs_extent_inode_open(ni, ale->mft_reference)) {
ntfs_log_trace("Couldn't attach extent inode.\n");
return -1;
}

View File

@ -58,6 +58,13 @@ static const char *col_red = "\e[01;31m";
static const char *col_redinv = "\e[01;07;31m";
static const char *col_end = "\e[0m";
/* gcc 3.3.3 crashes with internal compiler error. 4.x seems to be ok. */
#if __GNUC__ <= 3
# define BROKEN_GCC_FORMAT_ATTRIBUTE
#else
# define BROKEN_GCC_FORMAT_ATTRIBUTE __attribute__((format(printf, 6, 0)))
#endif
/**
* struct ntfs_logging - Control info for the logging system
* @levels: Bitfield of logging levels
@ -67,7 +74,7 @@ static const char *col_end = "\e[0m";
struct ntfs_logging {
u32 levels;
u32 flags;
ntfs_log_handler *handler;
ntfs_log_handler *handler BROKEN_GCC_FORMAT_ATTRIBUTE;
};
/**

View File

@ -81,12 +81,12 @@ int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
s64 br;
VCN m;
ntfs_log_trace("Entering for inode %lld\n", MREF(mref));
ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
if (!vol || !vol->mft_na || !b || count < 0) {
errno = EINVAL;
ntfs_log_perror("%s: b=%p count=%lld mft=%lld", __FUNCTION__,
b, (long long)count, (long long)MREF(mref));
ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__,
b, (long long)count, (unsigned long long)MREF(mref));
return -1;
}
m = MREF(mref);
@ -265,19 +265,20 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
}
err = EIO;
if (!ntfs_is_file_record(m->magic)) {
ntfs_log_perror("Record %llu has no FILE magic",
(unsigned long long)MREF(mref));
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
(unsigned long long)MREF(mref), *(le32 *)m);
goto err_out;
}
if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
ntfs_log_perror("Record %llu has wrong SeqNo",
(unsigned long long)MREF(mref));
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
(unsigned long long)MREF(mref), MSEQNO(mref),
le16_to_cpu(m->sequence_number));
goto err_out;
}
a = (ATTR_RECORD*)((char*)m + le16_to_cpu(m->attrs_offset));
if (p2n(a) < p2n(m) || (char*)a > (char*)m + vol->mft_record_size) {
ntfs_log_perror("Record %llu is corrupt",
(unsigned long long)MREF(mref));
ntfs_log_error("Record %llu is corrupt\n",
(unsigned long long)MREF(mref));
goto err_out;
}
*mrec = m;

View File

@ -500,13 +500,15 @@ void ntfs_generate_guid(GUID *guid)
*/
le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len)
{
const le32 *pos = (const le32*)sd;
const le32 *end = pos + (len >> 2);
u32 hash = 0;
const le32 *pos = (const le32*)sd;
const le32 *end = pos + (len >> 2);
u32 hash = 0;
while (pos < end)
hash = le32_to_cpup(pos++) + ntfs_rol32(hash, 3);
return cpu_to_le32(hash);
while (pos < end) {
hash = le32_to_cpup(pos) + ntfs_rol32(hash, 3);
pos++;
}
return cpu_to_le32(hash);
}
@ -3487,8 +3489,8 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx,
static int inherit_acl(const ACL *oldacl, ACL *newacl, BOOL fordir)
{
int src;
int dst;
unsigned int src;
unsigned int dst;
int oldcnt;
int newcnt;
unsigned int selection;
@ -3508,7 +3510,7 @@ static int inherit_acl(const ACL *oldacl, ACL *newacl, BOOL fordir)
newcnt = 0;
oldcnt = le16_to_cpu(oldacl->ace_count);
for (nace = 0; nace < oldcnt; nace++) {
poldace = (const ACCESS_ALLOWED_ACE*)((char*)oldacl + src);
poldace = (const ACCESS_ALLOWED_ACE*)((const char*)oldacl + src);
acesz = le16_to_cpu(poldace->size);
if (poldace->flags & selection) {
pnewace = (ACCESS_ALLOWED_ACE*)
@ -3540,8 +3542,7 @@ static int inherit_acl(const ACL *oldacl, ACL *newacl, BOOL fordir)
*/
static le32 build_inherited_id(struct SECURITY_CONTEXT *scx,
const char *parentattr,
ntfs_inode *dir_ni, BOOL fordir)
const char *parentattr, BOOL fordir)
{
const SECURITY_DESCRIPTOR_RELATIVE *pphead;
const ACL *ppacl;
@ -3684,8 +3685,7 @@ le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx,
parentattr = getsecurityattr(scx->vol, dir_path, dir_ni);
if (parentattr) {
securid = build_inherited_id(scx,
parentattr,
dir_ni, fordir);
parentattr, fordir);
free(parentattr);
/*
* Store the result into cache for further use
@ -3865,6 +3865,10 @@ static void free_mapping(struct SECURITY_CONTEXT *scx)
/*
* Build the user mapping list
* user identification may be given in symbolic or numeric format
*
* ! Note ! : does getpwnam() read /etc/passwd or some other file ?
* if so there is a possible recursion into fuse if this
* file is on NTFS, and fuse is not recursion safe.
*/
static struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
@ -3917,6 +3921,10 @@ static struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
*
* gid not associated to a uid are processed first in order
* to favour real groups
*
* ! Note ! : does getgrnam() read /etc/group or some other file ?
* if so there is a possible recursion into fuse if this
* file is on NTFS, and fuse is not recursion safe.
*/
static struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem)

View File

@ -120,6 +120,9 @@ typedef struct {
BOOL debug;
BOOL noatime;
BOOL no_detach;
BOOL blkdev;
BOOL mounted;
struct fuse_chan *fc;
BOOL inherit;
BOOL addsecurids;
struct SECURITY_CACHE *seccache;
@ -142,10 +145,6 @@ static const char *locale_msg =
" be correct or visible. Please see the potential solution at\n"
" http://ntfs-3g.org/support.html#locale\n";
static const char *dev_fuse_msg =
"HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
" kernel module as root (modprobe fuse) and make sure /dev/fuse exist.\n";
static const char *usage_msg =
"\n"
"%s %s - Third Generation NTFS Driver\n"
@ -169,40 +168,20 @@ static const char *usage_msg =
*
* Returns 1 if path is to named data stream or 0 otherwise.
*/
static __inline__ int ntfs_fuse_is_named_data_stream(const char *path)
static int ntfs_fuse_is_named_data_stream(const char *path)
{
if (strchr(path, ':') && ctx->streams == NF_STREAMS_INTERFACE_WINDOWS)
return 1;
return 0;
}
static long ntfs_get_nr_free_mft_records(ntfs_volume *vol)
static s64 ntfs_get_nr_free_mft_records(ntfs_volume *vol)
{
u8 *buf;
long nr_free = 0;
s64 br, total = 0;
ntfs_attr *na = vol->mftbmp_na;
s64 nr_free = ntfs_attr_get_free_bits(na);
buf = ntfs_malloc(vol->cluster_size);
if (!buf)
return -errno;
while (1) {
int i, j;
br = ntfs_attr_pread(vol->mftbmp_na, total,
vol->cluster_size, buf);
if (br <= 0)
break;
total += br;
for (i = 0; i < br; i++)
for (j = 0; j < 8; j++)
if (!((buf[i] >> j) & 1))
nr_free++;
}
free(buf);
if (!total || br < 0)
return -errno;
nr_free += (vol->mftbmp_na->allocated_size - vol->mftbmp_na->data_size) << 3;
if (nr_free >= 0)
nr_free += (na->allocated_size - na->data_size) << 3;
return nr_free;
}
@ -229,34 +208,6 @@ static BOOL ntfs_fuse_fill_security_context(struct SECURITY_CONTEXT *scx)
return (ctx->security.usermapping != (struct MAPPING*)NULL);
}
static long ntfs_get_nr_free_clusters(ntfs_volume *vol)
{
u8 *buf;
long nr_free = 0;
s64 br, total = 0;
buf = ntfs_malloc(vol->cluster_size);
if (!buf)
return -errno;
while (1) {
int i, j;
br = ntfs_attr_pread(vol->lcnbmp_na, total,
vol->cluster_size, buf);
if (br <= 0)
break;
total += br;
for (i = 0; i < br; i++)
for (j = 0; j < 8; j++)
if (!((buf[i] >> j) & 1))
nr_free++;
}
free(buf);
if (!total || br < 0)
return -errno;
return nr_free;
}
/**
* ntfs_fuse_statfs - return information about mounted NTFS volume
* @path: ignored (but fuse requires it)
@ -275,7 +226,7 @@ static long ntfs_get_nr_free_clusters(ntfs_volume *vol)
* Returns 0 on success or -errno on error.
*/
static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
struct statvfs *sfs)
struct statvfs *sfs)
{
s64 size;
int delta_bits;
@ -285,22 +236,23 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
if (!vol)
return -ENODEV;
/* Optimal transfer block size. */
/* File system block size, used for optimal transfer block size. */
sfs->f_bsize = vol->cluster_size;
/* Fundamental file system block size, used as the unit. */
sfs->f_frsize = vol->cluster_size;
/*
* Total data blocks in file system in units of f_bsize and since
* inodes are also stored in data blocs ($MFT is a file) this is just
* the total clusters.
* Total number of blocks on file system in units of f_frsize.
* Since inodes are also stored in blocks ($MFT is a file) hence
* this is the number of clusters on the volume.
*/
sfs->f_blocks = vol->nr_clusters;
/* Free data blocks in file system in units of f_bsize. */
/* Free blocks available for all and for non-privileged processes. */
size = vol->free_clusters;
if (size < 0)
size = 0;
/* Free blocks avail to non-superuser, same as above on NTFS. */
sfs->f_bavail = sfs->f_bfree = size;
/* Free inodes on the free space */
@ -310,15 +262,14 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
else
size >>= -delta_bits;
/* Number of inodes in file system (at this point in time). */
/* Number of inodes at this point in time. */
sfs->f_files = (vol->mftbmp_na->allocated_size << 3) + size;
/* Free inodes in fs (based on current total count). */
/* Free inodes available for all and for non-privileged processes. */
size += vol->free_mft_records;
if (size < 0)
size = 0;
sfs->f_ffree = size;
sfs->f_favail = 0;
sfs->f_ffree = sfs->f_favail = size;
/* Maximum length of filenames. */
sfs->f_namemax = NTFS_MAX_NAME_LEN;
@ -606,7 +557,7 @@ static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,
if (MREF(mref) == FILE_root || MREF(mref) >= FILE_first_user ||
ctx->show_sys_files) {
struct stat st = { .st_ino = MREF(mref) };
if (dt_type == NTFS_DT_REG)
st.st_mode = S_IFREG | (0777 & ~ctx->fmask);
else if (dt_type == NTFS_DT_DIR)
@ -701,7 +652,8 @@ static int ntfs_fuse_read(const char *org_path, char *buf, size_t size,
ntfs_attr *na = NULL;
char *path = NULL;
ntfschar *stream_name;
int stream_name_len, res, total = 0;
int stream_name_len, res;
s64 total = 0;
stream_name_len = ntfs_fuse_parse_path(org_path, &path, &stream_name);
if (stream_name_len < 0)
@ -717,21 +669,26 @@ static int ntfs_fuse_read(const char *org_path, char *buf, size_t size,
res = -errno;
goto exit;
}
if (offset + size > (size_t)na->data_size)
size = na->data_size - offset;
while (size) {
res = ntfs_attr_pread(na, offset, size, buf);
if (res < (s64)size)
ntfs_log_perror("ntfs_attr_pread partial write (%lld: "
"%lld <> %d)", (long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
if (offset + (off_t)size > na->data_size) {
if (na->data_size < offset) {
res = -EINVAL;
goto exit;
}
size -= res;
offset += res;
total += res;
size = na->data_size - offset;
}
while (size > 0) {
s64 ret = ntfs_attr_pread(na, offset, size, buf);
if (ret != (s64)size)
ntfs_log_perror("ntfs_attr_pread error reading '%s' at "
"offset %lld: %lld <> %lld", org_path,
(long long)offset, (long long)size, (long long)ret);
if (ret <= 0 || ret > (s64)size) {
res = (ret <= 0) ? -errno : -EIO;
goto exit;
}
size -= ret;
offset += ret;
total += ret;
}
res = total;
exit:
@ -1809,15 +1766,18 @@ exit:
#endif /* HAVE_SETXATTR */
static void ntfs_fuse_destroy(void)
static void ntfs_close(void)
{
struct SECURITY_CONTEXT security;
if (!ctx)
return;
if (ctx->vol) {
ntfs_log_info("Unmounting %s (%s)\n", opts.device,
if (!ctx->vol)
return;
if (ctx->mounted) {
ntfs_log_info("Unmounting %s (%s)\n", opts.device,
ctx->vol->vol_name);
if (ntfs_fuse_fill_security_context(&security)) {
if (ctx->seccache && ctx->seccache->head.p_reads) {
@ -1847,21 +1807,20 @@ static void ntfs_fuse_destroy(void)
}
}
ntfs_close_secure(&security);
if (ntfs_umount(ctx->vol, FALSE))
ntfs_log_perror("Failed to cleanly unmount volume %s",
opts.device);
}
free(ctx);
ctx = NULL;
free(opts.device);
if (ntfs_umount(ctx->vol, FALSE))
ntfs_log_perror("Failed to close volume %s", opts.device);
ctx->vol = NULL;
}
static void ntfs_fuse_destroy2(void *unused __attribute__((unused)))
{
ntfs_fuse_destroy();
ntfs_close();
}
static struct fuse_operations ntfs_fuse_oper = {
static struct fuse_operations ntfs_3g_ops = {
.getattr = ntfs_fuse_getattr,
.readlink = ntfs_fuse_readlink,
.readdir = ntfs_fuse_readdir,
@ -1894,25 +1853,23 @@ static struct fuse_operations ntfs_fuse_oper = {
static int ntfs_fuse_init(void)
{
ctx = ntfs_malloc(sizeof(ntfs_fuse_context_t));
ctx = ntfs_calloc(sizeof(ntfs_fuse_context_t));
if (!ctx)
return -1;
*ctx = (ntfs_fuse_context_t) {
.uid = getuid(),
.gid = getgid(),
.fmask = 0,
.dmask = 0,
.streams = NF_STREAMS_INTERFACE_NONE,
};
return 0;
}
static ntfs_volume *ntfs_open(const char *device, char *mntpoint, int blkdev)
static int ntfs_open(const char *device, char *mntpoint)
{
unsigned long flags = 0;
if (!blkdev)
if (!ctx->blkdev)
flags |= MS_EXCLUSIVE;
if (ctx->ro)
flags |= MS_RDONLY;
@ -1922,7 +1879,22 @@ static ntfs_volume *ntfs_open(const char *device, char *mntpoint, int blkdev)
flags |= MS_FORCE;
ctx->vol = utils_mount_volume(device, mntpoint, flags);
return ctx->vol;
if (!ctx->vol)
return -1;
ctx->vol->free_clusters = ntfs_attr_get_free_bits(ctx->vol->lcnbmp_na);
if (ctx->vol->free_clusters < 0) {
ntfs_log_perror("Failed to read NTFS $Bitmap");
return -1;
}
ctx->vol->free_mft_records = ntfs_get_nr_free_mft_records(ctx->vol);
if (ctx->vol->free_mft_records < 0) {
ntfs_log_perror("Failed to calculate free MFT records");
return -1;
}
return 0;
}
static void signal_handler(int arg __attribute__((unused)))
@ -2286,7 +2258,13 @@ static int parse_options(int argc, char *argv[])
return 0;
}
#ifdef linux
#if defined(linux) || defined(__uClinux__)
static const char *dev_fuse_msg =
"HINT: You should be root, or make ntfs-3g setuid root, or load the FUSE\n"
" kernel module as root ('modprobe fuse' or 'insmod <path_to>/fuse.ko'"
" or insmod <path_to>/fuse.o'). Make also sure that the fuse device"
" exists. It's usually either /dev/fuse or /dev/misc/fuse.";
static const char *fuse26_kmod_msg =
"WARNING: Deficient Linux kernel detected. Some driver features are\n"
@ -2299,19 +2277,39 @@ static const char *fuse26_kmod_msg =
" http://ntfs-3g.org/support.html#fuse26\n"
"\n";
static void create_dev_fuse(void)
static void mknod_dev_fuse(const char *dev)
{
struct stat st;
if (stat("/dev/fuse", &st) && (errno == ENOENT)) {
if (mknod("/dev/fuse", S_IFCHR | 0666, makedev(10, 229))) {
ntfs_log_perror("Failed to create /dev/fuse");
if (stat(dev, &st) && (errno == ENOENT)) {
mode_t mask = umask(0);
if (mknod(dev, S_IFCHR | 0666, makedev(10, 229))) {
ntfs_log_perror("Failed to create '%s'", dev);
if (errno == EPERM)
ntfs_log_error(dev_fuse_msg);
}
umask(mask);
}
}
static void create_dev_fuse(void)
{
mknod_dev_fuse("/dev/fuse");
#ifdef __UCLIBC__
{
struct stat st;
/* The fuse device is under /dev/misc using devfs. */
if (stat("/dev/misc", &st) && (errno == ENOENT)) {
mode_t mask = umask(0);
mkdir("/dev/misc", 0775);
umask(mask);
}
mknod_dev_fuse("/dev/misc/fuse");
}
#endif
}
static fuse_fstype get_fuse_fstype(void)
{
char buf[256];
@ -2430,15 +2428,46 @@ static void set_user_mount_option(char *parsed_options, uid_t uid)
strcat(parsed_options, option);
}
static struct fuse *mount_fuse(char *parsed_options)
{
struct fuse *fh = NULL;
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
/* Libfuse can't always find fusermount, so let's help it. */
if (setenv("PATH", ":/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin", 0))
ntfs_log_perror("WARNING: Failed to set $PATH\n");
ctx->fc = try_fuse_mount(parsed_options);
if (!ctx->fc)
return NULL;
if (fuse_opt_add_arg(&args, "") == -1)
goto err;
if (fuse_opt_add_arg(&args, "-ouse_ino,kernel_cache") == -1)
goto err;
if (ctx->debug)
if (fuse_opt_add_arg(&args, "-odebug") == -1)
goto err;
fh = fuse_new(ctx->fc, &args , &ntfs_3g_ops, sizeof(ntfs_3g_ops), NULL);
if (!fh)
goto err;
ctx->mounted = TRUE;
out:
fuse_opt_free_args(&args);
return fh;
err:
fuse_unmount(opts.mnt_point, ctx->fc);
goto out;
}
int main(int argc, char *argv[])
{
char *parsed_options = NULL;
struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
struct fuse *fh;
struct fuse_chan *fc;
fuse_fstype fstype = FSTYPE_UNKNOWN;
struct stat sbuf;
int use_blkdev = 0;
uid_t uid, euid;
int err = 10;
@ -2467,7 +2496,7 @@ int main(int argc, char *argv[])
goto err_out;
}
#ifdef linux
#if defined(linux) || defined(__uClinux__)
fstype = get_fuse_fstype();
if (fstype == FSTYPE_NONE || fstype == FSTYPE_UNKNOWN)
fstype = load_fuse_module();
@ -2481,64 +2510,27 @@ int main(int argc, char *argv[])
}
/* Always use fuseblk for block devices unless it's surely missing. */
if (S_ISBLK(sbuf.st_mode) && (fstype != FSTYPE_FUSE))
use_blkdev = 1;
ctx->blkdev = TRUE;
if (!ntfs_open(opts.device, opts.mnt_point, use_blkdev))
if (ntfs_open(opts.device, opts.mnt_point))
goto err_out;
ctx->vol->free_clusters = ntfs_get_nr_free_clusters(ctx->vol);
if (ctx->vol->free_clusters < 0) {
ntfs_log_perror("Failed to read NTFS $Bitmap");
if (ctx->blkdev) {
/* Must do after ntfs_open() to set the right blksize. */
set_fuseblk_options(parsed_options);
set_user_mount_option(parsed_options, uid);
}
fh = mount_fuse(parsed_options);
if (!fh)
goto err_out;
}
ctx->vol->free_mft_records = ntfs_get_nr_free_mft_records(ctx->vol);
if (ctx->vol->free_mft_records < 0) {
ntfs_log_perror("Failed to calculate free MFT records");
goto err_out;
}
if (use_blkdev) {
set_fuseblk_options(parsed_options);
set_user_mount_option(parsed_options, uid);
}
/* Libfuse can't always find fusermount, so let's help it. */
if (setenv("PATH", ":/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin", 0))
ntfs_log_perror("WARNING: Failed to set $PATH\n");
fc = try_fuse_mount(parsed_options);
if (!fc)
goto err_out;
fh = (struct fuse *)1; /* Cast anything except NULL to handle errors. */
if (fuse_opt_add_arg(&margs, "") == -1 ||
fuse_opt_add_arg(&margs, "-o") == -1)
fh = NULL;
if (!ctx->debug && !ctx->no_detach) {
if (fuse_opt_add_arg(&margs, "use_ino,kernel_cache") == -1)
fh = NULL;
} else {
if (fuse_opt_add_arg(&margs, "use_ino,kernel_cache,debug") == -1)
fh = NULL;
}
if (fh)
fh = fuse_new(fc, &margs , &ntfs_fuse_oper,
sizeof(ntfs_fuse_oper), NULL);
fuse_opt_free_args(&margs);
if (!fh) {
ntfs_log_error("fuse_new failed.\n");
fuse_unmount(opts.mnt_point, fc);
goto err_out;
}
if (setuid(uid)) {
ntfs_log_perror("Failed to set user ID to %d", uid);
fuse_unmount(opts.mnt_point, fc);
goto err_out;
goto err_umount;
}
#ifdef linux
#if defined(linux) || defined(__uClinux__)
if (S_ISBLK(sbuf.st_mode) && (fstype == FSTYPE_FUSE))
ntfs_log_info(fuse26_kmod_msg);
#endif
@ -2580,12 +2572,15 @@ int main(int argc, char *argv[])
fuse_loop(fh);
fuse_unmount(opts.mnt_point, fc);
fuse_destroy(fh);
err = 0;
err_umount:
fuse_unmount(opts.mnt_point, ctx->fc);
fuse_destroy(fh);
err_out:
free(opts.options);
ntfs_close();
free(ctx);
free(parsed_options);
ntfs_fuse_destroy();
free(opts.options);
free(opts.device);
return err;
}