Fix pg_file_write() error handling.
authorNoah Misch <[email protected]>
Sun, 12 Mar 2017 23:35:31 +0000 (19:35 -0400)
committerNoah Misch <[email protected]>
Sun, 12 Mar 2017 23:35:31 +0000 (19:35 -0400)
Detect fclose() failures; given "ln -s /dev/full $PGDATA/devfull",
"pg_file_write('devfull', 'x', true)" now fails as it should.  Don't
leak a stream when fwrite() fails.  Remove a born-ineffective test that
aimed to skip zero-length writes.  Back-patch to 9.2 (all supported
versions).

contrib/adminpack/adminpack.c

index c7ff9055ef304bdd739ceab378c24a345d8e4331..a63ff36f05cebd27bc9323a417a59d61fe2ef6f5 100644 (file)
@@ -136,10 +136,10 @@ pg_file_write(PG_FUNCTION_ARGS)
                    (ERRCODE_DUPLICATE_FILE,
                     errmsg("file \"%s\" exists", filename)));
 
-       f = fopen(filename, "wb");
+       f = AllocateFile(filename, "wb");
    }
    else
-       f = fopen(filename, "ab");
+       f = AllocateFile(filename, "ab");
 
    if (!f)
        ereport(ERROR,
@@ -147,16 +147,11 @@ pg_file_write(PG_FUNCTION_ARGS)
                 errmsg("could not open file \"%s\" for writing: %m",
                        filename)));
 
-   if (VARSIZE(data) != 0)
-   {
-       count = fwrite(VARDATA(data), 1, VARSIZE(data) - VARHDRSZ, f);
-
-       if (count != VARSIZE(data) - VARHDRSZ)
-           ereport(ERROR,
-                   (errcode_for_file_access(),
-                    errmsg("could not write file \"%s\": %m", filename)));
-   }
-   fclose(f);
+   count = fwrite(VARDATA(data), 1, VARSIZE(data) - VARHDRSZ, f);
+   if (count != VARSIZE(data) - VARHDRSZ || FreeFile(f))
+       ereport(ERROR,
+               (errcode_for_file_access(),
+                errmsg("could not write file \"%s\": %m", filename)));
 
    PG_RETURN_INT64(count);
 }