Re: tmpfile alternative

From: Giorgio Zoppi (denebat_private)
Date: Thu Jan 03 2002 - 09:45:46 PST

  • Next message: Tim van Erven: "Re: tmpfile alternative"

    Thanks for your answers.  
    
    So this is better (my major mistake was the assumption that fopen implementations
    are safe against race condition):
    
    #include <string.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include "bondlog.h" /* here there are all headers needed by the app */
    #include <time.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <pwd.h>
    
    #define MAX_BUF 11
    #define RANDOMFILE "/dev/urandom"
    
    FILE *
    mytmpfile (void )
    {
    
      char appname[] = "/var/spool/bondlog/tmp";
      char filename[PATH_MAX];
      base64buf b;
      unsigned int num = 0;
      unsigned int count = 0;
      int mypid;
      FILE *urand_file;
      FILE *tmp;
      unsigned char *stream;
      struct stat f_stat_info, l_stat_info;
      int fd, finfo;
    
      if ((stream = (char *) malloc (MAX_BUF)) == NULL)
        {
          return NULL;
        }
      
      memset (stream, '\0', MAX_BUF);
      memset(filename,'\0',sizeof(filename)-1);
    
      urand_file = fopen (RANDOMFILE, "r");
    
      if (urand_file == NULL)
        {
          /* If I cannot open the random file 
             i assume that i can't create a safe filename 
    	so I cannot assume that the file creation is safe
    */
          free (stream);
          return NULL;
        }
      do
        {
    
          count = 0;
    
          while (count < 9)
    	{
    	  fread (&num, sizeof (unsigned int), 1, urand_file);
    	  stream[count] = (char) num;
    	  count++;
    	}
          base64_encode (&b, stream, 9);
          
          memset (filename, '\0', sizeof (filename)-1);
          mypid = (int) getpid();
          snprintf (filename, sizeof (filename), "%s-%d-%s", appname, mypid, b.data);
        }
    
      while ((finfo = lstat (filename, &l_stat_info)) != -1);
    
      fclose (urand_file);
    
      if (finfo == -1)
        {
          
          if (errno != ENOENT)
    	return NULL;
    
          if ((fd = open (filename, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1)
    	return NULL;
    
          lstat (filename, &l_stat_info);
          }
      else
        {
          free (stream);
          return NULL;
        }
      
       if ((fstat (fd, &f_stat_info) == -1) ||
    	  (l_stat_info.st_mode != f_stat_info.st_mode) ||
    	  (l_stat_info.st_ino != f_stat_info.st_ino) ||
    	  (l_stat_info.st_dev != f_stat_info.st_dev))
    	{ 
    	  free(stream);
    	  close (fd);
    	  return NULL;
    	}
        
      if ((tmp = fdopen (fd, "r+b")) == NULL)
        {
          close (fd);
          unlink (filename);
          free (stream);
          return NULL;
        }
      unlink (filename);		// the file will be not delete until closed;
      free (stream);
      buffer_delete (&b);
      return (tmp);
    }
    
    ---------------end-------------------
    



    This archive was generated by hypermail 2b30 : Thu Jan 03 2002 - 12:08:14 PST