X-Git-Url: https://git.cameronkatri.com/pw-darwin.git/blobdiff_plain/b1da672b1218212f3151eff39f55f65f6f1bbac0..b0081f6365e438f9d18dba1905ca9989451bb14d:/pw/fileupd.c?ds=sidebyside diff --git a/pw/fileupd.c b/pw/fileupd.c index 0abaac6..a846513 100644 --- a/pw/fileupd.c +++ b/pw/fileupd.c @@ -22,10 +22,13 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $Id: fileupd.c,v 1.1.1.1 1996/12/09 14:05:35 joerg Exp $ */ +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + #include #include #include @@ -38,50 +41,90 @@ #include "pwupd.h" +int +extendline(char **buf, int * buflen, int needed) +{ + if (needed > *buflen) { + char *tmp = realloc(*buf, needed); + if (tmp == NULL) + return -1; + *buf = tmp; + *buflen = needed; + } + return *buflen; +} + +int +extendarray(char ***buf, int * buflen, int needed) +{ + if (needed > *buflen) { + char **tmp = realloc(*buf, needed * sizeof(char *)); + if (tmp == NULL) + return -1; + *buf = tmp; + *buflen = needed; + } + return *buflen; +} + + int fileupdate(char const * filename, mode_t fmode, char const * newline, char const * prefix, int pfxlen, int updmode) { - int rc = 0; + int rc = 0; if (pfxlen <= 1) - errno = EINVAL; + rc = EINVAL; else { - int infd = open(filename, O_RDWR | O_CREAT | O_EXLOCK, fmode); + int infd = open(filename, O_RDWR | O_CREAT, fmode); - if (infd != -1) { - FILE *infp = fdopen(infd, "r+"); + if (infd == -1) + rc = errno; + else { + FILE *infp = fdopen(infd, "r+"); - if (infp == NULL) + if (infp == NULL) { + rc = errno; /* Assumes fopen(3) sets errno from open(2) */ close(infd); - else { - int outfd; - char file[MAXPATHLEN]; + } else { + int outfd; + char file[MAXPATHLEN]; strcpy(file, filename); strcat(file, ".new"); outfd = open(file, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, fmode); - if (outfd != -1) { - FILE *outfp = fdopen(outfd, "w+"); + if (outfd == -1) + rc = errno; + else { + FILE *outfp = fdopen(outfd, "w+"); - if (outfp == NULL) + if (outfp == NULL) { + rc = errno; close(outfd); - else { - int updated = UPD_CREATE; - char line[2048]; - - while (fgets(line, sizeof(line), infp) != NULL) { - char *p = strchr(line, '\n'); - - if (p == NULL) { /* Line too long */ - int ch; - - fputs(line, outfp); - while ((ch = fgetc(infp)) != EOF) { - fputc(ch, outfp); - if (ch == '\n') - break; + } else { + int updated = UPD_CREATE; + int linesize = PWBUFSZ; + char *line = malloc(linesize); + + nextline: + while (fgets(line, linesize, infp) != NULL) { + char *p = strchr(line, '\n'); + + while ((p = strchr(line, '\n')) == NULL) { + int l; + if (extendline(&line, &linesize, linesize + PWBUFSZ) == -1) { + int ch; + fputs(line, outfp); + while ((ch = fgetc(infp)) != EOF) { + fputc(ch, outfp); + if (ch == '\n') + break; + } + goto nextline; } - continue; + l = strlen(line); + if (fgets(line + l, linesize - l, infp) == NULL) + break; } if (*line != '#' && *line != '\n') { if (!updated && strncmp(line, prefix, pfxlen) == 0) { @@ -106,7 +149,11 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const * then error */ if (updmode != updated) - errno = (updmode == UPD_CREATE) ? EEXIST : ENOENT; + /* -1 return means: + * update,delete=no user entry + * create=entry exists + */ + rc = -1; else { /* @@ -118,29 +165,34 @@ fileupdate(char const * filename, mode_t fmode, char const * newline, char const /* * Flush the file and check for the result */ - rc = fflush(outfp) != EOF; - if (rc) { - + if (fflush(outfp) == EOF) + rc = errno; /* Failed to update */ + else { /* * Copy data back into the * original file and truncate */ rewind(infp); rewind(outfp); - while (fgets(line, sizeof(line), outfp) != NULL) + while (fgets(line, linesize, outfp) != NULL) fputs(line, infp); /* + * If there was a problem with copying + * we will just rename 'file.new' + * to 'file'. * This is a gross hack, but we may have * corrupted the original file - * Unfortunately, it will lose the inode. + * Unfortunately, it will lose the inode + * and hence the lock. */ if (fflush(infp) == EOF || ferror(infp)) - rc = rename(file, filename) == 0; + rename(file, filename); else ftruncate(infd, ftell(infp)); } } + free(line); fclose(outfp); } remove(file);