1 /* 2 * linux/fs/sysv/dir.c 3 * 4 * minix/dir.c 5 * Copyright (C) 1991, 1992 Linus Torvalds 6 * 7 * coh/dir.c 8 * Copyright (C) 1993 Pascal Haible, Bruno Haible 9 * 10 * sysv/dir.c 11 * Copyright (C) 1993 Bruno Haible 12 * 13 * SystemV/Coherent directory handling functions 14 */ 15 16 #include <linux/pagemap.h> 17 #include <linux/highmem.h> 18 #include <linux/smp_lock.h> 19 #include "sysv.h" 20 21 static int sysv_readdir(struct file *, void *, filldir_t); 22 23 const struct file_operations sysv_dir_operations = { 24 .read = generic_read_dir, 25 .readdir = sysv_readdir, 26 .fsync = sysv_sync_file, 27 }; 28 29 static inline void dir_put_page(struct page *page) 30 { 31 kunmap(page); 32 page_cache_release(page); 33 } 34 35 static inline unsigned long dir_pages(struct inode *inode) 36 { 37 return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT; 38 } 39 40 static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) 41 { 42 struct inode *dir = (struct inode *)page->mapping->host; 43 int err = 0; 44 45 page->mapping->a_ops->commit_write(NULL, page, from, to); 46 if (IS_DIRSYNC(dir)) 47 err = write_one_page(page, 1); 48 else 49 unlock_page(page); 50 return err; 51 } 52 53 static struct page * dir_get_page(struct inode *dir, unsigned long n) 54 { 55 struct address_space *mapping = dir->i_mapping; 56 struct page *page = read_mapping_page(mapping, n, NULL); 57 if (!IS_ERR(page)) 58 kmap(page); 59 return page; 60 } 61 62 static int sysv_readdir(struct file * filp, void * dirent, filldir_t filldir) 63 { 64 unsigned long pos = filp->f_pos; 65 struct inode *inode = filp->f_path.dentry->d_inode; 66 struct super_block *sb = inode->i_sb; 67 unsigned offset = pos & ~PAGE_CACHE_MASK; 68 unsigned long n = pos >> PAGE_CACHE_SHIFT; 69 unsigned long npages = dir_pages(inode); 70 71 lock_kernel(); 72 73 pos = (pos + SYSV_DIRSIZE-1) & ~(SYSV_DIRSIZE-1); 74 if (pos >= inode->i_size) 75 goto done; 76 77 for ( ; n < npages; n++, offset = 0) { 78 char *kaddr, *limit; 79 struct sysv_dir_entry *de; 80 struct page *page = dir_get_page(inode, n); 81 82 if (IS_ERR(page)) 83 continue; 84 kaddr = (char *)page_address(page); 85 de = (struct sysv_dir_entry *)(kaddr+offset); 86 limit = kaddr + PAGE_CACHE_SIZE - SYSV_DIRSIZE; 87 for ( ;(char*)de <= limit; de++) { 88 char *name = de->name; 89 int over; 90 91 if (!de->inode) 92 continue; 93 94 offset = (char *)de - kaddr; 95 96 over = filldir(dirent, name, strnlen(name,SYSV_NAMELEN), 97 ((loff_t)n<<PAGE_CACHE_SHIFT) | offset, 98 fs16_to_cpu(SYSV_SB(sb), de->inode), 99 DT_UNKNOWN); 100 if (over) { 101 dir_put_page(page); 102 goto done; 103 } 104 } 105 dir_put_page(page); 106 } 107 108 done: 109 filp->f_pos = ((loff_t)n << PAGE_CACHE_SHIFT) | offset; 110 unlock_kernel(); 111 return 0; 112 } 113 114 /* compare strings: name[0..len-1] (not zero-terminated) and 115 * buffer[0..] (filled with zeroes up to buffer[0..maxlen-1]) 116 */ 117 static inline int namecompare(int len, int maxlen, 118 const char * name, const char * buffer) 119 { 120 if (len < maxlen && buffer[len]) 121 return 0; 122 return !memcmp(name, buffer, len); 123 } 124 125 /* 126 * sysv_find_entry() 127 * 128 * finds an entry in the specified directory with the wanted name. It 129 * returns the cache buffer in which the entry was found, and the entry 130 * itself (as a parameter - res_dir). It does NOT read the inode of the 131 * entry - you'll have to do that yourself if you want to. 132 */ 133 struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page) 134 { 135 const char * name = dentry->d_name.name; 136 int namelen = dentry->d_name.len; 137 struct inode * dir = dentry->d_parent->d_inode; 138 unsigned long start, n; 139 unsigned long npages = dir_pages(dir); 140 struct page *page = NULL; 141 struct sysv_dir_entry *de; 142 143 *res_page = NULL; 144 145 start = SYSV_I(dir)->i_dir_start_lookup; 146 if (start >= npages) 147 start = 0; 148 n = start; 149 150 do { 151 char *kaddr; 152 page = dir_get_page(dir, n); 153 if (!IS_ERR(page)) { 154 kaddr = (char*)page_address(page); 155 de = (struct sysv_dir_entry *) kaddr; 156 kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE; 157 for ( ; (char *) de <= kaddr ; de++) { 158 if (!de->inode) 159 continue; 160 if (namecompare(namelen, SYSV_NAMELEN, 161 name, de->name)) 162 goto found; 163 } 164 } 165 dir_put_page(page); 166 167 if (++n >= npages) 168 n = 0; 169 } while (n != start); 170 171 return NULL; 172 173 found: 174 SYSV_I(dir)->i_dir_start_lookup = n; 175 *res_page = page; 176 return de; 177 } 178 179 int sysv_add_link(struct dentry *dentry, struct inode *inode) 180 { 181 struct inode *dir = dentry->d_parent->d_inode; 182 const char * name = dentry->d_name.name; 183 int namelen = dentry->d_name.len; 184 struct page *page = NULL; 185 struct sysv_dir_entry * de; 186 unsigned long npages = dir_pages(dir); 187 unsigned long n; 188 char *kaddr; 189 unsigned from, to; 190 int err; 191 192 /* We take care of directory expansion in the same loop */ 193 for (n = 0; n <= npages; n++) { 194 page = dir_get_page(dir, n); 195 err = PTR_ERR(page); 196 if (IS_ERR(page)) 197 goto out; 198 kaddr = (char*)page_address(page); 199 de = (struct sysv_dir_entry *)kaddr; 200 kaddr += PAGE_CACHE_SIZE - SYSV_DIRSIZE; 201 while ((char *)de <= kaddr) { 202 if (!de->inode) 203 goto got_it; 204 err = -EEXIST; 205 if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) 206 goto out_page; 207 de++; 208 } 209 dir_put_page(page); 210 } 211 BUG(); 212 return -EINVAL; 213 214 got_it: 215 from = (char*)de - (char*)page_address(page); 216 to = from + SYSV_DIRSIZE; 217 lock_page(page); 218 err = page->mapping->a_ops->prepare_write(NULL, page, from, to); 219 if (err) 220 goto out_unlock; 221 memcpy (de->name, name, namelen); 222 memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); 223 de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); 224 err = dir_commit_chunk(page, from, to); 225 dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; 226 mark_inode_dirty(dir); 227 out_page: 228 dir_put_page(page); 229 out: 230 return err; 231 out_unlock: 232 unlock_page(page); 233 goto out_page; 234 } 235 236 int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page) 237 { 238 struct address_space *mapping = page->mapping; 239 struct inode *inode = (struct inode*)mapping->host; 240 char *kaddr = (char*)page_address(page); 241 unsigned from = (char*)de - kaddr; 242 unsigned to = from + SYSV_DIRSIZE; 243 int err; 244 245 lock_page(page); 246 err = mapping->a_ops->prepare_write(NULL, page, from, to); 247 BUG_ON(err); 248 de->inode = 0; 249 err = dir_commit_chunk(page, from, to); 250 dir_put_page(page); 251 inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; 252 mark_inode_dirty(inode); 253 return err; 254 } 255 256 int sysv_make_empty(struct inode *inode, struct inode *dir) 257 { 258 struct address_space *mapping = inode->i_mapping; 259 struct page *page = grab_cache_page(mapping, 0); 260 struct sysv_dir_entry * de; 261 char *base; 262 int err; 263 264 if (!page) 265 return -ENOMEM; 266 kmap(page); 267 err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * SYSV_DIRSIZE); 268 if (err) { 269 unlock_page(page); 270 goto fail; 271 } 272 273 base = (char*)page_address(page); 274 memset(base, 0, PAGE_CACHE_SIZE); 275 276 de = (struct sysv_dir_entry *) base; 277 de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); 278 strcpy(de->name,"."); 279 de++; 280 de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino); 281 strcpy(de->name,".."); 282 283 err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE); 284 fail: 285 kunmap(page); 286 page_cache_release(page); 287 return err; 288 } 289 290 /* 291 * routine to check that the specified directory is empty (for rmdir) 292 */ 293 int sysv_empty_dir(struct inode * inode) 294 { 295 struct super_block *sb = inode->i_sb; 296 struct page *page = NULL; 297 unsigned long i, npages = dir_pages(inode); 298 299 for (i = 0; i < npages; i++) { 300 char *kaddr; 301 struct sysv_dir_entry * de; 302 page = dir_get_page(inode, i); 303 304 if (IS_ERR(page)) 305 continue; 306 307 kaddr = (char *)page_address(page); 308 de = (struct sysv_dir_entry *)kaddr; 309 kaddr += PAGE_CACHE_SIZE-SYSV_DIRSIZE; 310 311 for ( ;(char *)de <= kaddr; de++) { 312 if (!de->inode) 313 continue; 314 /* check for . and .. */ 315 if (de->name[0] != '.') 316 goto not_empty; 317 if (!de->name[1]) { 318 if (de->inode == cpu_to_fs16(SYSV_SB(sb), 319 inode->i_ino)) 320 continue; 321 goto not_empty; 322 } 323 if (de->name[1] != '.' || de->name[2]) 324 goto not_empty; 325 } 326 dir_put_page(page); 327 } 328 return 1; 329 330 not_empty: 331 dir_put_page(page); 332 return 0; 333 } 334 335 /* Releases the page */ 336 void sysv_set_link(struct sysv_dir_entry *de, struct page *page, 337 struct inode *inode) 338 { 339 struct inode *dir = (struct inode*)page->mapping->host; 340 unsigned from = (char *)de-(char*)page_address(page); 341 unsigned to = from + SYSV_DIRSIZE; 342 int err; 343 344 lock_page(page); 345 err = page->mapping->a_ops->prepare_write(NULL, page, from, to); 346 BUG_ON(err); 347 de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); 348 err = dir_commit_chunk(page, from, to); 349 dir_put_page(page); 350 dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; 351 mark_inode_dirty(dir); 352 } 353 354 struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p) 355 { 356 struct page *page = dir_get_page(dir, 0); 357 struct sysv_dir_entry *de = NULL; 358 359 if (!IS_ERR(page)) { 360 de = (struct sysv_dir_entry*) page_address(page) + 1; 361 *p = page; 362 } 363 return de; 364 } 365 366 ino_t sysv_inode_by_name(struct dentry *dentry) 367 { 368 struct page *page; 369 struct sysv_dir_entry *de = sysv_find_entry (dentry, &page); 370 ino_t res = 0; 371 372 if (de) { 373 res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode); 374 dir_put_page(page); 375 } 376 return res; 377 } 378