Import 2.3.26pre2
[davej-history.git] / fs / adfs / namei.c
blob4e41c0975c17adce359464fe5c31e1c926a948a7
1 /*
2 * linux/fs/adfs/namei.c
4 * Copyright (C) 1997 Russell King
5 */
7 #include <linux/errno.h>
8 #include <linux/fs.h>
9 #include <linux/adfs_fs.h>
10 #include <linux/fcntl.h>
11 #include <linux/sched.h>
12 #include <linux/stat.h>
13 #include <linux/string.h>
14 #include <linux/locks.h>
17 * NOTE! unlike strncmp, ext2_match returns 1 for success, 0 for failure
19 static int adfs_match (int len, const char * const name, struct adfs_idir_entry *de)
21 int i;
23 if (!de || len > ADFS_NAME_LEN)
24 return 0;
26 * "" means "." ---> so paths like "/usr/lib//libc.a" work
28 if (!len && de->name_len == 1 && de->name[0] == '.' &&
29 de->name[1] == '\0')
30 return 1;
31 if (len != de->name_len)
32 return 0;
34 for (i = 0; i < len; i++)
35 if ((de->name[i] ^ name[i]) & 0x5f)
36 return 0;
37 return 1;
40 static int adfs_find_entry (struct inode *dir, const char * const name, int namelen,
41 struct adfs_idir_entry *ide)
43 struct super_block *sb;
44 struct buffer_head *bh[4];
45 union adfs_dirtail dt;
46 unsigned long parent_object_id, dir_object_id;
47 int buffers, pos;
49 sb = dir->i_sb;
51 if (adfs_inode_validate (dir)) {
52 adfs_error (sb, "adfs_find_entry",
53 "invalid inode number: %lu", dir->i_ino);
54 return 0;
57 if (!(buffers = adfs_dir_read (dir, bh))) {
58 adfs_error (sb, "adfs_find_entry", "unable to read directory");
59 return 0;
62 if (adfs_dir_check (dir, bh, buffers, &dt)) {
63 adfs_dir_free (bh, buffers);
64 return 0;
67 parent_object_id = adfs_val (dt.new.dirparent, 3);
68 dir_object_id = adfs_inode_objid (dir);
70 if (namelen == 2 && name[0] == '.' && name[1] == '.') {
71 ide->name_len = 2;
72 ide->name[0] = ide->name[1] = '.';
73 ide->name[2] = '\0';
74 ide->inode_no = adfs_inode_generate (parent_object_id, 0);
75 adfs_dir_free (bh, buffers);
76 return 1;
79 pos = 5;
81 do {
82 if (!adfs_dir_get (sb, bh, buffers, pos, dir_object_id, ide))
83 break;
85 if (adfs_match (namelen, name, ide)) {
86 adfs_dir_free (bh, buffers);
87 return pos;
89 pos += 26;
90 } while (1);
91 adfs_dir_free (bh, buffers);
92 return 0;
95 struct dentry *adfs_lookup (struct inode *dir, struct dentry *dentry)
97 struct inode *inode = NULL;
98 struct adfs_idir_entry de;
99 unsigned long ino;
101 if (dentry->d_name.len > ADFS_NAME_LEN)
102 return ERR_PTR(-ENAMETOOLONG);
104 if (adfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de)) {
105 ino = de.inode_no;
106 inode = iget (dir->i_sb, ino);
108 if (!inode)
109 return ERR_PTR(-EACCES);
111 d_add(dentry, inode);
112 return NULL;