Exemple #1
0
int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)
{
  int (*libc_fchmodat)(int dirfd, const char *pathname, mode_t mode, int flags);
  *(void **)(&libc_fchmodat) = dlsym(RTLD_NEXT, "fchmodat");
  if(dlerror()) {
    errno = EPERM;
    return -1;
  }
  return (*libc_fchmodat)(dirfd, pathname, fix_mode(mode), flags);
}
Exemple #2
0
int fchmod(int fd, mode_t mode)
{
  int (*libc_fchmod)(int fd, mode_t mode);
  *(void **)(&libc_fchmod) = dlsym(RTLD_NEXT, "fchmod");
  if(dlerror()) {
    errno = EPERM;
    return -1;
  }
  return (*libc_fchmod)(fd, fix_mode(mode));
}
Exemple #3
0
int chmod(const char *path, mode_t mode)
{
  int (*libc_chmod)(const char *path, mode_t mode);
  *(void **)(&libc_chmod) = dlsym(RTLD_NEXT, "chmod");
  if(dlerror()) {
    errno = EPERM;
    return -1;
  }
  return (*libc_chmod)(path, fix_mode(mode));
}
static int sdcardfs_setattr(struct dentry *dentry, struct iattr *ia)
{
	int err = 0;
	struct dentry *lower_dentry;
	struct inode *inode;
	struct inode *lower_inode;
	struct path lower_path;
	struct iattr lower_ia;

	inode = dentry->d_inode;

	/*
	 * Check if user has permission to change inode.  We don't check if
	 * this user can change the lower inode: that should happen when
	 * calling notify_change on the lower inode.
	 */
	err = inode_change_ok(inode, ia);
	if (err)
		goto out_err;

	sdcardfs_get_lower_path(dentry, &lower_path);
	lower_dentry = lower_path.dentry;
	lower_inode = sdcardfs_lower_inode(inode);


	/* fix warpfs file owner and permission. cannot change them. */ 
	ia->ia_uid = AID_ROOT; 
	ia->ia_gid = AID_SDCARD_RW; 
	fix_mode(ia->ia_mode); 

	/* prepare our own lower struct iattr (with the lower file) */
	memcpy(&lower_ia, ia, sizeof(lower_ia));
	if (ia->ia_valid & ATTR_FILE)
		lower_ia.ia_file = sdcardfs_lower_file(ia->ia_file);

	lower_ia.ia_uid = AID_MEDIA_RW;
	lower_ia.ia_gid = AID_MEDIA_RW;
	fix_mode(lower_ia.ia_mode); 

	/*
	 * If shrinking, first truncate upper level to cancel writing dirty
	 * pages beyond the new eof; and also if its' maxbytes is more
	 * limiting (fail with -EFBIG before making any change to the lower
	 * level).  There is no need to vmtruncate the upper level
	 * afterwards in the other cases: we fsstack_copy_inode_size from
	 * the lower level.
	 */
	if (ia->ia_valid & ATTR_SIZE) {
		err = inode_newsize_ok(inode, ia->ia_size);
		if (err)
			goto out;
		truncate_setsize(inode, ia->ia_size);
	}

	/* for FAT emulation */
	/*
	 * mode change is for clearing setuid/setgid bits. Allow lower fs
	 * to interpret this in its own way.
	 */
	if (lower_ia.ia_valid & (ATTR_KILL_SUID | ATTR_KILL_SGID))
		lower_ia.ia_valid &= ~ATTR_MODE;

	/* notify the (possibly copied-up) lower inode */
	/*
	 * Note: we use lower_dentry->d_inode, because lower_inode may be
	 * unlinked (no inode->i_sb and i_ino==0.  This happens if someone
	 * tries to open(), unlink(), then ftruncate() a file.
	 */
	mutex_lock(&lower_dentry->d_inode->i_mutex);
	err = notify_change(lower_dentry, &lower_ia); /* note: lower_ia */
	mutex_unlock(&lower_dentry->d_inode->i_mutex);
	if (err)
		goto out;

	/* get attributes from the lower inode */
	fsstack_copy_attr_all(inode, lower_inode);
	fix_fat_permission(inode); 
	
	/*
	 * Not running fsstack_copy_inode_size(inode, lower_inode), because
	 * VFS should update our inode size, and notify_change on
	 * lower_inode should update its size.
	 */

out:
	sdcardfs_put_lower_path(dentry, &lower_path);
out_err:
	return err;
}
static void
clone (char* s_path, char* d_path, int sroot_flag, int level)
{
  struct stat src_stat_buf;
  struct stat dst_stat_buf;
  int dir_already_exists = 0;
  const char* intype = "file";

  if (lstat (s_path, &src_stat_buf) == -1)
    {
      if (!quiet_flag)
	{
          fprintf (stderr, "%s: error: can't get status of %s: %s\n",
	    pname, s_path, sys_errlist[errno]);
          fprintf (stderr, "%s: input entity %s will be ignored\n",
	    pname, s_path);
	}
      return;
    }
  if (sccs_flag && sroot_flag && S_ISLNK (src_stat_buf.st_mode))
    {

      /* If root of the source path is a symbolic link and
	 SCCS cloning is enabled, clone the target of the link */

      if (stat(s_path, &src_stat_buf) == -1)
	{
          if (!quiet_flag)
	    {
              fprintf (stderr, "%s: error: can't get status of %s: %s\n",
	        pname, s_path, sys_errlist[errno]);
              fprintf (stderr, "%s: input entity %s will be ignored\n",
	        pname, s_path);
            }	
          return;
	}
    }
  if (IS_DIR (src_stat_buf))
    intype = "directory";
  if (access (d_path, 0))
    {
      if (errno != ENOENT)
	{
	  if (!quiet_flag)
	    {
	      fprintf (stderr, "%s: error: can't check accessability of %s: %s\n",
	        pname, d_path, sys_errlist[errno]);
	      fprintf (stderr, "%s: input %s %s will be ignored\n",
	        pname, intype, s_path);
	    }
	  return;
	}
    }
  else
    {
      const char* outtype = "file";

      if (lstat (d_path, &dst_stat_buf) == -1)
	{
	  if (!quiet_flag)
	    {
	      fprintf (stderr, "%s: error: unable to get status of %s: %s\n"
,
	        pname, d_path, sys_errlist[errno]);
              fprintf (stderr, "%s: input %s %s will be ignored\n",
	        pname, intype, s_path);
	    }
	  return;
	}
      if (IS_DIR (dst_stat_buf))
	outtype = "directory";
      if (IS_DIR (src_stat_buf) && IS_DIR (dst_stat_buf))
	{
	  dir_already_exists = -1;

	  /* Have to make sure that we have full access to the output
	     directory (at least temporarily).  */

	  chmod (d_path, (dst_stat_buf.st_mode & 07777) | 0700);
	  if (access (d_path, R_OK | W_OK | X_OK) != 0)
	    {
	      if (!quiet_flag)
		{
	          fprintf (stderr, 
                    "%s: error: too few permissions for existing directory %s\n",
	            pname, d_path);
		  fprintf (stderr, "%s: input directory %s will be ignored\n",
	            pname, s_path);
		}
              return;
	    }
	}
      else
	{
          if (force_flag)
	    {
              if (remove_item (s_path, d_path))
	        return;
	    }
          else
	    {
	      if (!quiet_flag)
		{
	          fprintf (stderr, "%s: error: output %s already exists: %s\n",
	            pname, outtype, d_path);
	          fprintf (stderr, "%s: input %s %s will be ignored\n",
	            pname, intype, s_path);
		}
              return;
	    }
	}
    }

  switch (src_stat_buf.st_mode & S_IFMT)
    {
      case  S_IFDIR:				/* Clone a directory */

        if (!dir_already_exists)
          {
            /* Don't let others sneak in. 
               Only we can write the new directory (for now).  */
      
            if (mkdir (d_path, 0700))
              {
                if (!quiet_flag)
      	          {
                    fprintf (stderr, "%s: error: can't create output directory %s: %s\n",
	              pname, d_path, sys_errlist[errno]);
                    fprintf (stderr, "%s: input directory %s will be ignored\n",
	              pname, s_path);
	          }
                return;
	      }
            if (verbose_flag)
              fprintf (stderr, "%s: created new output directory: %s\n",
                pname, d_path);
          }

	clone_dir(s_path, d_path, level);

	/* By default, output directories which existed before this
	   program was executed are reset back to their original
	   permissions (when we are done adding things to them).  For
	   output directories which are actually created by this program
	   however, these have their permissions set so that they are
	   essentially the same as the permissions for their corresponding
	   input directories, except that the owner is given full
	   permissions.  */

	if (dir_already_exists)
	  fix_mode (dst_stat_buf.st_mode & 07777, d_path);
	else
	  fix_mode ((src_stat_buf.st_mode & 07777) | 0700, d_path);
	break;

#ifndef USG
      case S_IFLNK:				/* Clone a symbolic link */

	if (!sccs_flag)
          clone_symbolic_link (s_path, d_path);
	break;
#endif

      default:					/* Clone a normal file */

	if (sccs_flag)
	  break;

#ifndef USG
	if (symlink_flag)
	  mk_symbolic_link(s_path, d_path, level);
	else
#endif
	if (copy_flag)
	  copy_file(s_path, d_path);
	else
	  mk_hard_link(s_path, d_path);

	break;
    } /* switch */
}
static void
copy_file (char *s_path, char *d_path)
{
  int input, output;
  struct stat src_stat_buf;

  if (lstat (s_path, &src_stat_buf) == -1)
    {
      if (!quiet_flag)
	{
          fprintf (stderr, "%s: error: can't get status of %s: %s\n",
	    pname, s_path, sys_errlist[errno]);
          fprintf (stderr, "%s: input entity %s will be ignored\n",
	    pname, s_path);
	}
      return;
    }

  if ((input = open (s_path, O_RDONLY, 0)) == -1)
    {
      if (!quiet_flag)
        {
          fprintf (stderr, "%s: error: can't open input file %s: %s\n",
	    pname, d_path, sys_errlist[errno]);
	  fprintf (stderr, "%s: input file %s will be ignored\n",
	    pname, s_path);
	}
	return;
    }

  if ((output = open (d_path, O_CREAT | O_WRONLY, src_stat_buf.st_mode & 07777)) == -1)
    {
      if (!quiet_flag)
        {
          fprintf (stderr, "%s: error: can't create output file %s: %s\n",
	    pname, d_path, sys_errlist[errno]);
	  fprintf (stderr, "%s: input file %s will be ignored\n",
	    pname, s_path);
	}
	return;
    }

  for (;;)
    {
      int rlen, wlen;
      char block_buf[BLKDEV_IOSIZE];

      if ((rlen = read (input, block_buf, BLKDEV_IOSIZE)) == -1)
        {
          if (!quiet_flag)
	    {
	      fprintf (stderr, "%s: error: bad read from input file %s: %s\n",
	        pname, s_path, sys_errlist[errno]);
	      fprintf (stderr, "%s: input file %s was not fully copied\n",
	        pname, s_path);
	    }
	  break;
	}

    if (rlen == 0)
      break;

    if ((wlen = write (output, block_buf, rlen)) == -1 || wlen != rlen)
      {
        if (!quiet_flag)
          {
	    fprintf (stderr, "%s: error: bad write to output file %s: %s\n",
	      pname, s_path, sys_errlist[errno]);
	    fprintf (stderr, "%s: input file %s not fully copied\n",
	      pname, s_path);
	  }
	break;
      }
    }

  close (output);
  close (input);

  fix_mode (src_stat_buf.st_mode & 07777, d_path);

  if (verbose_flag)
    fprintf (stderr, "%s: created file copy %s = %s\n",
      pname, d_path, s_path);
}