fs/smb/client/dir.c

Source file repositories/reference/linux-study-clean/fs/smb/client/dir.c

File Facts

System
Linux kernel
Corpus path
fs/smb/client/dir.c
Extension
.c
Size
31632 bytes
Lines
1213
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (sbflags & CIFS_MOUNT_POSIX_PATHS) {
			int i;
			for (i = 0; i < dfsplen; i++) {
				if (s[i] == '\\')
					s[i] = '/';
			}
		}
	}
	return s;
}

char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
					     bool prefix)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
	struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);

	return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name,
							MAX_TREE_SIZE, prefix);
}

/*
 * Don't allow path components longer than the server max.
 * Don't allow the separator character in a path component.
 * The VFS will not allow "/", but "\" is allowed by posix.
 */
static int
check_name(struct dentry *direntry, struct cifs_tcon *tcon)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(direntry);
	int i;

	if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
		     direntry->d_name.len >
		     le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
		return -ENAMETOOLONG;

	if (!(cifs_sb_flags(cifs_sb) & CIFS_MOUNT_POSIX_PATHS)) {
		for (i = 0; i < direntry->d_name.len; i++) {
			if (direntry->d_name.name[i] == '\\') {
				cifs_dbg(FYI, "Invalid file name\n");
				return -EINVAL;
			}
		}
	}
	return 0;
}

static char *alloc_parent_path(struct dentry *dentry, size_t namelen)
{
	struct cifs_sb_info *cifs_sb = CIFS_SB(dentry);
	void *page = alloc_dentry_path();
	const char *path;
	size_t size;
	char *npath;

	path = build_path_from_dentry(dentry->d_parent, page);
	if (IS_ERR(path)) {
		npath = ERR_CAST(path);
		goto out;
	}

	size = strlen(path) + namelen + 2;
	npath = kmalloc(size, GFP_KERNEL);
	if (!npath)
		npath = ERR_PTR(-ENOMEM);
	else
		scnprintf(npath, size, "%s%c", path, CIFS_DIR_SEP(cifs_sb));
out:
	free_dentry_path(page);
	return npath;
}

/* Inode operations in similar order to how they appear in Linux file fs.h */
static int __cifs_do_create(struct inode *dir, struct dentry *direntry,
			    const char *full_path, unsigned int xid,
			    struct tcon_link *tlink, unsigned int oflags,
			    umode_t mode, __u32 *oplock, struct cifs_fid *fid,
			    struct cifs_open_info_data *buf,
			    struct inode **inode)
{
	int rc = -ENOENT;
	int create_options = CREATE_NOT_DIR;
	int desired_access;
	struct cifs_sb_info *cifs_sb = CIFS_SB(dir);
	struct cifs_tcon *tcon = tlink_tcon(tlink);
	struct inode *newinode = NULL;
	unsigned int sbflags = cifs_sb_flags(cifs_sb);
	int disposition;
	struct TCP_Server_Info *server = tcon->ses->server;

Annotation

Implementation Notes