Пример #1
0
int safe_rename (const char *src, const char *target)
{
  struct stat ssb, tsb;

  if (!src || !target)
    return -1;

  if (link (src, target) != 0) {

    /*
     * Coda does not allow cross-directory links, but tells
     * us it's a cross-filesystem linking attempt.
     * 
     * However, the Coda rename call is allegedly safe to use.
     * 
     * With other file systems, rename should just fail when 
     * the files reside on different file systems, so it's safe
     * to try it here.
     *
     */

    if (errno == EXDEV)
      return rename (src, target);

    return -1;
  }

  /*
   * Stat both links and check if they are equal.
   */

  if (stat (src, &ssb) == -1) {
    return -1;
  }

  if (stat (target, &tsb) == -1) {
    return -1;
  }

  /* 
   * pretend that the link failed because the target file
   * did already exist.
   */

  if (compare_stat (&ssb, &tsb) == -1) {
    errno = EEXIST;
    return -1;
  }

  /*
   * Unlink the original link.  Should we really ignore the return
   * value here? XXX
   */

  unlink (src);

  return 0;
}
Пример #2
0
int io_open (const char *path, int flags, int u) {
  struct stat osb, nsb;
  int fd;

  if (u > 0)
    umask (u);
  if ((fd = open (path, flags, 0666)) < 0)
    return fd;

  /* make sure the file is not symlink */
  if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
      compare_stat (&osb, &nsb) == -1) {
    close (fd);
    return (-1);
  }

  return (fd);
}
Пример #3
0
int safe_open (const char *path, int flags)
{
  struct stat osb, nsb;
  int fd;

#if defined(__linux__)
  if ((fd = opennfs (path, flags, 0600)) < 0)
    return fd;
#else
  if (flags & O_EXCL) 
  {
    char safe_file[_POSIX_PATH_MAX];
    char safe_dir[_POSIX_PATH_MAX];

    if (mutt_mkwrapdir (path, safe_file, sizeof (safe_file),
			safe_dir, sizeof (safe_dir)) == -1)
      return -1;
    
    if ((fd = open (safe_file, flags, 0600)) < 0)
    {
      rmdir (safe_dir);
      return fd;
    }

    /* NFS and I believe cygwin do not handle movement of open files well */
    close (fd);
    if (mutt_put_file_in_place (path, safe_file, safe_dir) == -1)
      return -1;
  }

  if ((fd = open (path, flags & ~O_EXCL, 0600)) < 0)
    return fd;
#endif
  /* make sure the file is not symlink */
  if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
      compare_stat(&osb, &nsb) == -1)
  {
/*    dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */
    close (fd);
    return (-1);
  }

  return (fd);
}
Пример #4
0
int safe_open (const char *path, int flags)
{
  struct stat osb, nsb;
  int fd;

  umask (Umask);
  if ((fd = open (path, flags, 0666)) < 0)
    return fd;

  /* make sure the file is not symlink */
  if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
      compare_stat (&osb, &nsb) == -1) {
    debug_print (1, ("%s is a symlink!\n", path));
    close (fd);
    return (-1);
  }

  return (fd);
}
Пример #5
0
int safe_open (const char *path, int flags)
{
  struct stat osb, nsb;
  int fd;

  if ((fd = open (path, flags, 0600)) < 0)
    return fd;

  /* make sure the file is not symlink */
  if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 ||
      compare_stat(&osb, &nsb) == -1)
  {
/*    dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); */
    close (fd);
    return (-1);
  }

  return (fd);
}
Пример #6
0
int safe_symlink(const char *oldpath, const char *newpath)
{
  struct stat osb, nsb;

  if(!oldpath || !newpath)
    return -1;
  
  if(unlink(newpath) == -1 && errno != ENOENT)
    return -1;
  
  if (oldpath[0] == '/')
  {
    if (symlink (oldpath, newpath) == -1)
      return -1;
  }
  else
  {
    char abs_oldpath[_POSIX_PATH_MAX];

    if ((getcwd (abs_oldpath, sizeof abs_oldpath) == NULL) ||
	(strlen (abs_oldpath) + 1 + strlen (oldpath) + 1 > sizeof abs_oldpath))
    return -1;
  
    strcat (abs_oldpath, "/");		/* __STRCAT_CHECKED__ */
    strcat (abs_oldpath, oldpath);	/* __STRCAT_CHECKED__ */
    if (symlink (abs_oldpath, newpath) == -1)
      return -1;
  }

  if(stat(oldpath, &osb) == -1 || stat(newpath, &nsb) == -1
     || compare_stat(&osb, &nsb) == -1)
  {
    unlink(newpath);
    return -1;
  }
  
  return 0;
}
Пример #7
0
int safe_rename (const char *src, const char *target)
{
  struct stat ssb, tsb;

  if (!src || !target)
    return -1;

  if (link (src, target) != 0)
  {

    /*
     * Coda does not allow cross-directory links, but tells
     * us it's a cross-filesystem linking attempt.
     * 
     * However, the Coda rename call is allegedly safe to use.
     * 
     * With other file systems, rename should just fail when 
     * the files reside on different file systems, so it's safe
     * to try it here.
     *
     */
    
    dprint (1, (debugfile, "safe_rename: link (%s, %s) failed: %s (%d)\n", src, target, strerror (errno), errno));

    /*
     * FUSE may return ENOSYS. VFAT may return EPERM. FreeBSD's
     * msdosfs may return EOPNOTSUPP.  ENOTSUP can also appear.
     */
    if (errno == EXDEV || errno == ENOSYS || errno == EPERM
#ifdef ENOTSUP
	|| errno == ENOTSUP
#endif
#ifdef EOPNOTSUPP
	|| errno == EOPNOTSUPP
#endif
	)
    {
      dprint (1, (debugfile, "safe_rename: trying rename...\n"));
      if (rename (src, target) == -1) 
      {
	dprint (1, (debugfile, "safe_rename: rename (%s, %s) failed: %s (%d)\n", src, target, strerror (errno), errno));
	return -1;
      }
      dprint (1, (debugfile, "safe_rename: rename succeeded.\n"));
    
      return 0;
    }

    return -1;
  }

  /*
   * Stat both links and check if they are equal.
   */
  
  if (lstat (src, &ssb) == -1)
  {
    dprint (1, (debugfile, "safe_rename: can't stat %s: %s (%d)\n",
		src, strerror (errno), errno));
    return -1;
  }
  
  if (lstat (target, &tsb) == -1)
  {
    dprint (1, (debugfile, "safe_rename: can't stat %s: %s (%d)\n",
		src, strerror (errno), errno));
    return -1;
  }

  /* 
   * pretend that the link failed because the target file
   * did already exist.
   */

  if (compare_stat (&ssb, &tsb) == -1)
  {
    dprint (1, (debugfile, "safe_rename: stat blocks for %s and %s diverge; pretending EEXIST.\n", src, target));
    errno = EEXIST;
    return -1;
  }

  /*
   * Unlink the original link.  Should we really ignore the return
   * value here? XXX
   */

  if (unlink (src) == -1) 
  {
    dprint (1, (debugfile, "safe_rename: unlink (%s) failed: %s (%d)\n",
		src, strerror (errno), errno));
  }
  

  return 0;
}