From 5aa177e03bfa30a7434fa9bb9e0dfd81ee4d9313 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 20 Jan 2016 09:36:07 -0600 Subject: [PATCH] apps/fsutils/passwd: Fix numerous errors found during testing --- fsutils/passwd/passwd_adduser.c | 2 + fsutils/passwd/passwd_append.c | 2 +- fsutils/passwd/passwd_delete.c | 90 +++++++++++++++++++++++++++------ fsutils/passwd/passwd_deluser.c | 3 +- fsutils/passwd/passwd_find.c | 6 +-- include/fsutils/passwd.h | 9 +++- 6 files changed, 91 insertions(+), 21 deletions(-) diff --git a/fsutils/passwd/passwd_adduser.c b/fsutils/passwd/passwd_adduser.c index e8f8c4656..b37c30f29 100644 --- a/fsutils/passwd/passwd_adduser.c +++ b/fsutils/passwd/passwd_adduser.c @@ -55,6 +55,8 @@ * then this function will fail with -EEXIST. * * Input Parameters: + * username - Identifies the user to be added + * password - The password for the new user * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on diff --git a/fsutils/passwd/passwd_append.c b/fsutils/passwd/passwd_append.c index 12e27093f..5209b9fad 100644 --- a/fsutils/passwd/passwd_append.c +++ b/fsutils/passwd/passwd_append.c @@ -77,7 +77,7 @@ int passwd_append(FAR const char *username, FAR const char *password) /* Append the new user record to the end of the password file */ - stream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "at"); + stream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "a"); if (stream == NULL) { int errcode = errno; diff --git a/fsutils/passwd/passwd_delete.c b/fsutils/passwd/passwd_delete.c index 27b1caa56..2167dd5e0 100644 --- a/fsutils/passwd/passwd_delete.c +++ b/fsutils/passwd/passwd_delete.c @@ -76,14 +76,18 @@ static int passwd_copyfile(FAR char *iobuffer, FILE *instream, size_t nbytes; size_t gulpsize; size_t ncopied; + size_t remaining; + bool eof; /* Copy 'offset' bytes from the instream to the outstream */ - for (ncopied = 0; ncopied < copysize; ncopied += nwritten) + for (ncopied = 0, remaining = copysize, eof = false; + ncopied < copysize && !eof; + ncopied += nwritten) { /* How big of a gulp can we take on this pass through the loop */ - gulpsize = copysize; + gulpsize = remaining; if (gulpsize > CONFIG_FSUTILS_PASSWD_IOBUFFER_SIZE) { gulpsize = CONFIG_FSUTILS_PASSWD_IOBUFFER_SIZE; @@ -98,24 +102,56 @@ static int passwd_copyfile(FAR char *iobuffer, FILE *instream, do { nxfrd = fread(buffer, 1, nbytes, instream); - if (nxfrd < 0) + if (nxfrd == 0) { - int errcode = errno; - DEBUGASSERT(errcode > 0); + /* Zero is returned on either a read error or end-of-file */ - if (errcode != EINTR) + if (ferror(instream)) { - return -errcode; + /* Read error */ + + int errcode = errno; + DEBUGASSERT(errcode > 0); + + if (errcode != EINTR) + { + return -errcode; + } + } + else + { + /* End of file encountered. + * + * This occurs normally when copying to the end-of-the file. + * In that case, the caller just sticks a huge number in for + * copysize and lets the end-of-file indication terminate the + * copy. + */ + + eof = true; + + /* Was anything buffered on this pass? */ + + if (nread == 0) + { + /* No.. then we can just return success now */ + + return OK; + } } } else { + DEBUGASSERT(nxfrd > 0); + + /* Update counters and pointers for successful read */ + nread += nxfrd; buffer += nxfrd; nbytes -= nxfrd; } } - while (nread < gulpsize); + while (nread < gulpsize && !eof); /* Write the buffer of data to outstream */ @@ -125,9 +161,11 @@ static int passwd_copyfile(FAR char *iobuffer, FILE *instream, do { - nxfrd = fwrite(buffer, 1, nbytes, instream); - if (nxfrd < 0) + nxfrd = fwrite(buffer, 1, nbytes, outstream); + if (nxfrd == 0) { + /* Write error */ + int errcode = errno; DEBUGASSERT(errcode > 0); @@ -138,13 +176,18 @@ static int passwd_copyfile(FAR char *iobuffer, FILE *instream, } else { + DEBUGASSERT(nxfrd > 0); + + /* Update counters and pointers for successful write */ + nwritten += nxfrd; buffer += nxfrd; nbytes -= nxfrd; } } while (nwritten < nread); - copysize -= nwritten; + + remaining -= nwritten; } return OK; @@ -185,7 +228,8 @@ int passwd_delete(off_t offset) /* Rename the /set/password file */ - ret = rename(CONFIG_FSUTILS_PASSWD_PATH, CONFIG_FSUTILS_PASSWD_PATH ".tmp"); + ret = rename(CONFIG_FSUTILS_PASSWD_PATH, + CONFIG_FSUTILS_PASSWD_PATH ".tmp"); if (ret < 0) { ret = -errno; @@ -197,15 +241,15 @@ int passwd_delete(off_t offset) * writing. */ - instream = fopen(CONFIG_FSUTILS_PASSWD_PATH ".tmp", "rt"); + instream = fopen(CONFIG_FSUTILS_PASSWD_PATH ".tmp", "r"); if (instream == NULL) { ret = -errno; DEBUGASSERT(ret < 0); - goto errout_with_iobuffer; + goto errout_with_tmpfile; } - outstream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "wt"); + outstream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "w"); if (outstream == NULL) { ret = -errno; @@ -259,6 +303,22 @@ errout_with_outstream: errout_with_instream: (void)fclose(instream); +errout_with_tmpfile: + if (ret < 0) + { + /* Restore the previous /etc/passwd file */ + + (void)unlink(CONFIG_FSUTILS_PASSWD_PATH); + (void)rename(CONFIG_FSUTILS_PASSWD_PATH ".tmp", + CONFIG_FSUTILS_PASSWD_PATH); + } + else + { + /* Delete the previous /etc/passwd file */ + + (void)unlink(CONFIG_FSUTILS_PASSWD_PATH ".tmp"); + } + errout_with_iobuffer: free(iobuffer); return ret; diff --git a/fsutils/passwd/passwd_deluser.c b/fsutils/passwd/passwd_deluser.c index 0604acc50..a6df2807a 100644 --- a/fsutils/passwd/passwd_deluser.c +++ b/fsutils/passwd/passwd_deluser.c @@ -55,6 +55,7 @@ * not exist, then this function will fail. * * Input Parameters: + * username - Identifies the user to be deleted * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -62,7 +63,7 @@ * ****************************************************************************/ -int passwd_deluser(FAR const char *username, FAR const char *password) +int passwd_deluser(FAR const char *username) { struct passwd_s passwd; FAR sem_t *sem; diff --git a/fsutils/passwd/passwd_find.c b/fsutils/passwd/passwd_find.c index 3bae9f8df..c38f37da4 100644 --- a/fsutils/passwd/passwd_find.c +++ b/fsutils/passwd/passwd_find.c @@ -85,12 +85,12 @@ int passwd_find(FAR const char *username, FAR struct passwd_s *passwd) /* Open the password file for reading */ - stream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "at"); + stream = fopen(CONFIG_FSUTILS_PASSWD_PATH, "r"); if (stream == NULL) { int errcode = errno; DEBUGASSERT(errcode > 0); - return errcode; + return -errcode; } /* Read the password file line by line until the record with the matching @@ -132,7 +132,7 @@ int passwd_find(FAR const char *username, FAR struct passwd_s *passwd) { /* We have a match, skip over any whitespace after the user name */ - for (src = iobuffer; *src && isspace((int)*src); src++); + for (; *src && isspace((int)*src); src++); if (*src == '\0') { /* Bad file format? */ diff --git a/include/fsutils/passwd.h b/include/fsutils/passwd.h index 3374b2571..462d8cd5b 100644 --- a/include/fsutils/passwd.h +++ b/include/fsutils/passwd.h @@ -54,6 +54,8 @@ * then this function will fail with -EEXIST. * * Input Parameters: + * username - Identifies the user to be added + * password - The password for the new user * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -71,6 +73,7 @@ int passwd_adduser(FAR const char *username, FAR const char *password); * not exist, then this function will fail. * * Input Parameters: + * username - Identifies the user to be deleted * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -78,7 +81,7 @@ int passwd_adduser(FAR const char *username, FAR const char *password); * ****************************************************************************/ -int passwd_deluser(FAR const char *username, FAR const char *password); +int passwd_deluser(FAR const char *username); /**************************************************************************** * Name: passwd_update @@ -88,6 +91,8 @@ int passwd_deluser(FAR const char *username, FAR const char *password); * then this function will fail. * * Input Parameters: + * username - Identifies the user whose password will be updated + * password - The new password for the existing user * * Returned Value: * Zero (OK) is returned on success; a negated errno value is returned on @@ -105,6 +110,8 @@ int passwd_update(FAR const char *username, FAR const char *password); * password matches the user password in that faile. * * Input Parameters: + * username - Identifies the user whose password will be verified + * password - The password to be verified * * Returned Value: * One (1) is returned on success match, Zero (OK) is returned on an