Under VMS, ftruncate should be available
[openssl.git] / crypto / rand / randfile.c
index 8318df1c408f9c19fe8b933891f886e044743c93..375c339e5c3c6b5776f44afafa5e0a09754cd9ab 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/types.h>
 
-#ifndef FLAT_INC
-# include "../e_os.h"
+#include "openssl/e_os.h"
+
+#ifndef NO_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef MAC_OS_pre_X
+# include <stat.h>
 #else
-# include "e_os.h"
+# include <sys/stat.h>
 #endif
 
 #include <openssl/rand.h>
@@ -76,7 +78,7 @@
 #define BUFSIZE        1024
 #define RAND_DATA 1024
 
-/* #define RFILE ".rand" - defined in ../../e_os.h */
+/* #define RFILE ".rnd" - defined in ../../e_os.h */
 
 int RAND_load_file(const char *file, long bytes)
        {
@@ -89,8 +91,7 @@ int RAND_load_file(const char *file, long bytes)
 
        i=stat(file,&sb);
        /* If the state fails, put some crap in anyway */
-       RAND_seed(&sb,sizeof(sb));
-       ret+=sizeof(sb);
+       RAND_add(&sb,sizeof(sb),0);
        if (i < 0) return(0);
        if (bytes <= 0) return(ret);
 
@@ -102,7 +103,7 @@ int RAND_load_file(const char *file, long bytes)
                i=fread(buf,1,n,in);
                if (i <= 0) break;
                /* even if n != i, use the full array */
-               RAND_seed(buf,n);
+               RAND_add(buf,n,i);
                ret+=i;
                bytes-=n;
                if (bytes <= 0) break;
@@ -116,29 +117,42 @@ err:
 int RAND_write_file(const char *file)
        {
        unsigned char buf[BUFSIZE];
-       int i,ret=0;
-       FILE *out;
+       int i,ret=0,err=0;
+       FILE *out = NULL;
        int n;
 
-       /* Under VMS, fopen(file, "wb") will craete a new version of the
+#ifdef VMS
+       /* Under VMS, fopen(file, "wb") will create a new version of the
           same file.  This is not good, so let's try updating an existing
-          one, and create file only if it doesn't already exist.  This
-          should be completely harmless on system that have no file
-          versions.                                    -- Richard Levitte */
+          one, and create file only if it doesn't already exist. */
        out=fopen(file,"rb+");
-       if (out == NULL && errno == ENOENT)
+       if (out == NULL && errno != ENOENT)
+               goto err;
+#endif
+
+       if (out == NULL)
                {
-               errno = 0;
+#if defined O_CREAT && defined O_EXCL
+               /* chmod(..., 0600) is too late to protect the file,
+                * permissions should be restrictive from the start */
+               int fd = open(file, O_CREAT | O_EXCL, 0600);
+               if (fd != -1)
+                       out = fdopen(fd, "wb");
+#else          
                out=fopen(file,"wb");
+#endif
                }
        if (out == NULL) goto err;
+#ifndef NO_CHMOD
        chmod(file,0600);
+#endif
        n=RAND_DATA;
        for (;;)
                {
                i=(n > BUFSIZE)?BUFSIZE:n;
                n-=BUFSIZE;
-               RAND_bytes(buf,i);
+               if (RAND_bytes(buf,i) <= 0)
+                       err=1;
                i=fwrite(buf,1,i,out);
                if (i <= 0)
                        {
@@ -148,10 +162,17 @@ int RAND_write_file(const char *file)
                ret+=i;
                if (n <= 0) break;
                }
+#ifdef VMS
+       /* We may have updated an existing file using mode "rb+",
+        * now remove any old extra bytes */
+       if (ret > 0)
+               ftruncate(fileno(out), ret);
+#endif
+
        fclose(out);
        memset(buf,0,BUFSIZE);
 err:
-       return(ret);
+       return(err ? -1 : ret);
        }
 
 char *RAND_file_name(char *buf, int size)