Synchronet now requires the libarchive development package (e.g. libarchive-dev on Debian-based Linux distros, libarchive.org for more info) to build successfully.

Commit 7db3b623 authored by Rob Swindell's avatar Rob Swindell 💬

Refactor putuserrec()

This started with a Coverity issue (CID 33230) which got me looking at this function and wondering: why is str2 being NUL-terminated here? Why is the length of str2 to be calculated on successive lines? What is with this (long)((long)((long)((long)) typecast?

This was some of the oldest code in Synchronet (along with a lot of the other functions in this file). I tried to keep as much intact as possible while still improving the logic and readability.
parent 12fde4ab
Pipeline #1912 passed with stage
in 8 minutes and 18 seconds
......@@ -2217,66 +2217,73 @@ int getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str)
}
/****************************************************************************/
/* Places into user.dat at the offset for usernumber+start for length bytes */
/* Called from various locations */
/* Write a string (str) into user.dat at the offset for usernumber + start */
/* 'length' may be auto-determined (from 'start') by passing 0 for length */
/* If 'str' is longer than 'length', only 'length' characters are written */
/****************************************************************************/
int putuserrec(scfg_t* cfg, int usernumber,int start, uint length, const char *str)
int putuserrec(scfg_t* cfg, int usernumber, int start, int length, const char *str)
{
char str2[256];
const char* p;
char buf[256];
char path[MAX_PATH + 1];
int file;
uint c,i;
uint i;
if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
return(-1);
if(!VALID_CFG(cfg) || usernumber < 1 || str == NULL)
return -1;
if(length > sizeof(str2) - 1)
return -10;
if(length == 0) { /* auto-length */
length = user_rec_len(start);
if(length < 1)
return -2;
}
size_t slen = strlen(str);
if(slen >= (size_t)length)
p = str;
else {
if(length > sizeof(buf))
return -10;
memset(buf, ETX, length);
memcpy(buf, str, slen);
p = buf;
}
SAFEPRINTF(str2,"%suser/user.dat",cfg->data_dir);
if((file=nopen(str2,O_RDWR|O_DENYNONE))==-1)
return(errno);
SAFEPRINTF(path, "%suser/user.dat", cfg->data_dir);
if((file = nopen(path, O_RDWR|O_DENYNONE))==-1)
return errno;
if(filelength(file)<((long)usernumber-1)*U_LEN) {
off_t offset = (usernumber - 1) * U_LEN;
if(filelength(file) < offset) {
close(file);
return(-4);
}
if(length==0) { /* auto-length */
length=user_rec_len(start);
if((long)length < 0) {
close(file);
return -2;
}
return -4;
}
SAFECOPY(str2,str);
if(strlen(str2)<length) {
for(c=strlen(str2);c<length;c++)
str2[c]=ETX;
str2[c]=0;
offset += start;
if(lseek(file, offset, SEEK_SET) != offset) {
close(file);
return -5;
}
lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET);
i=0;
while(i<LOOP_NODEDAB
&& lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
while(i < LOOP_NODEDAB
&& lock(file, offset, length) == -1) {
if(i)
mswait(100);
i++;
}
if(i>=LOOP_NODEDAB) {
if(i >= LOOP_NODEDAB) {
close(file);
return(-3);
return -3;
}
int wr = write(file, str2, length);
unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
int wr = write(file, p, length);
unlock(file, offset, length);
close(file);
if(wr != length)
return -4;
dirtyuserdat(cfg,usernumber);
return(0);
return -6;
dirtyuserdat(cfg, usernumber);
return 0;
}
/****************************************************************************/
......
......@@ -81,7 +81,7 @@ DLLEXPORT uint userdatdupe(scfg_t*, uint usernumber, uint offset, uint datlen, c
DLLEXPORT BOOL chk_ar(scfg_t*, uchar* str, user_t*, client_t*); /* checks access requirements */
DLLEXPORT int getuserrec(scfg_t*, int usernumber, int start, int length, char *str);
DLLEXPORT int putuserrec(scfg_t*, int usernumber, int start, uint length, const char *str);
DLLEXPORT int putuserrec(scfg_t*, int usernumber, int start, int length, const char *str);
DLLEXPORT ulong adjustuserrec(scfg_t*, int usernumber, int start, int length, long adj);
DLLEXPORT BOOL logoutuserdat(scfg_t*, user_t*, time_t now, time_t logontime);
DLLEXPORT void resetdailyuserdat(scfg_t*, user_t*, BOOL write);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment