2 #include <linux/kernel.h>
3 #include <linux/dirent.h>
4 #include <linux/string.h>
8 extern asmlinkage
long sys_symlink(const char *old
, const char *new);
9 extern asmlinkage
long sys_access(const char * filename
, int mode
);
10 extern asmlinkage
long sys_getdents64(unsigned int fd
, void * dirent
,
13 void __init
mount_devfs(void)
15 sys_mount("devfs", "/dev", "devfs", 0, NULL
);
18 void __init
umount_devfs(char *path
)
24 * If the dir will fit in *buf, return its length. If it won't fit, return
25 * zero. Return -ve on error.
27 static int __init
do_read_dir(int fd
, void *buf
, int len
)
33 for (bytes
= 0; bytes
< len
; bytes
+= n
) {
34 n
= sys_getdents64(fd
, p
+ bytes
, len
- bytes
);
44 * Try to read all of a directory. Returns the contents at *p, which
45 * is kmalloced memory. Returns the number of bytes read at *len. Returns
48 static void * __init
read_dir(char *path
, int *len
)
51 int fd
= open(path
, 0, 0);
57 for (size
= 1 << 9; size
<= (PAGE_SIZE
<< MAX_ORDER
); size
<<= 1) {
58 void *p
= kmalloc(size
, GFP_KERNEL
);
62 n
= do_read_dir(fd
, p
, size
);
70 continue; /* Try a larger buffer */
79 * recursively scan <path>, looking for a device node of type <dev>
81 static int __init
find_in_devfs(char *path
, unsigned dev
)
83 char *end
= path
+ strlen(path
);
84 int rest
= path
+ 64 - end
;
86 char *p
= read_dir(path
, &size
);
91 for (s
= p
; s
< p
+ size
; s
+= ((struct linux_dirent64
*)s
)->d_reclen
) {
92 struct linux_dirent64
*d
= (struct linux_dirent64
*)s
;
93 if (strlen(d
->d_name
) + 2 > rest
)
97 sprintf(end
, "/%s", d
->d_name
);
98 if (bstat(path
) != dev
)
103 if (strcmp(d
->d_name
, ".") == 0)
105 if (strcmp(d
->d_name
, "..") == 0)
107 sprintf(end
, "/%s", d
->d_name
);
108 if (find_in_devfs(path
, dev
) < 0)
119 * create a device node called <name> which points to
120 * <devfs_name> if possible, otherwise find a device node
121 * which matches <dev> and make <name> a symlink pointing to it.
123 int __init
create_dev(char *name
, dev_t dev
, char *devfs_name
)
128 if (devfs_name
&& devfs_name
[0]) {
129 if (strncmp(devfs_name
, "/dev/", 5) == 0)
131 sprintf(path
, "/dev/%s", devfs_name
);
132 if (sys_access(path
, 0) == 0)
133 return sys_symlink(devfs_name
, name
);
137 strcpy(path
, "/dev");
138 if (find_in_devfs(path
, new_encode_dev(dev
)) < 0)
140 return sys_symlink(path
+ 5, name
);