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