From eb55c1662084b8c19079e3c537a51d1d85faf874 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Thu, 11 Jun 2026 09:11:17 +0000 Subject: [PATCH] quota: precheck first write for newly created files --- include/nwfile.h | 1 + src/nwfile.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/nwfile.h b/include/nwfile.h index 164e1e8..1f511a9 100644 --- a/include/nwfile.h +++ b/include/nwfile.h @@ -46,6 +46,7 @@ typedef struct { #define FH_DO_NOT_REUSE 0x04 #define FH_IS_READONLY 0x20 /* filesystem is readonly */ #define FH_OPENED_RO 0x40 /* is opened RO */ +#define FH_CREATED_NEW 0x80 /* newly created file: force first-write quota check */ extern void sig_bus_mmap(int rsig); diff --git a/src/nwfile.c b/src/nwfile.c index 775171a..330e0f8 100644 --- a/src/nwfile.c +++ b/src/nwfile.c @@ -493,6 +493,15 @@ int file_creat_open(int volume, uint8 *unixname, struct stat *stbuff, if (fh->fd==-1) completition=-0x9c; else { + /* + * ncpfs may create a new file and then make the first data write + * through a path where the local file already appears to have the + * target EOF. Keep a one-shot marker so the first write still + * runs the user-volume quota precheck. This matters for the + * metadata/NWQUOTA backend, where the kernel will not catch an + * already-sized newly-created file the way Linux quota does. + */ + fh->fh_flags |= FH_CREATED_NEW; if (seteuid(0)) {} stat(fh->fname, stbuff); (void)reseteuid(); @@ -959,7 +968,7 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset) if (fstat(fh->fd, &qst) == 0) { old_size = qst.st_size; - if (new_size > old_size) + if (new_size > old_size || (fh->fh_flags & FH_CREATED_NEW)) qresult = nw_check_vol_user_space((uint8)fh->volume, act_uid, fh->fname, old_size, new_size); @@ -968,6 +977,8 @@ int nw_write_file(int fhandle, uint8 *data, int size, uint32 offset) size = qresult; } else { size = write(fh->fd, data, size); + if (size > -1) + fh->fh_flags &= ~FH_CREATED_NEW; fh->offd+=(long)size; if (!fh->modified) fh->modified++;