From 9bd0d68e7711a593c1f071c76cdb513918523462 Mon Sep 17 00:00:00 2001 From: "Rob Swindell (on macOS)" <rob@synchro.net> Date: Tue, 31 Dec 2024 19:07:37 -0800 Subject: [PATCH] Check return value of lseek() before reading/writing node.dab records I don't know if these seek failures are actually happening or not, but reading from or writing to the wrong offset in the node.dab file could explain some of the node.dab corruption I'm seeing from macOS (over SMB share). --- src/sbbs3/getnode.cpp | 18 +++++++++--------- src/sbbs3/putnode.cpp | 11 ++++++----- src/sbbs3/userdat.c | 38 ++++++++++++++++++++++++++------------ src/sbbs3/userdat.h | 2 ++ 4 files changed, 43 insertions(+), 26 deletions(-) diff --git a/src/sbbs3/getnode.cpp b/src/sbbs3/getnode.cpp index 4ec584b233..475e59fda4 100644 --- a/src/sbbs3/getnode.cpp +++ b/src/sbbs3/getnode.cpp @@ -55,18 +55,18 @@ bool sbbs_t::getnodedat(uint number, node_t *node, bool lockit) else utime(str,NULL); /* NFS fix... utime() forces a cache refresh */ #endif - number--; /* make zero based */ for(count=0;count<LOOP_NODEDAB;count++) { - if(lockit && lock(nodefile,(long)number*sizeof(node_t),sizeof(node_t))!=0) { - unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t)); + if(lockit && lock(nodefile, nodedatoffset(number), sizeof(node_t))!=0) { + unlock(nodefile, nodedatoffset(number), sizeof(node_t)); continue; } - lseek(nodefile,(long)number*sizeof(node_t),SEEK_SET); - rd=read(nodefile,node,sizeof(node_t)); - if(rd!=sizeof(node_t)) - unlock(nodefile,(long)number*sizeof(node_t),sizeof(node_t)); - if(rd==sizeof(node_t)) - break; + if(seeknodedat(nodefile, number)) { + rd=read(nodefile,node,sizeof(node_t)); + if(rd!=sizeof(node_t)) + unlock(nodefile, nodedatoffset(number), sizeof(node_t)); + if(rd==sizeof(node_t)) + break; + } FILE_RETRY_DELAY(count + 1); } if(!lockit && cfg.node_misc&NM_CLOSENODEDAB) { diff --git a/src/sbbs3/putnode.cpp b/src/sbbs3/putnode.cpp index e8b9c183ae..4ebb40427a 100644 --- a/src/sbbs3/putnode.cpp +++ b/src/sbbs3/putnode.cpp @@ -60,11 +60,12 @@ bool sbbs_t::putnodedat(uint number, node_t* node) } for(attempts=0;attempts<10;attempts++) { - lseek(nodefile, (number - 1) * sizeof(node_t), SEEK_SET); - wr=write(nodefile,node,sizeof(node_t)); - if(wr==sizeof(node_t)) - break; - wrerr=errno; /* save write error */ + if(seeknodedat(nodefile, number)) { + wr=write(nodefile,node,sizeof(node_t)); + if(wr==sizeof(node_t)) + break; + wrerr=errno; /* save write error */ + } FILE_RETRY_DELAY(attempts + 1); } unlocknodedat(number); diff --git a/src/sbbs3/userdat.c b/src/sbbs3/userdat.c index 4b77d6d108..42c6ab0a83 100644 --- a/src/sbbs3/userdat.c +++ b/src/sbbs3/userdat.c @@ -1101,6 +1101,16 @@ int opennodedat(scfg_t* cfg) return nopen(fname, O_RDWR | O_CREAT | O_DENYNONE); } +off_t nodedatoffset(unsigned node_number) +{ + return (node_number - 1) * sizeof(node_t); +} + +bool seeknodedat(int file, unsigned node_number) +{ + return lseek(file, nodedatoffset(node_number), SEEK_SET) == nodedatoffset(node_number); +} + /****************************************************************************/ /****************************************************************************/ int opennodeext(scfg_t* cfg) @@ -1138,18 +1148,20 @@ int getnodedat(scfg_t* cfg, uint number, node_t *node, bool lockit, int* fdp) int result = USER_SIZE_ERROR; if(filelength(file)>=(long)(number*sizeof(node_t))) { - number--; /* make zero based */ for(count=0;count<LOOP_NODEDAB;count++) { - (void)lseek(file,(long)number*sizeof(node_t),SEEK_SET); + if(!seeknodedat(file, number)) { + result = USER_SEEK_ERROR; + continue; + } if(lockit - && lock(file,(long)number*sizeof(node_t),sizeof(node_t))!=0) { + && lock(file, nodedatoffset(number), sizeof(node_t))!=0) { result = USER_LOCK_ERROR; continue; } rd=read(file,node,sizeof(node_t)); if(rd!=sizeof(node_t)) { result = USER_READ_ERROR; - unlock(file,(long)number*sizeof(node_t),sizeof(node_t)); + unlock(file, nodedatoffset(number), sizeof(node_t)); } else { result = USER_SUCCESS; break; @@ -1172,8 +1184,8 @@ int getnodedat(scfg_t* cfg, uint number, node_t *node, bool lockit, int* fdp) /****************************************************************************/ int putnodedat(scfg_t* cfg, uint number, node_t* node, bool closeit, int file) { - size_t wr=0; int attempts; + int result = -1; if(file<0) return USER_INVALID_ARG; @@ -1184,20 +1196,22 @@ int putnodedat(scfg_t* cfg, uint number, node_t* node, bool closeit, int file) return USER_INVALID_ARG; } - number--; /* make zero based */ for(attempts=0;attempts<LOOP_USERDAT;attempts++) { - (void)lseek(file,(long)number*sizeof(node_t),SEEK_SET); - if((wr=write(file,node,sizeof(node_t)))==sizeof(node_t)) + if(!seeknodedat(file, number)) + result = USER_SEEK_ERROR; + else if(write(file,node,sizeof(node_t)) != sizeof(node_t)) + result = USER_WRITE_ERROR; + else { + result = USER_SUCCESS; break; + } FILE_RETRY_DELAY(attempts + 1); } - unlock(file,(long)number*sizeof(node_t),sizeof(node_t)); + unlock(file, nodedatoffset(number), sizeof(node_t)); if(closeit) close(file); - if(wr!=sizeof(node_t)) - return USER_WRITE_ERROR; - return USER_SUCCESS; + return result; } /****************************************************************************/ diff --git a/src/sbbs3/userdat.h b/src/sbbs3/userdat.h index 0d60262daa..4f6077c05d 100644 --- a/src/sbbs3/userdat.h +++ b/src/sbbs3/userdat.h @@ -90,6 +90,8 @@ DLLEXPORT char* username(scfg_t*, int usernumber, char * str); DLLEXPORT char* usermailaddr(scfg_t*, char* addr, const char* name); DLLEXPORT void smtp_netmailaddr(scfg_t*, smbmsg_t*, char* name, size_t namelen, char* addr, size_t addrlen); DLLEXPORT int opennodedat(scfg_t*); +DLLEXPORT off_t nodedatoffset(unsigned node_number); +DLLEXPORT bool seeknodedat(int file, unsigned node_number); DLLEXPORT int opennodeext(scfg_t*); DLLEXPORT int getnodedat(scfg_t*, uint number, node_t *node, bool lockit, int* file); DLLEXPORT int putnodedat(scfg_t*, uint number, node_t *node, bool closeit, int file); -- GitLab