Blame view
fs/minix/namei.c
5.4 KB
b24413180
|
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c
|
2 3 4 5 6 7 8 |
/* * linux/fs/minix/namei.c * * Copyright (C) 1991, 1992 Linus Torvalds */ #include "minix.h" |
1da177e4c
|
9 10 11 12 13 14 15 |
static int add_nondir(struct dentry *dentry, struct inode *inode) { int err = minix_add_link(dentry, inode); if (!err) { d_instantiate(dentry, inode); return 0; } |
78ec7b691
|
16 |
inode_dec_link_count(inode); |
1da177e4c
|
17 18 19 |
iput(inode); return err; } |
00cd8dd3b
|
20 |
static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags) |
1da177e4c
|
21 22 23 |
{ struct inode * inode = NULL; ino_t ino; |
1da177e4c
|
24 25 26 27 |
if (dentry->d_name.len > minix_sb(dir->i_sb)->s_namelen) return ERR_PTR(-ENAMETOOLONG); ino = minix_inode_by_name(dentry); |
b01495169
|
28 |
if (ino) |
a90a08802
|
29 |
inode = minix_iget(dir->i_sb, ino); |
b01495169
|
30 |
return d_splice_alias(inode, dentry); |
1da177e4c
|
31 |
} |
1a67aafb5
|
32 |
static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode, dev_t rdev) |
1da177e4c
|
33 34 35 36 37 38 |
{ int error; struct inode *inode; if (!old_valid_dev(rdev)) return -EINVAL; |
9eed1fb72
|
39 |
inode = minix_new_inode(dir, mode, &error); |
1da177e4c
|
40 41 |
if (inode) { |
1da177e4c
|
42 43 44 45 46 47 |
minix_set_inode(inode, rdev); mark_inode_dirty(inode); error = add_nondir(dentry, inode); } return error; } |
60545d0d4
|
48 49 50 51 52 53 54 55 56 57 58 |
static int minix_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) { int error; struct inode *inode = minix_new_inode(dir, mode, &error); if (inode) { minix_set_inode(inode, 0); mark_inode_dirty(inode); d_tmpfile(dentry, inode); } return error; } |
4acdaf27e
|
59 |
static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
ebfc3b49a
|
60 |
bool excl) |
1da177e4c
|
61 62 63 64 65 66 67 68 69 70 71 72 73 |
{ return minix_mknod(dir, dentry, mode, 0); } static int minix_symlink(struct inode * dir, struct dentry *dentry, const char * symname) { int err = -ENAMETOOLONG; int i = strlen(symname)+1; struct inode * inode; if (i > dir->i_sb->s_blocksize) goto out; |
9eed1fb72
|
74 |
inode = minix_new_inode(dir, S_IFLNK | 0777, &err); |
1da177e4c
|
75 76 |
if (!inode) goto out; |
1da177e4c
|
77 78 79 80 81 82 83 84 85 86 |
minix_set_inode(inode, 0); err = page_symlink(inode, symname, i); if (err) goto out_fail; err = add_nondir(dentry, inode); out: return err; out_fail: |
78ec7b691
|
87 |
inode_dec_link_count(inode); |
1da177e4c
|
88 89 90 91 92 93 94 |
iput(inode); goto out; } static int minix_link(struct dentry * old_dentry, struct inode * dir, struct dentry *dentry) { |
2b0143b5c
|
95 |
struct inode *inode = d_inode(old_dentry); |
1da177e4c
|
96 |
|
02027d42c
|
97 |
inode->i_ctime = current_time(inode); |
78ec7b691
|
98 |
inode_inc_link_count(inode); |
7de9c6ee3
|
99 |
ihold(inode); |
1da177e4c
|
100 101 |
return add_nondir(dentry, inode); } |
18bb1db3e
|
102 |
static int minix_mkdir(struct inode * dir, struct dentry *dentry, umode_t mode) |
1da177e4c
|
103 104 |
{ struct inode * inode; |
8de527787
|
105 |
int err; |
1da177e4c
|
106 |
|
78ec7b691
|
107 |
inode_inc_link_count(dir); |
1da177e4c
|
108 |
|
eee743fd7
|
109 |
inode = minix_new_inode(dir, S_IFDIR | mode, &err); |
1da177e4c
|
110 111 |
if (!inode) goto out_dir; |
1da177e4c
|
112 |
minix_set_inode(inode, 0); |
78ec7b691
|
113 |
inode_inc_link_count(inode); |
1da177e4c
|
114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
err = minix_make_empty(inode, dir); if (err) goto out_fail; err = minix_add_link(dentry, inode); if (err) goto out_fail; d_instantiate(dentry, inode); out: return err; out_fail: |
78ec7b691
|
128 129 |
inode_dec_link_count(inode); inode_dec_link_count(inode); |
1da177e4c
|
130 131 |
iput(inode); out_dir: |
78ec7b691
|
132 |
inode_dec_link_count(dir); |
1da177e4c
|
133 134 135 136 137 138 |
goto out; } static int minix_unlink(struct inode * dir, struct dentry *dentry) { int err = -ENOENT; |
2b0143b5c
|
139 |
struct inode * inode = d_inode(dentry); |
1da177e4c
|
140 141 142 143 144 145 146 147 148 149 150 151 |
struct page * page; struct minix_dir_entry * de; de = minix_find_entry(dentry, &page); if (!de) goto end_unlink; err = minix_delete_entry(de, page); if (err) goto end_unlink; inode->i_ctime = dir->i_ctime; |
78ec7b691
|
152 |
inode_dec_link_count(inode); |
1da177e4c
|
153 154 155 156 157 158 |
end_unlink: return err; } static int minix_rmdir(struct inode * dir, struct dentry *dentry) { |
2b0143b5c
|
159 |
struct inode * inode = d_inode(dentry); |
1da177e4c
|
160 161 162 163 164 |
int err = -ENOTEMPTY; if (minix_empty_dir(inode)) { err = minix_unlink(dir, dentry); if (!err) { |
78ec7b691
|
165 166 |
inode_dec_link_count(dir); inode_dec_link_count(inode); |
1da177e4c
|
167 168 169 170 171 172 |
} } return err; } static int minix_rename(struct inode * old_dir, struct dentry *old_dentry, |
f03b8ad8d
|
173 174 |
struct inode * new_dir, struct dentry *new_dentry, unsigned int flags) |
1da177e4c
|
175 |
{ |
2b0143b5c
|
176 177 |
struct inode * old_inode = d_inode(old_dentry); struct inode * new_inode = d_inode(new_dentry); |
1da177e4c
|
178 179 180 181 182 |
struct page * dir_page = NULL; struct minix_dir_entry * dir_de = NULL; struct page * old_page; struct minix_dir_entry * old_de; int err = -ENOENT; |
f03b8ad8d
|
183 184 |
if (flags & ~RENAME_NOREPLACE) return -EINVAL; |
1da177e4c
|
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
old_de = minix_find_entry(old_dentry, &old_page); if (!old_de) goto out; if (S_ISDIR(old_inode->i_mode)) { err = -EIO; dir_de = minix_dotdot(old_inode, &dir_page); if (!dir_de) goto out_old; } if (new_inode) { struct page * new_page; struct minix_dir_entry * new_de; err = -ENOTEMPTY; if (dir_de && !minix_empty_dir(new_inode)) goto out_dir; err = -ENOENT; new_de = minix_find_entry(new_dentry, &new_page); if (!new_de) goto out_dir; |
1da177e4c
|
208 |
minix_set_link(new_de, new_page, old_inode); |
02027d42c
|
209 |
new_inode->i_ctime = current_time(new_inode); |
1da177e4c
|
210 |
if (dir_de) |
9a53c3a78
|
211 |
drop_nlink(new_inode); |
78ec7b691
|
212 |
inode_dec_link_count(new_inode); |
1da177e4c
|
213 |
} else { |
1da177e4c
|
214 |
err = minix_add_link(new_dentry, old_inode); |
6f88049ca
|
215 |
if (err) |
1da177e4c
|
216 |
goto out_dir; |
1da177e4c
|
217 |
if (dir_de) |
78ec7b691
|
218 |
inode_inc_link_count(new_dir); |
1da177e4c
|
219 220 221 |
} minix_delete_entry(old_de, old_page); |
6f88049ca
|
222 |
mark_inode_dirty(old_inode); |
1da177e4c
|
223 224 225 |
if (dir_de) { minix_set_link(dir_de, dir_page, new_dir); |
78ec7b691
|
226 |
inode_dec_link_count(old_dir); |
1da177e4c
|
227 228 229 230 231 232 |
} return 0; out_dir: if (dir_de) { kunmap(dir_page); |
09cbfeaf1
|
233 |
put_page(dir_page); |
1da177e4c
|
234 235 236 |
} out_old: kunmap(old_page); |
09cbfeaf1
|
237 |
put_page(old_page); |
1da177e4c
|
238 239 240 241 242 243 244 |
out: return err; } /* * directories can handle most operations... */ |
92e1d5be9
|
245 |
const struct inode_operations minix_dir_inode_operations = { |
1da177e4c
|
246 247 248 249 250 251 252 253 254 255 |
.create = minix_create, .lookup = minix_lookup, .link = minix_link, .unlink = minix_unlink, .symlink = minix_symlink, .mkdir = minix_mkdir, .rmdir = minix_rmdir, .mknod = minix_mknod, .rename = minix_rename, .getattr = minix_getattr, |
60545d0d4
|
256 |
.tmpfile = minix_tmpfile, |
1da177e4c
|
257 |
}; |