Пример #1
0
int     main(int argc, char **argv)
{
    msg_vstream_init(argv[0], VSTREAM_ERR);
    if (argc < 2)
	msg_fatal("usage: %s path...", argv[0]);
    while (--argc > 0 && *++argv != 0)
	if (make_dirs(*argv, 0755))
	    msg_fatal("%s: %m", *argv);
    exit(0);
}
Пример #2
0
int main( int argc, char* argv[] )
{
	#ifdef _WINDOWS
	_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
	#endif

	char conf_path[1024] = { 0 };
	if( xgc_nullptr == get_absolute_path( conf_path, "../client.ini" ) )
	{
		fprintf( stderr, "format conf path error %s", conf_path );
		return -1;
	}

	ini_reader ini;
	if( false == ini.load( conf_path ) )
	{
		fprintf( stderr, "conf load error %s", conf_path );
		return -1;
	}

	auto addr = ini.get_item_value( "Client", "Host", "127.0.0.1" );
	auto port = ini.get_item_value( "Client", "Port", 50001 );
	auto root = ini.get_item_value( "Client", "Root", xgc_nullptr );
	XGC_ASSERT_RETURN( root, -1 );

	make_dirs( root );
	strcpy_s( root_path, root );

	if( false == net::CreateNetwork( 1 ) )
		return -1;

	net::connect_options opt;
	memset( &opt, 0, sizeof( opt ) );
	opt.is_async = false;
	opt.is_reconnect_passive = false;
	opt.is_reconnect_timeout = false;
	opt.recv_buffer_size = 64 * 1024;
	opt.send_buffer_size = 64 * 1024;

	opt.recv_packet_max = 64 * 1024;
	opt.recv_packet_max = 64 * 1024;

	opt.timeout = 1000;

	net::Connect( addr, port, XGC_NEW CNetSession(), &opt );
	while( running )
	{
		if( net::ProcessNetEvent( 100 ) == 100 )
			std::this_thread::sleep_for( std::chrono::milliseconds(1) );
	}
	net::DestroyNetwork();

	return 0;
}
Пример #3
0
int process_template(HDF *hdf, char *infile, char *outfile)
{
  int ret = 0;
  FILE *outfh = NULL;
  NEOERR *err;
  CSPARSE *parse = NULL;

  if (!make_dirs(outfile))
  {
    ret = -1;
  }
  else
  {
    if ((outfh = fopen(outfile, "w")) == NULL)
    {
      perror("fopen");
      ret = -2;
    }
    else
    {
      err = cs_init(&parse, hdf);
      if (err != STATUS_OK)
      {
        nerr_log_error(err);
        ret = -5;
      }
      else
      { 
        err = cs_parse_file(parse, infile);
        if (err != STATUS_OK)
        {
          nerr_log_error(err);
          ret = -6;
        }
        
        err = cs_render(parse, outfh, csoutfunc);  
        if (err != STATUS_OK)
        {
          nerr_log_error(err);
          ret = -7;
        }

        cs_destroy(&parse);
      }
      fclose(outfh);
    }
  }
  return ret;
}
Пример #4
0
int main(void)
{
    int ret;

    ret = toku_fs_mount(MOUNT_PATH);
    assert(ret == 0);

    make_dirs();
    test_open_close_dir();

    ret = toku_fs_unmount();
    assert(ret == 0);

    return 0;
}
Пример #5
0
int main(void)
{


	/* setup fake directory structure we'll chroot */
	if (make_dirs())
		return EXIT_FAILURE;

	if (make_hardlinks())
		return EXIT_FAILURE;

	hack_the_planet();

	return EXIT_SUCCESS;
}
Пример #6
0
static void
make_dirs(YogEnv* env, const char* path)
{
    /**
     * TODO: Here is duplicated with builtins.make_dirs. To resolve this,
     * + make classes to represent struct zip etc.
     * + be open above classes to Yog script
     * + implement creating/extracting zips in Yog
     */
    char* dir = (char*)YogSysdeps_alloca(strlen(path) + 1);
    strcpy(dir, path);
    dirname(dir);
    if (dir[0] != '\0') {
        make_dirs(env, dir);
    }
    YogSysdeps_mkdir(path);
}
Пример #7
0
t3_config_write_file_t *t3_config_open_write(const char *file_name) {
	t3_config_write_file_t *result;
	char *dirsep;
	size_t length;
	char *pathname;
	int fd;

	if ((dirsep = strrchr(file_name, '/')) == NULL) {
		length = 0;
	} else {
		length = dirsep - file_name;
		if (length > 0)
			length--;
	}

	if ((pathname = malloc(strlen(file_name) + 1 + 7)) == NULL)
		return NULL;
	memcpy(pathname, file_name, length);
	pathname[length] = 0;

	if (length > 0 && !make_dirs(pathname)) {
		free(pathname);
		return NULL;
	}

	if (dirsep != NULL)
		strcat(pathname, "/");
	strcat(pathname, ".");
	strcat(pathname, dirsep == NULL ? file_name : dirsep + 1);
	strcat(pathname, "XXXXXX");
	if ((fd = mkstemp(pathname)) < 0) {
		free(pathname);
		return NULL;
	}

	if ((result = malloc(sizeof(t3_config_write_file_t))) == NULL || (result->file = fdopen(fd, "w")) == NULL) {
		close(fd);
		unlink(pathname);
		free(pathname);
		return NULL;
	}
	result->pathname = pathname;
	result->closed = t3_false;

	return result;
}
Пример #8
0
t3_config_write_file_t *t3_config_xdg_open_write(t3_config_xdg_dirs_t xdg_dir, const char *program_dir, const char *file_name) {
	t3_config_write_file_t *result;
	char *pathname;
	int fd;

	if (strchr(file_name, '/') != NULL) {
		errno = EINVAL;
		return NULL;
	}

	if ((pathname = t3_config_xdg_get_path(xdg_dir, program_dir, strlen(file_name) + 7)) == NULL)
		return NULL;

	if (!make_dirs(pathname)) {
		free(pathname);
		return NULL;
	}

	strcat(pathname, "/.");
	strcat(pathname, file_name);
	strcat(pathname, "XXXXXX");
	if ((fd = mkstemp(pathname)) < 0) {
		free(pathname);
		return NULL;
	}

	if ((result = malloc(sizeof(t3_config_write_file_t))) == NULL || (result->file = fdopen(fd, "w")) == NULL) {
		close(fd);
		unlink(pathname);
		free(pathname);
		return NULL;
	}
	result->pathname = pathname;
	result->closed = t3_false;

	return result;
}
Пример #9
0
int
main(int argc, char *argv[])
{
	int dflag = 0;
	char *gflag = 0;
	char *oflag = 0;
	char *mflag = 0;
	char *tflag = 0;
	struct group *gr;
	struct passwd *pw;
	struct stat st;
	char *p;

	ARGBEGIN {
	case 'd':
		dflag = 1;
		break;
	case 'D':
		Dflag = 1;
		break;
	case 's':
		sflag = 1;
		break;
	case 'g':
		gflag = EARGF(usage());
		break;
	case 'o':
		oflag = EARGF(usage());
		break;
	case 'm':
		mflag = EARGF(usage());
		break;
	case 't':
		tflag = EARGF(usage());
		break;
	default:
		usage();
	} ARGEND

	if (argc < 1 + (!tflag & !dflag) || dflag & (Dflag | sflag | !!tflag))
		usage();

	if (gflag) {
		errno = 0;
		gr = getgrnam(gflag);
		if (gr) {
			group = gr->gr_gid;
		} else {
			if (errno)
				eprintf("getgrnam %s:", gflag);
			group = estrtonum(gflag, 0, UINT_MAX);
		}
	} else {
		group = getgid();
	}

	if (oflag) {
		errno = 0;
		pw = getpwnam(oflag);
		if (pw) {
			owner = pw->pw_uid;
		} else {
			if (errno)
				eprintf("getpwnam %s:", oflag);
			owner = estrtonum(oflag, 0, UINT_MAX);
		}
	} else {
		owner = getuid();
	}

	if (mflag) {
		mode = parsemode(mflag, mode, 0);
		if (mode < 0)
			return 1;
	}

	if (tflag) {
		memmove(argv - 1, argv, argc);
		argv[argc++] = tflag;
	}
	if (tflag || argc > 2) {
		if (stat(argv[argc - 1], &st) < 0) {
			if ((errno == ENOENT) && Dflag) {
				make_dirs(argv[argc - 1], 1);
			} else {
				eprintf("stat %s:", argv[argc - 1]);
			}
		} else if (!S_ISDIR(st.st_mode)) {
			eprintf("%s: not a directory\n", argv[argc - 1]);
		}
	}

	if (dflag) {
		for (; *argv; argc--, argv++)
			make_dirs(*argv, 0);
	} else {
		if (stat(argv[argc - 1], &st) < 0) {
			if (errno != ENOENT)
				eprintf("stat %s:", argv[argc - 1]);
			if (tflag || Dflag || argc > 2) {
				if ((p = strrchr(argv[argc - 1], '/')) != NULL) {
					*p = '\0';
					make_dirs(argv[argc - 1], 1);
					*p = '/';
				}
			}
		}
		enmasse(argc, argv, install);
	}

	return 0;
}
Пример #10
0
/*
 * Extract a file from the archive.
 */
void
extract_archive ()
{
  register char *data;
  int fd, check, namelen, written, openflag;
  long size;
  struct utimbuf acc_upd_times;
  register int skipcrud;
  register int i;
  /*	int sparse_ind = 0;*/
  union record *exhdr;
  struct saved_dir_info *tmp;
  /*	int end_nulls; */

  saverec (&head);		/* Make sure it sticks around */
  userec (head);		/* And go past it in the archive */
  decode_header (head, &hstat, &head_standard, 1);	/* Snarf fields */

  if ((f_confirm && !confirm ("extract", current_file_name)) ||
      (f_exstdout && head->header.linkflag != LF_OLDNORMAL &&
       head->header.linkflag != LF_NORMAL &&
       head->header.linkflag != LF_CONTIG))
    {
      if (head->header.isextended)
	skip_extended_headers ();
      skip_file ((long) hstat.st_size);
      saverec ((union record **) 0);
      return;
    }

  /* Print the record from 'head' and 'hstat' */
  if (f_verbose)
    print_header ();

  /*
	 * Check for fully specified pathnames and other atrocities.
	 *
	 * Note, we can't just make a pointer to the new file name,
	 * since saverec() might move the header and adjust "head".
	 * We have to start from "head" every time we want to touch
	 * the header record.
	 */
  skipcrud = 0;
  while (!f_absolute_paths
	 && '/' == current_file_name[skipcrud])
    {
      static int warned_once = 0;

      skipcrud++;		/* Force relative path */
      if (!warned_once++)
	{
	  msg ("Removing leading / from absolute path names in the archive.");
	}
    }

  switch (head->header.linkflag)
    {

    default:
      msg ("Unknown file type '%c' for %s, extracted as normal file",
	   head->header.linkflag, skipcrud + current_file_name);
      /* FALL THRU */

      /*
	  * JK - What we want to do if the file is sparse is loop through
	  * the array of sparse structures in the header and read in
	  * and translate the character strings representing  1) the offset
	  * at which to write and 2) how many bytes to write into numbers,
	  * which we store into the scratch array, "sparsearray".  This
	  * array makes our life easier the same way it did in creating
	  * the tar file that had to deal with a sparse file.
	  *
	  * After we read in the first five (at most) sparse structures,
	  * we check to see if the file has an extended header, i.e.,
	  * if more sparse structures are needed to describe the contents
	  * of the new file.  If so, we read in the extended headers
	  * and continue to store their contents into the sparsearray.
	  */
    case LF_SPARSE:
      sp_array_size = 10;
      sparsearray = (struct sp_array *) ck_malloc (sp_array_size * sizeof (struct sp_array));
      for (i = 0; i < SPARSE_IN_HDR; i++)
	{
	  sparsearray[i].offset =
	    from_oct (1 + 12, head->header.sp[i].offset);
	  sparsearray[i].numbytes =
	    from_oct (1 + 12, head->header.sp[i].numbytes);
	  if (!sparsearray[i].numbytes)
	    break;
	}

      /*		end_nulls = from_oct(1+12, head->header.ending_blanks);*/

      if (head->header.isextended)
	{
	  /* read in the list of extended headers
			    and translate them into the sparsearray
			    as before */

	  /* static */ int ind = SPARSE_IN_HDR;

	  for (;;)
	    {

	      exhdr = findrec ();
	      for (i = 0; i < SPARSE_EXT_HDR; i++)
		{

		  if (i + ind > sp_array_size - 1)
		    {
		      /*
					  * realloc the scratch area
					  * since we've run out of room --
					  */
		      sparsearray = (struct sp_array *)
			ck_realloc (sparsearray,
			    2 * sp_array_size * (sizeof (struct sp_array)));
		      sp_array_size *= 2;
		    }
		  if (!exhdr->ext_hdr.sp[i].numbytes)
		    break;
		  sparsearray[i + ind].offset =
		    from_oct (1 + 12, exhdr->ext_hdr.sp[i].offset);
		  sparsearray[i + ind].numbytes =
		    from_oct (1 + 12, exhdr->ext_hdr.sp[i].numbytes);
		}
	      if (!exhdr->ext_hdr.isextended)
		break;
	      else
		{
		  ind += SPARSE_EXT_HDR;
		  userec (exhdr);
		}
	    }
	  userec (exhdr);
	}

      /* FALL THRU */
    case LF_OLDNORMAL:
    case LF_NORMAL:
    case LF_CONTIG:
      /*
		  * Appears to be a file.
		  * See if it's really a directory.
		  */
      namelen = strlen (skipcrud + current_file_name) - 1;
      if (current_file_name[skipcrud + namelen] == '/')
	goto really_dir;

      /* FIXME, deal with protection issues */
    again_file:
      openflag = (f_keep ?
		  O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_EXCL :
		  O_BINARY | O_NDELAY | O_WRONLY | O_CREAT | O_TRUNC)
	| ((head->header.linkflag == LF_SPARSE) ? 0 : O_APPEND);
      /*
			  * JK - The last | is a kludge to solve the problem
			  * the O_APPEND flag  causes with files we are
			  * trying to make sparse:  when a file is opened
			  * with O_APPEND, it writes  to the last place
			  * that something was written, thereby ignoring
			  * any lseeks that we have done.  We add this
			  * extra condition to make it able to lseek when
			  * a file is sparse, i.e., we don't open the new
			  * file with this flag.  (Grump -- this bug caused
			  * me to waste a good deal of time, I might add)
			  */

      if (f_exstdout)
	{
	  fd = 1;
	  goto extract_file;
	}

      if (f_unlink && !f_keep) {
	if (unlink(skipcrud + current_file_name) == -1)
		if (errno != ENOENT)
		   msg_perror ("Could not unlink %s",
                      skipcrud + current_file_name);
      }

#ifdef O_CTG
      /*
		  * Contiguous files (on the Masscomp) have to specify
		  * the size in the open call that creates them.
		  */
      if (head->header.linkflag == LF_CONTIG)
	fd = open ((longname ? longname : head->header.name)
		   + skipcrud,
		   openflag | O_CTG,
		   hstat.st_mode, hstat.st_size);
      else
#endif
	{
#ifdef NO_OPEN3
	  /*
			  * On raw V7 we won't let them specify -k (f_keep), but
			  * we just bull ahead and create the files.
			  */
	  fd = creat ((longname
		       ? longname
		       : head->header.name) + skipcrud,
		      hstat.st_mode);
#else
	  /*
			  * With 3-arg open(), we can do this up right.
			  */
	  fd = open (skipcrud + current_file_name,
		     openflag, hstat.st_mode);
#endif
	}

      if (fd < 0)
	{
	  if (make_dirs (skipcrud + current_file_name))
	    goto again_file;
	  msg_perror ("Could not create file %s",
		      skipcrud + current_file_name);
	  if (head->header.isextended)
	    skip_extended_headers ();
	  skip_file ((long) hstat.st_size);
	  goto quit;
	}

    extract_file:
      if (head->header.linkflag == LF_SPARSE)
	{
	  char *name;
	  int namelen;

	  /*
			  * Kludge alert.  NAME is assigned to header.name
			  * because during the extraction, the space that
			  * contains the header will get scribbled on, and
			  * the name will get munged, so any error messages
			  * that happen to contain the filename will look
			  * REAL interesting unless we do this.
			  */
	  namelen = strlen (skipcrud + current_file_name) + 1;
	  name = (char *) ck_malloc ((sizeof (char)) * namelen);
	  bcopy (skipcrud + current_file_name, name, namelen);
	  size = hstat.st_size;
	  extract_sparse_file (fd, &size, hstat.st_size, name);
	}
      else
	for (size = hstat.st_size;
	     size > 0;
	     size -= written)
	  {

	    /*			long	offset,
				 numbytes;*/

	    if (f_multivol)
	      {
		save_name = current_file_name;
		save_totsize = hstat.st_size;
		save_sizeleft = size;
	      }

	    /*
			  * Locate data, determine max length
			  * writeable, write it, record that
			  * we have used the data, then check
			  * if the write worked.
			  */
	    data = findrec ()->charptr;
	    if (data == NULL)
	      {			/* Check it... */
		msg ("Unexpected EOF on archive file");
		break;
	      }
	    /*
			  * JK - If the file is sparse, use the sparsearray
			  * that we created before to lseek into the new
			  * file the proper amount, and to see how many
			  * bytes we want to write at that position.
			  */
	    /*			if (head->header.linkflag == LF_SPARSE) {
				 off_t pos;

				 pos = lseek(fd, (off_t) sparsearray[sparse_ind].offset, 0);
				 printf("%d at %d\n", (int) pos, sparse_ind);
				 written = sparsearray[sparse_ind++].numbytes;
			 } else*/
	    written = endofrecs ()->charptr - data;
	    if (written > size)
	      written = size;
	    errno = 0;
	    check = write (fd, data, written);
	    /*
			  * The following is in violation of strict
			  * typing, since the arg to userec
			  * should be a struct rec *.  FIXME.
			  */
	    userec ((union record *) (data + written - 1));
	    if (check == written)
	      continue;
	    /*
			  * Error in writing to file.
			  * Print it, skip to next file in archive.
			  */
	    if (check < 0)
	      msg_perror ("couldn't write to file %s",
			  skipcrud + current_file_name);
	    else
	      msg ("could only write %d of %d bytes to file %s",
		   check, written, skipcrud + current_file_name);
	    skip_file ((long) (size - written));
	    break;		/* Still do the close, mod time, chmod, etc */
	  }

      if (f_multivol)
	save_name = 0;

      /* If writing to stdout, don't try to do anything
			    to the filename; it doesn't exist, or we don't
			    want to touch it anyway */
      if (f_exstdout)
	break;

      /*		if (head->header.isextended) {
			 register union record *exhdr;
			 register int i;

			 for (i = 0; i < 21; i++) {
				 long offset;

				 if (!exhdr->ext_hdr.sp[i].numbytes)
					 break;
				 offset = from_oct(1+12,
						 exhdr->ext_hdr.sp[i].offset);
				 written = from_oct(1+12,
						 exhdr->ext_hdr.sp[i].numbytes);
				 lseek(fd, offset, 0);
				 check = write(fd, data, written);
				 if (check == written) continue;

			 }


		 }*/
      check = close (fd);
      if (check < 0)
	{
	  msg_perror ("Error while closing %s",
		      skipcrud + current_file_name);
	}


    set_filestat:

      /*
		  * If we are root, set the owner and group of the extracted
		  * file.  This does what is wanted both on real Unix and on
		  * System V.  If we are running as a user, we extract as that
		  * user; if running as root, we extract as the original owner.
		  */
      if (we_are_root || f_do_chown)
	{
	  if (chown (skipcrud + current_file_name,
		     hstat.st_uid, hstat.st_gid) < 0)
	    {
	      msg_perror ("cannot chown file %s to uid %d gid %d",
			  skipcrud + current_file_name,
			  hstat.st_uid, hstat.st_gid);
	    }
	}

      /*
       * Set the modified time of the file.
       *
       * Note that we set the accessed time to "now", which
       * is really "the time we started extracting files".
       * unless f_gnudump is used, in which case .st_atime is used
       */
      if (!f_modified)
	{
	  /* fixme if f_gnudump should set ctime too, but how? */
	  if (f_gnudump)
	    acc_upd_times.actime = hstat.st_atime;
	  else
	    acc_upd_times.actime = now;	/* Accessed now */
	  acc_upd_times.modtime = hstat.st_mtime;	/* Mod'd */
	  if (utime (skipcrud + current_file_name,
		     &acc_upd_times) < 0)
	    {
	      msg_perror ("couldn't change access and modification times of %s", skipcrud + current_file_name);
	    }
	}
      /* We do the utime before the chmod because some versions of
		   utime are broken and trash the modes of the file.  Since
		   we then change the mode anyway, we don't care. . . */

      /*
		 * If '-k' is not set, open() or creat() could have saved
		 * the permission bits from a previously created file,
		 * ignoring the ones we specified.
		 * Even if -k is set, if the file has abnormal
		 * mode bits, we must chmod since writing or chown() has
		 * probably reset them.
		 *
		 * If -k is set, we know *we* created this file, so the mode
		 * bits were set by our open().   If the file is "normal", we
		 * skip the chmod.  This works because we did umask(0) if -p
		 * is set, so umask will have left the specified mode alone.
		 */
      if ((!f_keep)
	  || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
	{
	  if (chmod (skipcrud + current_file_name,
		     notumask & (int) hstat.st_mode) < 0)
	    {
	      msg_perror ("cannot change mode of file %s to 0%o",
			  skipcrud + current_file_name,
			  notumask & (int) hstat.st_mode);
	    }
	}

    quit:
      break;

    case LF_LINK:
    again_link:
      {
	struct stat st1, st2;

        if (f_unlink && !f_keep) {
	  if (unlink(skipcrud + current_file_name) == -1)
		if (errno != ENOENT)
		   msg_perror ("Could not unlink %s",
                      skipcrud + current_file_name);
        }

	check = link (current_link_name, skipcrud + current_file_name);

	if (check == 0)
	  break;
	if (make_dirs (skipcrud + current_file_name))
	  goto again_link;
	if (f_gnudump && errno == EEXIST)
	  break;
	if (stat (current_link_name, &st1) == 0
	    && stat (current_file_name + skipcrud, &st2) == 0
	    && st1.st_dev == st2.st_dev
	    && st1.st_ino == st2.st_ino)
	  break;
	msg_perror ("Could not link %s to %s",
		    skipcrud + current_file_name,
		    current_link_name);
      }
      break;

#ifdef S_ISLNK
    case LF_SYMLINK:
    again_symlink:
      if (f_unlink && !f_keep) {
	  if (unlink(skipcrud + current_file_name) == -1)
		if (errno != ENOENT)
		   msg_perror ("Could not unlink %s",
                      skipcrud + current_file_name);
      }

      check = symlink (current_link_name,
		       skipcrud + current_file_name);
      /* FIXME, don't worry uid, gid, etc... */
      if (check == 0)
	break;
      if (make_dirs (current_file_name + skipcrud))
	goto again_symlink;
      msg_perror ("Could not create symlink to %s",
		  current_link_name);
      break;
#endif

#ifdef S_IFCHR
    case LF_CHR:
      hstat.st_mode |= S_IFCHR;
      goto make_node;
#endif

#ifdef S_IFBLK
    case LF_BLK:
      hstat.st_mode |= S_IFBLK;
#endif
#if defined(S_IFCHR) || defined(S_IFBLK)
    make_node:
      if (f_unlink && !f_keep) {
	  if (unlink(skipcrud + current_file_name) == -1)
		if (errno != ENOENT)
		   msg_perror ("Could not unlink %s",
                      skipcrud + current_file_name);
      }

      check = mknod (current_file_name + skipcrud,
		     (int) hstat.st_mode, (int) hstat.st_rdev);
      if (check != 0)
	{
	  if (make_dirs (skipcrud + current_file_name))
	    goto make_node;
	  msg_perror ("Could not make %s",
		      current_file_name + skipcrud);
	  break;
	};
      goto set_filestat;
#endif

#ifdef S_ISFIFO
      /* If local system doesn't support FIFOs, use default case */
    case LF_FIFO:
    make_fifo:
      if (f_unlink && !f_keep) {
	  if (unlink(skipcrud + current_file_name) == -1)
		if (errno != ENOENT)
		   msg_perror ("Could not unlink %s",
                      skipcrud + current_file_name);
      }

      check = mkfifo (current_file_name + skipcrud,
		      (int) hstat.st_mode);
      if (check != 0)
	{
	  if (make_dirs (current_file_name + skipcrud))
	    goto make_fifo;
	  msg_perror ("Could not make %s",
		      skipcrud + current_file_name);
	  break;
	};
      goto set_filestat;
#endif

    case LF_DIR:
    case LF_DUMPDIR:
      namelen = strlen (current_file_name + skipcrud) - 1;
    really_dir:
      /* Check for trailing /, and zap as many as we find. */
      while (namelen
	     && current_file_name[skipcrud + namelen] == '/')
	current_file_name[skipcrud + namelen--] = '\0';
      if (f_gnudump)
	{			/* Read the entry and delete files
					   that aren't listed in the archive */
	  gnu_restore (skipcrud);

	}
      else if (head->header.linkflag == LF_DUMPDIR)
	skip_file ((long) (hstat.st_size));


    again_dir:
      check = mkdir (skipcrud + current_file_name,
		     (we_are_root ? 0 : 0300) | (int) hstat.st_mode);
      if (check != 0)
	{
	  struct stat st1;

	  if (make_dirs (skipcrud + current_file_name))
	    goto again_dir;
	  /* If we're trying to create '.', let it be. */
	  if (current_file_name[skipcrud + namelen] == '.' &&
	      (namelen == 0 ||
	       current_file_name[skipcrud + namelen - 1] == '/'))
	    goto check_perms;
	  if (errno == EEXIST
	      && stat (skipcrud + current_file_name, &st1) == 0
	      && (S_ISDIR (st1.st_mode)))
	    break;
	  msg_perror ("Could not create directory %s", skipcrud + current_file_name);
	  break;
	}

    check_perms:
      if (!we_are_root && 0300 != (0300 & (int) hstat.st_mode))
	{
	  hstat.st_mode |= 0300;
	  msg ("Added write and execute permission to directory %s",
	       skipcrud + current_file_name);
	}

      /*
       * If we are root, set the owner and group of the extracted
       * file.  This does what is wanted both on real Unix and on
       * System V.  If we are running as a user, we extract as that
       * user; if running as root, we extract as the original owner.
       */
      if (we_are_root || f_do_chown)
	{
	  if (chown (skipcrud + current_file_name,
		     hstat.st_uid, hstat.st_gid) < 0)
	    {
	      msg_perror ("cannot chown file %s to uid %d gid %d",
			  skipcrud + current_file_name,
			  hstat.st_uid, hstat.st_gid);
	    }
	}

      if (!f_modified)
	{
	  tmp = ((struct saved_dir_info *)
		 ck_malloc (sizeof (struct saved_dir_info)));
	  tmp->path = (char *) ck_malloc (strlen (skipcrud
						  + current_file_name) + 1);
	  strcpy (tmp->path, skipcrud + current_file_name);
	  tmp->mode = hstat.st_mode;
	  tmp->atime = hstat.st_atime;
	  tmp->mtime = hstat.st_mtime;
	  tmp->next = saved_dir_info_head;
	  saved_dir_info_head = tmp;
	}
      else
	{
	  /* This functions exactly as the code for set_filestat above. */
	  if ((!f_keep)
	      || (hstat.st_mode & (S_ISUID | S_ISGID | S_ISVTX)))
	    {
	      if (chmod (skipcrud + current_file_name,
			 notumask & (int) hstat.st_mode) < 0)
		{
		  msg_perror ("cannot change mode of file %s to 0%o",
			      skipcrud + current_file_name,
			      notumask & (int) hstat.st_mode);
		}
	    }
	}
      break;

    case LF_VOLHDR:
      if (f_verbose)
	{
	  printf ("Reading %s\n", current_file_name);
	}
      break;

    case LF_NAMES:
      extract_mangle (head);
      break;

    case LF_MULTIVOL:
      msg ("Can't extract '%s'--file is continued from another volume\n", current_file_name);
      skip_file ((long) hstat.st_size);
      break;

    case LF_LONGNAME:
    case LF_LONGLINK:
      msg ("Visible long name error\n");
      skip_file ((long) hstat.st_size);
      break;
    }

  /* We don't need to save it any longer. */
  saverec ((union record **) 0);/* Unsave it */
}
Пример #11
0
/*
/////////////////////////////////////////////////////////////////////////
// actually run the installation, copying files to and fro
*/
static Pk11Install_Error
DoInstall(JAR *jar, const char *installDir, const char *tempDir,
          Pk11Install_Platform *platform, PRFileDesc *feedback, PRBool noverify)
{
    Pk11Install_File *file;
    Pk11Install_Error ret;
    char *reldir;
    char *dest;
    char *modDest;
    char *cp;
    int i;
    int status;
    char *tempname, *temp;
    StringList executables;
    StringNode *execNode;
    PRProcessAttr *attr;
    PRProcess *proc;
    char *argv[2];
    char *envp[1];
    int errcode;

    ret = PK11_INSTALL_UNSPECIFIED;
    reldir = NULL;
    dest = NULL;
    modDest = NULL;
    tempname = NULL;

    StringList_new(&executables);
    /*
    // Create Temporary directory
    */
    tempname = PR_smprintf("%s/%s", tempDir, TEMPORARY_DIRECTORY_NAME);
    if (PR_Access(tempname, PR_ACCESS_EXISTS) == PR_SUCCESS) {
        /* Left over from previous run?  Delete it. */
        rm_dash_r(tempname);
    }
    if (PR_MkDir(tempname, 0700) != PR_SUCCESS) {
        error(PK11_INSTALL_CREATE_DIR, tempname);
        ret = PK11_INSTALL_CREATE_DIR;
        goto loser;
    }

    /*
    // Install all the files
    */
    for (i = 0; i < platform->numFiles; i++) {
        file = &platform->files[i];

        if (file->relativePath) {
            PRBool foundMarker = PR_FALSE;
            reldir = PR_Strdup(file->relativePath);

            /* Replace all the markers with the directories for which they stand */
            while (1) {
                if ((cp = PL_strcasestr(reldir, ROOT_MARKER))) {
                    /* Has a %root% marker  */
                    *cp = '\0';
                    temp = PR_smprintf("%s%s%s", reldir, installDir,
                                       cp + strlen(ROOT_MARKER));
                    PR_Free(reldir);
                    reldir = temp;
                    foundMarker = PR_TRUE;
                } else if ((cp = PL_strcasestr(reldir, TEMP_MARKER))) {
                    /* Has a %temp% marker */
                    *cp = '\0';
                    temp = PR_smprintf("%s%s%s", reldir, tempname,
                                       cp + strlen(TEMP_MARKER));
                    PR_Free(reldir);
                    reldir = temp;
                    foundMarker = PR_TRUE;
                } else {
                    break;
                }
            }
            if (!foundMarker) {
                /* Has no markers...this isn't really a relative directory */
                error(PK11_INSTALL_BOGUS_REL_DIR, file->relativePath);
                ret = PK11_INSTALL_BOGUS_REL_DIR;
                goto loser;
            }
            dest = reldir;
            reldir = NULL;
        } else if (file->absolutePath) {
            dest = PR_Strdup(file->absolutePath);
        }

        /* Remember if this is the module file, we'll need to add it later */
        if (i == platform->modFile) {
            modDest = PR_Strdup(dest);
        }

        /* Remember is this is an executable, we'll need to run it later */
        if (file->executable) {
            StringList_Append(&executables, dest);
            /*executables.Append(dest);*/
        }

        /* Make sure the directory we are targetting exists */
        if (make_dirs(dest, file->permissions)) {
            ret = PK11_INSTALL_CREATE_DIR;
            goto loser;
        }

        /* Actually extract the file onto the filesystem */
        if (noverify) {
            status = JAR_extract(jar, (char *)file->jarPath, dest);
        } else {
            status = JAR_verified_extract(jar, (char *)file->jarPath, dest);
        }
        if (status) {
            if (status >= JAR_BASE && status <= JAR_BASE_END) {
                error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
                      JAR_get_error(status));
            } else {
                error(PK11_INSTALL_JAR_EXTRACT, file->jarPath,
                      mySECU_ErrorString(PORT_GetError()));
            }
            ret = PK11_INSTALL_JAR_EXTRACT;
            goto loser;
        }
        if (feedback) {
            PR_fprintf(feedback, msgStrings[INSTALLED_FILE_MSG],
                       file->jarPath, dest);
        }

/* no NSPR command to change permissions? */
#ifdef XP_UNIX
        chmod(dest, file->permissions);
#endif

        /* Memory clean-up tasks */
        if (reldir) {
            PR_Free(reldir);
            reldir = NULL;
        }
        if (dest) {
            PR_Free(dest);
            dest = NULL;
        }
    }
    /* Make sure we found the module file */
    if (!modDest) {
        /* Internal problem here, since every platform is supposed to have
           a module file */
        error(PK11_INSTALL_NO_MOD_FILE, platform->moduleName);
        ret = PK11_INSTALL_NO_MOD_FILE;
        goto loser;
    }

    /*
    // Execute any executable files
    */
    {
        argv[1] = NULL;
        envp[0] = NULL;
        for (execNode = executables.head; execNode; execNode = execNode->next) {
            attr = PR_NewProcessAttr();
            argv[0] = PR_Strdup(execNode->str);

            /* Announce our intentions */
            if (feedback) {
                PR_fprintf(feedback, msgStrings[EXEC_FILE_MSG], execNode->str);
            }

            /* start the process */
            if (!(proc = PR_CreateProcess(execNode->str, argv, envp, attr))) {
                PR_Free(argv[0]);
                PR_DestroyProcessAttr(attr);
                error(PK11_INSTALL_EXEC_FILE, execNode->str);
                ret = PK11_INSTALL_EXEC_FILE;
                goto loser;
            }

            /* wait for it to finish */
            if (PR_WaitProcess(proc, &errcode) != PR_SUCCESS) {
                PR_Free(argv[0]);
                PR_DestroyProcessAttr(attr);
                error(PK11_INSTALL_WAIT_PROCESS, execNode->str);
                ret = PK11_INSTALL_WAIT_PROCESS;
                goto loser;
            }

            /* What happened? */
            if (errcode) {
                /* process returned an error */
                error(PK11_INSTALL_PROC_ERROR, execNode->str, errcode);
            } else if (feedback) {
                /* process ran successfully */
                PR_fprintf(feedback, msgStrings[EXEC_SUCCESS], execNode->str);
            }

            PR_Free(argv[0]);
            PR_DestroyProcessAttr(attr);
        }
    }

    /*
    // Add the module
    */
    status = Pk11Install_AddNewModule((char *)platform->moduleName,
                                      (char *)modDest, platform->mechFlags, platform->cipherFlags);

    if (status != SECSuccess) {
        error(PK11_INSTALL_ADD_MODULE, platform->moduleName);
        ret = PK11_INSTALL_ADD_MODULE;
        goto loser;
    }
    if (feedback) {
        PR_fprintf(feedback, msgStrings[INSTALLED_MODULE_MSG],
                   platform->moduleName);
    }

    if (feedback) {
        PR_fprintf(feedback, msgStrings[INSTALLATION_COMPLETE_MSG]);
    }

    ret = PK11_INSTALL_SUCCESS;

loser:
    if (reldir) {
        PR_Free(reldir);
    }
    if (dest) {
        PR_Free(dest);
    }
    if (modDest) {
        PR_Free(modDest);
    }
    if (tempname) {
        PRFileInfo info;
        if (PR_GetFileInfo(tempname, &info) == PR_SUCCESS) {
            if (info.type == PR_FILE_DIRECTORY) {
                /* Recursively remove temporary directory */
                if (rm_dash_r(tempname)) {
                    error(PK11_INSTALL_REMOVE_DIR,
                          tempname);
                    ret = PK11_INSTALL_REMOVE_DIR;
                }
            }
        }
        PR_Free(tempname);
    }
    StringList_delete(&executables);
    return ret;
}
Пример #12
0
void FilesystemTest::testDirectory() {
#ifdef _WIN32
	const string test_subdir = test_dir->Path() + "\\a";
	const string test_subsubdir = test_subdir + "\\b";
	const string test_file = test_subsubdir + "\\c.txt";
#else
	const string test_subdir = test_dir->Path() + "/a";
	const string test_subsubdir = test_subdir + "/b";
	const string test_file = test_subsubdir + "/c";
#endif

	CPPUNIT_ASSERT_MESSAGE(
		"inexistant directory is a file",
		!is_file(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"inexistant directory is a directory",
		!is_dir(test_subdir));

	CPPUNIT_ASSERT_MESSAGE(
		"failed to create test subdir",
		make_dir(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is a file",
		!is_file(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is not a directory",
		is_dir(test_subdir));

	CPPUNIT_ASSERT_MESSAGE(
		"failed to remove test subdir",
		remove_dir(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory became a file",
		!is_file(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory is still a directory",
		!is_dir(test_subdir));

	CPPUNIT_ASSERT_MESSAGE(
		"failed to create test subdirs",
		make_dirs(test_subsubdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is a file",
		!is_file(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is not a directory",
		is_dir(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is a file",
		!is_file(test_subsubdir));
	CPPUNIT_ASSERT_MESSAGE(
		"created directory is not a directory",
		is_dir(test_subsubdir));

	{ // create file
		ofstream file(test_file);
		file << "hello" << endl;
	}
	CPPUNIT_ASSERT_MESSAGE(
		"failed to create test file",
		is_file(test_file));

	CPPUNIT_ASSERT_MESSAGE(
		"failed to remove test subdir",
		remove_dir(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory became a file",
		!is_file(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory is still a directory",
		!is_dir(test_subdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory became a file",
		!is_file(test_subsubdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed directory is still a directory",
		!is_dir(test_subsubdir));
	CPPUNIT_ASSERT_MESSAGE(
		"removed file became a directory",
		!is_dir(test_file));
	CPPUNIT_ASSERT_MESSAGE(
		"removed file is still a file",
		!is_file(test_file));
}
Пример #13
0
/****************
 * Copy the option file skeleton to the given directory.  If NAME2 is
 * not NULL it is used as the destination name.
 */
static int
copy_file (const char *name, const char *name2)
{
  char *srcname, *dstname;
  FILE *srcfp, *dstfp;
  int tried_mkdir = 0;
  char buffer[4096];

  if (verbose > 1)
    {
      if (name2)
        inf ("copying '%s' as '%s'", name, name2);
      else
        inf ("copying '%s'", name);
    }

  srcname = make_sourcename (name);
  dstname = make_targetname (name2? name2:name);

  srcfp = fopen (srcname, "rb");
  if (!srcfp)
    {
      err ("failed to open '%s': %s\n", srcname, strerror (errno));
      free (srcname);
      free (dstname);
      return 1;
    }

 again:
  dstfp = fopen (dstname, "wb");
  if (!dstfp)
    {
      if (!tried_mkdir && errno == ENOENT && strchr (name, '/'))
        {
          tried_mkdir = 1;
          make_dirs (name);
          goto again;
        }

      err ("failed to create '%s': %s\n", dstname, strerror (errno));
      fclose (srcfp);
      free (srcname);
      free (dstname);
      return 1;
    }

  while (!feof (srcfp))
    {
      size_t n;

      n = fread (buffer, 1, sizeof buffer, srcfp);
      if (n < sizeof buffer && ferror (srcfp))
        {
          err ("error reading '%s'\n", srcname);
          fclose (srcfp);
          fclose (dstfp);
          free (srcname);
          free (dstname);
          return 1;
        }

      errno = 0;
      if (fwrite (buffer, 1, n, dstfp) != n)
        {
          err ("error writing to '%s': %s\n", dstname, strerror (errno));
          fclose (srcfp);
          fclose (dstfp);
          free (srcname);
          free (dstname);
          return 1;
        }
    }

  if (fflush (dstfp) == EOF)
    {
      err ("error writing to '%s': %s\n", dstname, strerror (errno));
      fclose (srcfp);
      fclose (dstfp);
      free (srcname);
      free (dstname);
      return 1;
    }
  if (fclose (dstfp) == EOF)
    {
      err ("error closing '%s': %s\n", dstname, strerror (errno));
      fclose (srcfp);
      fclose (dstfp);
      free (srcname);
      free (dstname);
      return 1;
    }

  fclose  (srcfp);

  free (srcname);
  free (dstname);
  return 0;
}
Пример #14
0
static YogVal
decompress(YogEnv* env, YogVal self, YogVal pkg, YogVal args, YogVal kw, YogVal block)
{
    SAVE_ARGS5(env, self, pkg, args, kw, block);
    YogVal zip = YUNDEF;
    YogVal dest = YNIL;
    YogVal s = YUNDEF;
    PUSH_LOCALS3(env, zip, dest, s);
    YogCArg params[] = {
        { "zip", &zip },
        { "|", NULL },
        { "dest", &dest },
        { NULL, NULL } };
    YogGetArgs_parse_args(env, "decompress", params, args, kw);
    if (!IS_PTR(zip) || (BASIC_OBJ_TYPE(zip) != TYPE_STRING)) {
        YogError_raise_TypeError(env, "zip must be String");
    }
    if (!IS_NIL(dest) && (!IS_PTR(dest) || (BASIC_OBJ_TYPE(dest) != TYPE_STRING))) {
        YogError_raise_TypeError(env, "dest must be nil or String");
    }

    struct zip* archive = open_zip(env, pkg, zip, 0);
    int n = zip_get_num_files(archive);
    YogHandle* h = VAL2HDL(env, dest);
    int i;
    for (i = 0; i < n; i++) {
        const char* name = zip_get_name(archive, i, 0);
        if (name == NULL) {
            close_zip(env, pkg, archive);
            raise_ZipError(env, pkg, zip_strerror(archive));
        }
        YogVal bin = YogString_to_bin_in_default_encoding(env, h);
        char* path = (char*)YogSysdeps_alloca(strlen(BINARY_CSTR(bin)) + strlen(name) + 2);
        strcpy(path, BINARY_CSTR(bin));
        strcat(path, "/");
        strcat(path, name);
        char* dir = (char*)YogSysdeps_alloca(strlen(path) + 1);
        strcpy(dir, path);
        dirname(dir);
        make_dirs(env, dir);

        struct zip_file* file = zip_fopen_index(archive, i, 0);
        if (file == NULL) {
            close_zip(env, pkg, archive);
            raise_ZipError(env, pkg, zip_strerror(archive));
        }
        FILE* fp = fopen(path, "wb");
        if (fp == NULL) {
            zip_fclose(file);
            close_zip(env, pkg, archive);
            s = YogString_from_string(env, path);
            YogError_raise_sys_err(env, errno, s);
        }
        while (1) {
            char buf[1024];
            int len = zip_fread(file, buf, array_sizeof(buf));
            if (len < 0) {
                zip_fclose(file);
                close_zip(env, pkg, archive);
                raise_ZipError(env, pkg, zip_strerror(archive));
            }
            else if (len == 0) {
                break;
            }
            fwrite(buf, sizeof(char), len, fp);
            if (ferror(fp)) {
                zip_fclose(file);
                close_zip(env, pkg, archive);
                YogError_raise_IOError(env, name);
            }
        }

        fclose(fp);
        if (zip_fclose(file) != 0) {
            close_zip(env, pkg, archive);
            raise_ZipError(env, pkg, zip_strerror(archive));
        }
    }
    close_zip(env, pkg, archive);

    RETURN(env, YNIL);
}
Пример #15
0
//-----------------------------------------------------------------------------
// the SD card has been inserted, do the necessary steps to get a sane system
static int
on_insert(void)
{
	FRESULT stat;

	kbs_setFName(KUROBOX_LOADING_NAME);
	if (!sdcConnect(&SDCD1))
	{
		kbs_setFName(KUROBOX_ERR1);
		return KB_NOT_OK;
	}

	stat = f_mount(&SDC_FS, "/", 1);
	if (stat != FR_OK)
	{
		kbs_setFName(KUROBOX_ERR2);
		sdcDisconnect(&SDCD1);
		return KB_NOT_OK;
	}

	chThdSleepMilliseconds(100);
	uint32_t clusters;
	FATFS * fsp = NULL;
	stat = f_getfree("/", &clusters, &fsp);
	if (stat != FR_OK)
	{
		kbs_setFName(KUROBOX_ERR3);
		sdcDisconnect(&SDCD1);
		return KB_NOT_OK;
	}
	uint64_t cardsize = clusters * (((uint32_t)fsp->csize * (uint32_t)MMCSD_BLOCK_SIZE) / 1024);
	cardsize_MB = cardsize / 1024;

	// @TODO: this can be moved to above the check for free space
	fs_write_protected = sdc_lld_is_write_protected(&SDCD1);
	if ( fs_write_protected )
	{
		// -1 means that it's write protected, display that
		kbs_setSDCFree(-1);
		kbs_setFName(KUROBOX_WP_NAME);
		return KB_NOT_OK;
	}
	kbs_setSDCFree(cardsize_MB);

	stat = make_dirs();
	if (stat != FR_OK)
	{
		kbs_setFName(KUROBOX_ERR4);
		sdcDisconnect(&SDCD1);
		return KB_NOT_OK;
	}

	stat = new_file();
	if (stat != FR_OK)
	{
		kbs_setFName(KUROBOX_ERR5);
		sdcDisconnect(&SDCD1);
		return KB_NOT_OK;
	}

	fs_ready = TRUE;
	logger_state = LS_RUNNING;

	kbs_err_setSD(1);

	return KB_OK;
}
Пример #16
0
int     deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr)
{
    const char *myname = "deliver_maildir";
    char   *newdir;
    char   *tmpdir;
    char   *curdir;
    char   *tmpfile;
    char   *newfile;
    DSN_BUF *why = state.msg_attr.why;
    VSTRING *buf;
    VSTREAM *dst;
    int     mail_copy_status;
    int     deliver_status;
    int     copy_flags;
    struct stat st;
    struct timeval starttime;

    GETTIMEOFDAY(&starttime);

    /*
     * Make verbose logging easier to understand.
     */
    state.level++;
    if (msg_verbose)
	MSG_LOG_STATE(myname, state);

    /*
     * Don't deliver trace-only requests.
     */
    if (DEL_REQ_TRACE_ONLY(state.request->flags)) {
	dsb_simple(why, "2.0.0", "delivers to maildir");
	return (sent(BOUNCE_FLAGS(state.request),
		     SENT_ATTR(state.msg_attr)));
    }

    /*
     * Initialize. Assume the operation will fail. Set the delivered
     * attribute to reflect the final recipient.
     */
    if (vstream_fseek(state.msg_attr.fp, state.msg_attr.offset, SEEK_SET) < 0)
	msg_fatal("seek message file %s: %m", VSTREAM_PATH(state.msg_attr.fp));
    state.msg_attr.delivered = state.msg_attr.rcpt.address;
    mail_copy_status = MAIL_COPY_STAT_WRITE;
    buf = vstring_alloc(100);

    copy_flags = MAIL_COPY_TOFILE | MAIL_COPY_RETURN_PATH
	| MAIL_COPY_DELIVERED | MAIL_COPY_ORIG_RCPT;

    newdir = concatenate(usr_attr.mailbox, "new/", (char *) 0);
    tmpdir = concatenate(usr_attr.mailbox, "tmp/", (char *) 0);
    curdir = concatenate(usr_attr.mailbox, "cur/", (char *) 0);

    /*
     * Create and write the file as the recipient, so that file quota work.
     * Create any missing directories on the fly. The file name is chosen
     * according to ftp://koobera.math.uic.edu/www/proto/maildir.html:
     * 
     * "A unique name has three pieces, separated by dots. On the left is the
     * result of time(). On the right is the result of gethostname(). In the
     * middle is something that doesn't repeat within one second on a single
     * host. I fork a new process for each delivery, so I just use the
     * process ID. If you're delivering several messages from one process,
     * use starttime.pid_count.host, where starttime is the time that your
     * process started, and count is the number of messages you've
     * delivered."
     * 
     * Well, that stopped working on fast machines, and on operating systems
     * that randomize process ID values. When creating a file in tmp/ we use
     * the process ID because it still is an exclusive resource. When moving
     * the file to new/ we use the device number and inode number. I do not
     * care if this breaks on a remote AFS file system, because people should
     * know better.
     * 
     * On January 26, 2003, http://cr.yp.to/proto/maildir.html said:
     * 
     * A unique name has three pieces, separated by dots. On the left is the
     * result of time() or the second counter from gettimeofday(). On the
     * right is the result of gethostname(). (To deal with invalid host
     * names, replace / with \057 and : with \072.) In the middle is a
     * delivery identifier, discussed below.
     * 
     * [...]
     * 
     * Modern delivery identifiers are created by concatenating enough of the
     * following strings to guarantee uniqueness:
     * 
     * [...]
     * 
     * In, where n is (in hexadecimal) the UNIX inode number of this file.
     * Unfortunately, inode numbers aren't always available through NFS.
     * 
     * Vn, where n is (in hexadecimal) the UNIX device number of this file.
     * Unfortunately, device numbers aren't always available through NFS.
     * (Device numbers are also not helpful with the standard UNIX
     * filesystem: a maildir has to be within a single UNIX device for link()
     * and rename() to work.)
     * 
     * Mn, where n is (in decimal) the microsecond counter from the same
     * gettimeofday() used for the left part of the unique name.
     * 
     * Pn, where n is (in decimal) the process ID.
     * 
     * [...]
     */
    set_eugid(usr_attr.uid, usr_attr.gid);
    vstring_sprintf(buf, "%lu.P%d.%s",
		 (unsigned long) starttime.tv_sec, var_pid, get_hostname());
    tmpfile = concatenate(tmpdir, STR(buf), (char *) 0);
    newfile = 0;
    if ((dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0
	&& (errno != ENOENT
	    || make_dirs(tmpdir, 0700) < 0
	    || (dst = vstream_fopen(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0600)) == 0)) {
	dsb_simple(why, mbox_dsn(errno, "4.2.0"),
		   "create maildir file %s: %m", tmpfile);
    } else if (fstat(vstream_fileno(dst), &st) < 0) {

	/*
	 * Coverity 200604: file descriptor leak in code that never executes.
	 * Code replaced by msg_fatal(), as it is not worthwhile to continue
	 * after an impossible error condition.
	 */
	msg_fatal("fstat %s: %m", tmpfile);
    } else {
	vstring_sprintf(buf, "%lu.V%lxI%lxM%lu.%s",
			(unsigned long) starttime.tv_sec,
			(unsigned long) st.st_dev,
			(unsigned long) st.st_ino,
			(unsigned long) starttime.tv_usec,
			get_hostname());
	newfile = concatenate(newdir, STR(buf), (char *) 0);
	if ((mail_copy_status = mail_copy(COPY_ATTR(state.msg_attr),
					  dst, copy_flags, "\n",
					  why)) == 0) {
	    if (sane_link(tmpfile, newfile) < 0
		&& (errno != ENOENT
		    || (make_dirs(curdir, 0700), make_dirs(newdir, 0700)) < 0
		    || sane_link(tmpfile, newfile) < 0)) {
		dsb_simple(why, mbox_dsn(errno, "4.2.0"),
			   "create maildir file %s: %m", newfile);
		mail_copy_status = MAIL_COPY_STAT_WRITE;
	    }
	}
	if (unlink(tmpfile) < 0)
	    msg_warn("remove %s: %m", tmpfile);
    }
    set_eugid(var_owner_uid, var_owner_gid);

    /*
     * The maildir location is controlled by the mail administrator. If
     * delivery fails, try again later. We would just bounce when the maildir
     * location possibly under user control.
     */
    if (mail_copy_status & MAIL_COPY_STAT_CORRUPT) {
	deliver_status = DEL_STAT_DEFER;
    } else if (mail_copy_status != 0) {
	if (errno == EACCES) {
	    msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
		     (long) usr_attr.uid, (long) usr_attr.gid,
		     STR(why->reason));
	    msg_warn("perhaps you need to create the maildirs in advance");
	}
	vstring_sprintf_prepend(why->reason, "maildir delivery failed: ");
	deliver_status =
	    (STR(why->status)[0] == '4' ?
	     defer_append : bounce_append)
	    (BOUNCE_FLAGS(state.request),
	     BOUNCE_ATTR(state.msg_attr));
    } else {
	dsb_simple(why, "2.0.0", "delivered to maildir");
	deliver_status = sent(BOUNCE_FLAGS(state.request),
			      SENT_ATTR(state.msg_attr));
    }
    vstring_free(buf);
    myfree(newdir);
    myfree(tmpdir);
    myfree(curdir);
    myfree(tmpfile);
    if (newfile)
	myfree(newfile);
    return (deliver_status);
}