]> git.cameronkatri.com Git - pw-darwin.git/blobdiff - pw/fileupd.c
Revert the libcrypt/libmd stuff back to how it was. This should not have
[pw-darwin.git] / pw / fileupd.c
index 0abaac6d11f03061e05a1557b73646939cceb802..a846513dbea3e15050a26aa0c65d08a939b80cf8 100644 (file)
  * 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 <stdio.h>
 #include <fcntl.h>
 #include <stdlib.h>
 
 #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);