2 * $Id: nametrans.c,v 1.2 1997/06/04 23:45:44 davem Exp $
4 * linux/fs/nametrans.c - context-dependend filename suffixes.
5 * Copyright (C) 1997, Thomas Schoebel-Theuer,
6 * <schoebel@informatik.uni-stuttgart.de>.
8 * translates names of the form "filename#host=myhost#" to "filename"
9 * as if both names were hardlinked to the same file.
10 * benefit: diskless clients can mount the / filesystem of the
11 * server if /etc/fstab (and other config files) are organized using
15 #include <linux/config.h>
16 #include <linux/errno.h>
17 #include <linux/kernel.h>
18 #include <linux/utsname.h>
19 #include <linux/sched.h>
21 #include <asm/uaccess.h>
22 #include <linux/nametrans.h>
24 char nametrans_txt
[MAX_DEFAULT_TRANSLEN
] = "";
25 static struct translations
* global_trans
= NULL
;
26 static int default_trans
= 1;
27 static const char version
[] = "revision: 2.3 <schoebel@informatik.uni-stuttgart.de>";
28 int translations_dirty
= 1;
29 static char * transl_names
[] = {
30 #ifdef CONFIG_TR_NODENAME
31 "host=", system_utsname
.nodename
,
33 #ifdef CONFIG_TR_KERNNAME
34 "kname=", CONFIG_KERNNAME
,
36 #ifdef CONFIG_TR_KERNTYPE
37 "ktype=", CONFIG_KERNTYPE
,
39 #ifdef CONFIG_TR_MACHINE
40 "machine=", system_utsname
.machine
,
42 #ifdef CONFIG_TR_SYSNAME
43 "system=", system_utsname
.sysname
,
48 /* Convert and do syntax checking. */
49 static void convert(char * txt
, struct translations
* res
)
52 char * space
= (char*)res
+ sizeof(struct translations
);
56 struct qstr
* name
= &res
->name
[res
->count
];
57 struct qstr
* c_name
= &res
->c_name
[res
->count
];
63 while(*p
&& *p
!= '=' && *p
!= ':')
68 len
= (unsigned long)p
- (unsigned long)tmp
;
70 memcpy(space
, tmp
, len
);
71 memcpy(space
+ len
, "CREATE#", 8);
72 c_name
->len
= len
+ 7;
73 if(c_name
->len
>= MAX_TRANS_SUFFIX
)
75 while(*p
&& *p
!= '#' && *p
!= ':')
83 name
->len
= len
= (unsigned long)p
- (unsigned long)tmp
;
84 if(len
>= MAX_TRANS_SUFFIX
)
87 memcpy(space
, tmp
, len
);
91 if(res
->count
>= MAX_TRANSLATIONS
||
92 (unsigned long)space
- (unsigned long)res
>= PAGE_SIZE
-2*MAX_TRANS_SUFFIX
)
95 while(*p
&& *p
++ != ':') ;
100 static inline void trans_to_string(struct translations
* trans
, char * buf
, int maxlen
)
104 for(i
= 0; i
< trans
->count
; i
++) {
105 int len
= trans
->name
[i
].len
;
107 memcpy(buf
, trans
->name
[i
].name
, len
);
118 static inline void default_nametrans(char * buf
)
124 for (entry
= transl_names
; *entry
; entry
++) {
126 for(ptr
= *entry
; *ptr
; ptr
++)
129 for(ptr
= *entry
; *ptr
; ptr
++)
138 void nametrans_setup(char * line
)
141 default_trans
= (!line
[0]);
143 /* This can happen at boot time, and there is no chance
144 * to allocate memory at this early stage.
146 strncpy(nametrans_txt
, line
, MAX_DEFAULT_TRANSLEN
);
149 default_nametrans(nametrans_txt
);
150 line
= nametrans_txt
;
152 convert(line
, global_trans
);
154 /* Show what really was recognized after parsing... */
155 trans_to_string(global_trans
, nametrans_txt
, MAX_DEFAULT_TRANSLEN
);
160 /* If the _first_ environment variable is "NAMETRANS", return
161 * a pointer to the list of appendices.
162 * You can set the first environment variable using
163 * 'env - NAMETRANS=... "`env`" command ...'
165 char* env_transl(void)
170 if(current
&& current
->mm
&& (env
= (char*)current
->mm
->env_start
)
171 && get_ds() != get_fs()
172 && current
->mm
->env_end
>=current
->mm
->env_start
+10
173 && !verify_area(VERIFY_READ
,env
,10)) {
174 for(i
=0; i
<10; i
++) {
178 if(c
!= "NAMETRANS="[i
])
186 /* If name has the correct suffix "#keyword=correct_context#",
187 * return position of the suffix, else 0.
189 char *testname(int restricted
, char* name
)
194 struct translations
* trans
;
199 #ifdef CONFIG_TRANS_RESTRICT
200 if(!env
&& restricted
)
203 (void)restricted
; /* inhibit parameter usage warning */
207 while(c
&& c
!= '#') {
216 while (c
&& c
!= '#') {
225 trans
= get_translations(env
);
226 len
= (unsigned long)ptr
- (unsigned long)cut
;
227 for(i
= 0; i
< trans
->count
; i
++)
228 if(trans
->name
[i
].len
== len
) {
229 const char * p1
= cut
;
230 const char * p2
= trans
->name
[i
].name
;
232 while(c
&& c
== *p2
++) {
243 static inline void check_dirty(void)
245 if(translations_dirty
&& default_trans
) {
247 translations_dirty
= 0;
251 struct translations
* get_translations(char * env
)
253 struct translations
* res
;
256 char * env_txt
= (char*)__get_free_page(GFP_KERNEL
);
258 strncpy_from_user(env_txt
, env
, PAGE_SIZE
);
259 res
= (struct translations
*)__get_free_page(GFP_KERNEL
);
260 convert(env_txt
, res
);
261 free_page((unsigned long)env_txt
);
269 int nametrans_dostring(ctl_table
* table
, int write
, struct file
* filp
,
270 void * buffer
, size_t * lenp
)
274 res
= proc_dostring(table
, write
, filp
, buffer
, lenp
);
276 nametrans_setup(nametrans_txt
);
281 int nametrans_string(ctl_table
* table
, int * name
, int nlen
,
282 void * oldval
, size_t * oldlenp
,
283 void * newval
, size_t newlen
, void ** context
)
287 res
= sysctl_string(table
, name
, nlen
, oldval
, oldlenp
, newval
, newlen
, context
);
288 if(!res
&& newval
&& newlen
)
289 nametrans_setup(nametrans_txt
);
294 void init_nametrans(void)
297 global_trans
= (struct translations
*)__get_free_page(GFP_KERNEL
);
299 printk("NAMETRANS: No free memory\n");
302 nametrans_setup(nametrans_txt
);
304 /* Notify user for the default/supplied translations.
305 * Extremely useful for finding translation problems.
307 printk("Nametrans %s\nNametrans %s: %s\n", version
,
308 default_trans
? "default translations" : "external parameter",