Exemple #1
0
static int
smb_dir_open(struct inode *dir, struct file *file)
{
	struct dentry *dentry = file->f_path.dentry;
	struct smb_sb_info *server;
	int error = 0;

	VERBOSE("(%s/%s)\n", dentry->d_parent->d_name.name,
		file->f_path.dentry->d_name.name);

	/*
	 * Directory timestamps in the core protocol aren't updated
	 * when a file is added, so we give them a very short TTL.
	 */
	lock_kernel();
	server = server_from_dentry(dentry);
	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
		unsigned long age = jiffies - SMB_I(dir)->oldmtime;
		if (age > 2*HZ)
			smb_invalid_dir_cache(dir);
	}

	/*
	 * Note: in order to allow the smbmount process to open the
	 * mount point, we only revalidate if the connection is valid or
	 * if the process is trying to access something other than the root.
	 */
	if (server->state == CONN_VALID || !IS_ROOT(dentry))
		error = smb_revalidate_inode(dentry);
	unlock_kernel();
	return error;
}
Exemple #2
0
/*
 * Note: in order to allow the smbclient process to open the
 * mount point, we don't revalidate if conn_pid is NULL.
 */
static int
smb_dir_open(struct inode *dir, struct file *file)
{
	struct dentry *dentry = file->f_dentry;
	struct smb_sb_info *server = server_from_dentry(dentry);
	int error = 0;
#ifdef SMBFS_DEBUG_VERBOSE
printk("smb_dir_open: (%s/%s)\n", dentry->d_parent->d_name.name, 
file->f_dentry->d_name.name);
#endif
	/*
	 * Directory timestamps in the core protocol aren't updated
	 * when a file is added, so we give them a very short TTL.
	 */
	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
	{
		unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
		if (age > 2*HZ)
			smb_invalid_dir_cache(dir);
	}

	if (server->conn_pid)
		error = smb_revalidate_inode(dentry);
	return error;
}
Exemple #3
0
int smb_symlink(struct inode *dir, struct dentry *dentry, const char *oldname)
{
	DEBUG1("create symlink %s -> %s/%s\n", oldname, DENTRY_PATH(dentry));

	smb_invalid_dir_cache(dir);
	return smb_proc_symlink(server_from_dentry(dentry), dentry, oldname);
}
Exemple #4
0
/*
 * This is called to update the inode attributes after
 * we've made changes to a file or directory.
 */
static int
smb_refresh_inode(struct dentry *dentry)
{
	struct inode *inode = dentry->d_inode;
	int error;
	struct smb_fattr fattr;

	error = smb_proc_getattr(dentry, &fattr);
	if (!error) {
		smb_renew_times(dentry);
		/*
		 * Check whether the type part of the mode changed,
		 * and don't update the attributes if it did.
		 *
		 * And don't dick with the root inode
		 */
		if (inode->i_ino == 2)
			return error;
		if (S_ISLNK(inode->i_mode))
			return error;	/* VFS will deal with it */

		if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {
			smb_set_inode_attr(inode, &fattr);
		} else {
			/*
			 * Big trouble! The inode has become a new object,
			 * so any operations attempted on it are invalid.
			 *
			 * To limit damage, mark the inode as bad so that
			 * subsequent lookup validations will fail.
			 */
			PARANOIA("%s/%s changed mode, %07o to %07o\n",
				 DENTRY_PATH(dentry),
				 inode->i_mode, fattr.f_mode);

			fattr.f_mode = inode->i_mode; /* save mode */
			make_bad_inode(inode);
			inode->i_mode = fattr.f_mode; /* restore mode */
			/*
			 * No need to worry about unhashing the dentry: the
			 * lookup validation will see that the inode is bad.
			 * But we do want to invalidate the caches ...
			 */
			if (!S_ISDIR(inode->i_mode))
				invalidate_remote_inode(inode);
			else
				smb_invalid_dir_cache(inode);
			error = -EIO;
		}
	}
	return error;
}
Exemple #5
0
static int
smb_create(struct inode *dir, const char *name, int len, int mode,
	   struct inode **result)
{
	int error;
	struct smb_dirent entry;
	struct smb_inode_info *new_inode_info;

	*result = NULL;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		printk("smb_create: inode is NULL or not a directory\n");
		iput(dir);
		return -ENOENT;
	}
	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
				     GFP_KERNEL);
	if (new_inode_info == NULL)
	{
		iput(dir);
		return -ENOMEM;
	}
	error = smb_proc_create(dir, name, len, 0, CURRENT_TIME);
	if (error < 0)
	{
		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
		iput(dir);
		return error;
	}
	smb_invalid_dir_cache(dir->i_ino);

	if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0)
	{
		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
		iput(dir);
		return error;
	}
	entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);

	new_inode_info->finfo = entry;

	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
	{
		iput(dir);
		return error;
	}
	iput(dir);
	return 0;
}
Exemple #6
0
static int
smb_mkdir(struct inode *dir, const char *name, int len, int mode)
{
	int error;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		iput(dir);
		return -EINVAL;
	}
	if ((error = smb_proc_mkdir(dir, name, len)) == 0)
	{
		smb_invalid_dir_cache(dir->i_ino);
	}
	iput(dir);
	return error;
}
Exemple #7
0
static int
smb_refill_dir_cache(struct smb_server *server, struct inode *dir,
		     unsigned long f_pos)
{
	int result;
	static struct semaphore sem = MUTEX;
	int i;
	ino_t ino;

	do
	{
		down(&sem);
		result = smb_proc_readdir(server, dir, f_pos,
					  SMB_READDIR_CACHE_SIZE, c_entry);

		if (result <= 0)
		{
			smb_invalid_dir_cache(dir->i_ino);
			up(&sem);
			return result;
		}
		c_seen_eof = (result < SMB_READDIR_CACHE_SIZE);
		c_dev = dir->i_dev;
		c_ino = dir->i_ino;
		c_size = result;
		c_last_returned_index = 0;

		ino = smb_fresh_inodes(server, c_size);
		for (i = 0; i < c_size; i++)
		{
			c_entry[i].f_ino = ino;
			ino += 1;
		}

		up(&sem);

	}
	while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino));

	return result;
}
Exemple #8
0
static int
smb_unlink(struct inode *dir, const char *name, int len)
{
	int error;

	if (!dir || !S_ISDIR(dir->i_mode))
	{
		printk("smb_unlink: inode is NULL or not a directory\n");
		iput(dir);
		return -ENOENT;
	}
	if (smb_find_dir_inode(dir, name, len) != NULL)
	{
		error = -EBUSY;
	} else
	{
		if ((error = smb_proc_unlink(dir, name, len)) == 0)
		{
			smb_invalid_dir_cache(dir->i_ino);
		}
	}
	iput(dir);
	return error;
}
Exemple #9
0
/* DO MORE */
int
smb_notify_change(struct inode *inode, struct iattr *attr)
{
	int error = 0;

	if ((error = inode_change_ok(inode, attr)) < 0)
		return error;

	if (((attr->ia_valid & ATTR_UID) && 
	     (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
		return -EPERM;

	if (((attr->ia_valid & ATTR_GID) && 
	     (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
                return -EPERM;

	if (((attr->ia_valid & ATTR_MODE) &&
	     (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
		return -EPERM;

        if ((attr->ia_valid & ATTR_SIZE) != 0) {

                if ((error = smb_make_open(inode, O_WRONLY)) < 0)
                        goto fail;

                if ((error = smb_proc_trunc(SMB_SERVER(inode),
                                            SMB_FINFO(inode)->fileid,
                                            attr->ia_size)) < 0)
                        goto fail;

        }

        if ((attr->ia_valid & (ATTR_CTIME | ATTR_MTIME | ATTR_ATIME)) != 0) {

                struct smb_dirent finfo;

                finfo.attr  = 0;

                if ((attr->ia_valid & ATTR_CTIME) != 0)
                        finfo.ctime = attr->ia_ctime;
                else
                        finfo.ctime = inode->i_ctime;

                if ((attr->ia_valid & ATTR_MTIME) != 0)
                        finfo.mtime = attr->ia_mtime;
                else
                        finfo.mtime = inode->i_mtime;

                if ((attr->ia_valid & ATTR_ATIME) != 0)
                        finfo.atime = attr->ia_atime;
                else
                        finfo.atime = inode->i_atime;

                if ((error = smb_proc_setattr(SMB_SERVER(inode),
                                              inode, &finfo)) >= 0) {
                        inode->i_ctime = finfo.ctime;
                        inode->i_mtime = finfo.mtime;
                        inode->i_atime = finfo.atime;
                }
        }

 fail:
        smb_invalid_dir_cache((unsigned long)(SMB_INOP(inode)->dir));

	return error;
}