summaryrefslogtreecommitdiff
path: root/include/linux/namei.h
blob: 58600cf234bcf97fb4a61704818e6535191985b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_NAMEI_H
#define _LINUX_NAMEI_H

#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/path.h>
#include <linux/fcntl.h>
#include <linux/errno.h>
#include <linux/fs_struct.h>

enum { MAX_NESTED_LINKS = 8 };

#define MAXSYMLINKS 40

/*
 * Type of the last component on LOOKUP_PARENT
 */
enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};

/* pathwalk mode */
#define LOOKUP_FOLLOW		BIT(0)	/* follow links at the end */
#define LOOKUP_DIRECTORY	BIT(1)	/* require a directory */
#define LOOKUP_AUTOMOUNT	BIT(2)  /* force terminal automount */
#define LOOKUP_EMPTY		BIT(3)	/* accept empty path [user_... only] */
#define LOOKUP_LINKAT_EMPTY	BIT(4) /* Linkat request with empty path. */
#define LOOKUP_DOWN		BIT(5)	/* follow mounts in the starting point */
#define LOOKUP_MOUNTPOINT	BIT(6)	/* follow mounts in the end */
#define LOOKUP_REVAL		BIT(7)	/* tell ->d_revalidate() to trust no cache */
#define LOOKUP_RCU		BIT(8)	/* RCU pathwalk mode; semi-internal */
#define LOOKUP_CACHED		BIT(9) /* Only do cached lookup */
#define LOOKUP_PARENT		BIT(10)	/* Looking up final parent in path */
/* 5 spare bits for pathwalk */

/* These tell filesystem methods that we are dealing with the final component... */
#define LOOKUP_OPEN		BIT(16)	/* ... in open */
#define LOOKUP_CREATE		BIT(17)	/* ... in object creation */
#define LOOKUP_EXCL		BIT(18)	/* ... in target must not exist */
#define LOOKUP_RENAME_TARGET	BIT(19)	/* ... in destination of rename() */

/* 4 spare bits for intent */

/* Scoping flags for lookup. */
#define LOOKUP_NO_SYMLINKS	BIT(24) /* No symlink crossing. */
#define LOOKUP_NO_MAGICLINKS	BIT(25) /* No nd_jump_link() crossing. */
#define LOOKUP_NO_XDEV		BIT(26) /* No mountpoint crossing. */
#define LOOKUP_BENEATH		BIT(27) /* No escaping from starting point. */
#define LOOKUP_IN_ROOT		BIT(28) /* Treat dirfd as fs root. */
/* LOOKUP_* flags which do scope-related checks based on the dirfd. */
#define LOOKUP_IS_SCOPED (LOOKUP_BENEATH | LOOKUP_IN_ROOT)
/* 3 spare bits for scoping */

extern int path_pts(struct path *path);

extern int user_path_at(int, const char __user *, unsigned, struct path *);

struct dentry *lookup_one_qstr_excl(const struct qstr *name,
				    struct dentry *base,
				    unsigned int flags);
extern int kern_path(const char *, unsigned, struct path *);
struct dentry *kern_path_parent(const char *name, struct path *parent);

extern struct dentry *start_creating_path(int, const char *, struct path *, unsigned int);
extern struct dentry *start_creating_user_path(int, const char __user *, struct path *, unsigned int);
extern void end_creating_path(const struct path *, struct dentry *);
extern struct dentry *start_removing_path(const char *, struct path *);
extern struct dentry *start_removing_user_path_at(int , const char __user *, struct path *);
static inline void end_removing_path(const struct path *path , struct dentry *dentry)
{
	end_creating_path(path, dentry);
}
int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
			   struct path *parent, struct qstr *last, int *type,
			   const struct path *root);
int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
		    unsigned int, struct path *);

extern struct dentry *try_lookup_noperm(struct qstr *, struct dentry *);
extern struct dentry *lookup_noperm(struct qstr *, struct dentry *);
extern struct dentry *lookup_noperm_unlocked(struct qstr *, struct dentry *);
extern struct dentry *lookup_noperm_positive_unlocked(struct qstr *, struct dentry *);
struct dentry *lookup_one(struct mnt_idmap *, struct qstr *, struct dentry *);
struct dentry *lookup_one_unlocked(struct mnt_idmap *idmap,
				   struct qstr *name, struct dentry *base);
struct dentry *lookup_one_positive_unlocked(struct mnt_idmap *idmap,
					    struct qstr *name,
					    struct dentry *base);
struct dentry *lookup_one_positive_killable(struct mnt_idmap *idmap,
					    struct qstr *name,
					    struct dentry *base);

struct dentry *start_creating(struct mnt_idmap *idmap, struct dentry *parent,
			      struct qstr *name);
struct dentry *start_removing(struct mnt_idmap *idmap, struct dentry *parent,
			      struct qstr *name);
struct dentry *start_creating_killable(struct mnt_idmap *idmap,
				       struct dentry *parent,
				       struct qstr *name);
struct dentry *start_removing_killable(struct mnt_idmap *idmap,
				       struct dentry *parent,
				       struct qstr *name);
struct dentry *start_creating_noperm(struct dentry *parent, struct qstr *name);
struct dentry *start_removing_noperm(struct dentry *parent, struct qstr *name);
struct dentry *start_creating_dentry(struct dentry *parent,
				     struct dentry *child);
struct dentry *start_removing_dentry(struct dentry *parent,
				     struct dentry *child);

/* end_creating - finish action started with start_creating
 * @child: dentry returned by start_creating() or vfs_mkdir()
 *
 * Unlock and release the child. This can be called after
 * start_creating() whether that function succeeded or not,
 * but it is not needed on failure.
 *
 * If vfs_mkdir() was called then the value returned from that function
 * should be given for @child rather than the original dentry, as vfs_mkdir()
 * may have provided a new dentry.
 *
 *
 * If vfs_mkdir() was not called, then @child will be a valid dentry and
 * @parent will be ignored.
 */
static inline void end_creating(struct dentry *child)
{
	end_dirop(child);
}

/* end_creating_keep - finish action started with start_creating() and return result
 * @child: dentry returned by start_creating() or vfs_mkdir()
 *
 * Unlock and return the child. This can be called after
 * start_creating() whether that function succeeded or not,
 * but it is not needed on failure.
 *
 * If vfs_mkdir() was called then the value returned from that function
 * should be given for @child rather than the original dentry, as vfs_mkdir()
 * may have provided a new dentry.
 *
 * Returns: @child, which may be a dentry or an error.
 *
 */
static inline struct dentry *end_creating_keep(struct dentry *child)
{
	if (!IS_ERR(child))
		dget(child);
	end_dirop(child);
	return child;
}

/**
 * end_removing - finish action started with start_removing
 * @child:  dentry returned by start_removing()
 * @parent: dentry given to start_removing()
 *
 * Unlock and release the child.
 *
 * This is identical to end_dirop().  It can be passed the result of
 * start_removing() whether that was successful or not, but it not needed
 * if start_removing() failed.
 */
static inline void end_removing(struct dentry *child)
{
	end_dirop(child);
}

extern int follow_down_one(struct path *);
extern int follow_down(struct path *path, unsigned int flags);
extern int follow_up(struct path *);

extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern struct dentry *lock_rename_child(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
int start_renaming(struct renamedata *rd, int lookup_flags,
		   struct qstr *old_last, struct qstr *new_last);
int start_renaming_dentry(struct renamedata *rd, int lookup_flags,
			  struct dentry *old_dentry, struct qstr *new_last);
int start_renaming_two_dentries(struct renamedata *rd,
				struct dentry *old_dentry, struct dentry *new_dentry);
void end_renaming(struct renamedata *rd);

/**
 * mode_strip_umask - handle vfs umask stripping
 * @dir:	parent directory of the new inode
 * @mode:	mode of the new inode to be created in @dir
 *
 * In most filesystems, umask stripping depends on whether or not the
 * filesystem supports POSIX ACLs. If the filesystem doesn't support it umask
 * stripping is done directly in here. If the filesystem does support POSIX
 * ACLs umask stripping is deferred until the filesystem calls
 * posix_acl_create().
 *
 * Some filesystems (like NFSv4) also want to avoid umask stripping by the
 * VFS, but don't support POSIX ACLs. Those filesystems can set SB_I_NOUMASK
 * to get this effect without declaring that they support POSIX ACLs.
 *
 * Returns: mode
 */
static inline umode_t __must_check mode_strip_umask(const struct inode *dir, umode_t mode)
{
	if (!IS_POSIXACL(dir) && !(dir->i_sb->s_iflags & SB_I_NOUMASK))
		mode &= ~current_umask();
	return mode;
}

extern int __must_check nd_jump_link(const struct path *path);

static inline void nd_terminate_link(void *name, size_t len, size_t maxlen)
{
	((char *) name)[min(len, maxlen)] = '\0';
}

/**
 * retry_estale - determine whether the caller should retry an operation
 * @error: the error that would currently be returned
 * @flags: flags being used for next lookup attempt
 *
 * Check to see if the error code was -ESTALE, and then determine whether
 * to retry the call based on whether "flags" already has LOOKUP_REVAL set.
 *
 * Returns true if the caller should try the operation again.
 */
static inline bool
retry_estale(const long error, const unsigned int flags)
{
	return unlikely(error == -ESTALE && !(flags & LOOKUP_REVAL));
}

#endif /* _LINUX_NAMEI_H */