diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 63b1b88b..603ec823 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -179,7 +179,8 @@ struct open_file { enum { CLOSE_GHOST = 1, CLOSE_COMPRESSED = 2, - CLOSE_ENCRYPTED = 4 + CLOSE_ENCRYPTED = 4, + CLOSE_DMTIME = 8 }; static struct ntfs_options opts; @@ -1219,6 +1220,9 @@ static void ntfs_fuse_open(fuse_req_t req, fuse_ino_t ino, && (ni->flags & FILE_ATTR_ENCRYPTED)) state |= CLOSE_ENCRYPTED; #endif /* HAVE_SETXATTR */ + /* mark a future need to update the mtime */ + if (ctx->dmtime) + state |= CLOSE_DMTIME; /* deny opening metadata files for writing */ if (ino < FILE_first_user) res = -EPERM; @@ -1355,7 +1359,7 @@ static void ntfs_fuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf, total += ret; } res = total; - if (res > 0) + if ((res > 0) && !ctx->dmtime) ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME); exit: if (na) @@ -1911,6 +1915,8 @@ static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name, && (ni->flags & FILE_ATTR_ENCRYPTED)) state |= CLOSE_ENCRYPTED; #endif /* HAVE_SETXATTR */ + if (fi && ctx->dmtime) + state |= CLOSE_DMTIME; ntfs_inode_update_mbsname(dir_ni, name, ni->mft_no); NInoSetDirty(ni); e->ino = ni->mft_no; @@ -2381,7 +2387,9 @@ static void ntfs_fuse_release(fuse_req_t req, fuse_ino_t ino, of = (struct open_file*)(long)fi->fh; /* Only for marked descriptors there is something to do */ - if (!of || !(of->state & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED))) { + if (!of + || !(of->state & (CLOSE_COMPRESSED + | CLOSE_ENCRYPTED | CLOSE_DMTIME))) { res = 0; goto out; } @@ -2396,6 +2404,8 @@ static void ntfs_fuse_release(fuse_req_t req, fuse_ino_t ino, goto exit; } res = 0; + if (of->state & CLOSE_DMTIME) + ntfs_inode_update_times(ni,NTFS_UPDATE_MCTIME); if (of->state & CLOSE_COMPRESSED) res = ntfs_attr_pclose(na); #ifdef HAVE_SETXATTR /* extended attributes interface required */ diff --git a/src/ntfs-3g.8.in b/src/ntfs-3g.8.in index 01f9e123..1f0dc8ce 100644 --- a/src/ntfs-3g.8.in +++ b/src/ntfs-3g.8.in @@ -199,6 +199,12 @@ this option doesn't break applications that need to know if a file has been read since the last time it was modified. This is the default behaviour. .TP +.B delay_mtime +Delay the updating of file modification time and file change time until +the file is closed. This is mainly useful for files which are written +to without changing their size, such as databases or file system images +mounted as loop. +.TP .B show_sys_files Show the metafiles in directory listings. Otherwise the default behaviour is to hide the metafiles, which are special files used to store the NTFS diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index c1497b95..73392483 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -140,7 +140,8 @@ typedef struct { enum { CLOSE_COMPRESSED = 1, - CLOSE_ENCRYPTED = 2 + CLOSE_ENCRYPTED = 2, + CLOSE_DMTIME = 4 }; static struct ntfs_options opts; @@ -1167,6 +1168,9 @@ static int ntfs_fuse_open(const char *org_path, && (ni->flags & FILE_ATTR_ENCRYPTED)) fi->fh |= CLOSE_ENCRYPTED; #endif /* HAVE_SETXATTR */ + /* mark a future need to update the mtime */ + if (ctx->dmtime) + fi->fh |= CLOSE_DMTIME; /* deny opening metadata files for writing */ if (ni->mft_no < FILE_first_user) res = -EPERM; @@ -1289,7 +1293,7 @@ static int ntfs_fuse_write(const char *org_path, const char *buf, size_t size, total += ret; } res = total; - if (res > 0) + if ((res > 0) && !ctx->dmtime) ntfs_fuse_update_times(na->ni, NTFS_UPDATE_MCTIME); exit: if (na) @@ -1315,7 +1319,7 @@ static int ntfs_fuse_release(const char *org_path, int stream_name_len, res; /* Only for marked descriptors there is something to do */ - if (!(fi->fh & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED))) { + if (!(fi->fh & (CLOSE_COMPRESSED | CLOSE_ENCRYPTED | CLOSE_DMTIME))) { res = 0; goto out; } @@ -1335,6 +1339,8 @@ static int ntfs_fuse_release(const char *org_path, goto exit; } res = 0; + if (fi->fh & CLOSE_DMTIME) + ntfs_inode_update_times(na->ni,NTFS_UPDATE_MCTIME); if (fi->fh & CLOSE_COMPRESSED) res = ntfs_attr_pclose(na); #ifdef HAVE_SETXATTR /* extended attributes interface required */ @@ -1712,6 +1718,9 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev, && (ni->flags & FILE_ATTR_ENCRYPTED)) fi->fh |= CLOSE_ENCRYPTED; #endif /* HAVE_SETXATTR */ + /* mark a need to update the mtime */ + if (fi && ctx->dmtime) + fi->fh |= CLOSE_DMTIME; NInoSetDirty(ni); /* * closing ni requires access to dir_ni to @@ -1781,6 +1790,8 @@ static int ntfs_fuse_create_stream(const char *path, && (ni->flags & FILE_ATTR_ENCRYPTED)) fi->fh |= CLOSE_ENCRYPTED; #endif /* HAVE_SETXATTR */ + if (ctx->dmtime) + fi->fh |= CLOSE_DMTIME; } if (ntfs_inode_close(ni)) diff --git a/src/ntfs-3g_common.c b/src/ntfs-3g_common.c index 85d267d6..dc5fc370 100644 --- a/src/ntfs-3g_common.c +++ b/src/ntfs-3g_common.c @@ -76,6 +76,7 @@ const struct DEFOPTION optionlist[] = { { "noatime", OPT_NOATIME, FLGOPT_BOGUS }, { "atime", OPT_ATIME, FLGOPT_BOGUS }, { "relatime", OPT_RELATIME, FLGOPT_BOGUS }, + { "delay_mtime", OPT_DMTIME, FLGOPT_BOGUS }, { "fake_rw", OPT_FAKE_RW, FLGOPT_BOGUS }, { "fsname", OPT_FSNAME, FLGOPT_NOSUPPORT }, { "no_def_opts", OPT_NO_DEF_OPTS, FLGOPT_BOGUS }, @@ -238,6 +239,9 @@ char *parse_mount_options(ntfs_fuse_context_t *ctx, case OPT_RELATIME : ctx->atime = ATIME_RELATIVE; break; + case OPT_DMTIME : + ctx->dmtime = TRUE; + break; case OPT_NO_DEF_OPTS : no_def_opts = TRUE; /* Don't add default options. */ ctx->silent = FALSE; /* cancel default silent */ diff --git a/src/ntfs-3g_common.h b/src/ntfs-3g_common.h index f1ac1e5a..9d269841 100644 --- a/src/ntfs-3g_common.h +++ b/src/ntfs-3g_common.h @@ -50,6 +50,7 @@ enum { OPT_NOATIME, OPT_ATIME, OPT_RELATIME, + OPT_DMTIME, OPT_FAKE_RW, OPT_FSNAME, OPT_NO_DEF_OPTS, @@ -116,6 +117,7 @@ typedef struct { unsigned int dmask; ntfs_fuse_streams_interface streams; ntfs_atime_t atime; + BOOL dmtime; BOOL ro; BOOL show_sys_files; BOOL hide_hid_files;