elf2coff isn't a generic tool for all linux ports
[linux-2.6/linux-mips.git] / fs / nametrans.c
blob15c98ed7072940641ea0aecc43c4bcaaa606c953
1 /*
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
12 * context suffixes.
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>
20 #include <linux/mm.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,
32 #endif
33 #ifdef CONFIG_TR_KERNNAME
34 "kname=", CONFIG_KERNNAME,
35 #endif
36 #ifdef CONFIG_TR_KERNTYPE
37 "ktype=", CONFIG_KERNTYPE,
38 #endif
39 #ifdef CONFIG_TR_MACHINE
40 "machine=", system_utsname.machine,
41 #endif
42 #ifdef CONFIG_TR_SYSNAME
43 "system=", system_utsname.sysname,
44 #endif
45 0, 0
48 /* Convert and do syntax checking. */
49 static void convert(char * txt, struct translations * res)
51 char * tmp = txt;
52 char * space = (char*)res + sizeof(struct translations);
54 res->count = 0;
55 while(*tmp) {
56 struct qstr * name = &res->name[res->count];
57 struct qstr * c_name = &res->c_name[res->count];
58 int len;
59 char * p = tmp;
61 if(*p++ != '#')
62 goto next;
63 while(*p && *p != '=' && *p != ':')
64 p++;
65 if(*p != '=')
66 goto next;
67 p++;
68 len = (unsigned long)p - (unsigned long)tmp;
69 c_name->name = space;
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)
74 goto next;
75 while(*p && *p != '#' && *p != ':')
76 p++;
77 if(*p != '#')
78 goto next;
79 p++;
80 if(*p != ':' && *p)
81 goto next;
82 space += len + 8;
83 name->len = len = (unsigned long)p - (unsigned long)tmp;
84 if(len >= MAX_TRANS_SUFFIX)
85 goto next;
86 name->name = space;
87 memcpy(space, tmp, len);
88 space[len] = '\0';
89 space += len + 1;
90 res->count++;
91 if(res->count >= MAX_TRANSLATIONS ||
92 (unsigned long)space - (unsigned long)res >= PAGE_SIZE-2*MAX_TRANS_SUFFIX)
93 return;
94 next:
95 while(*p && *p++ != ':') ;
96 tmp = p;
100 static inline void trans_to_string(struct translations * trans, char * buf, int maxlen)
102 int i;
104 for(i = 0; i < trans->count; i++) {
105 int len = trans->name[i].len;
106 if(len < maxlen) {
107 memcpy(buf, trans->name[i].name, len);
108 buf += len;
109 maxlen -= len;
110 *buf++ = ':';
111 maxlen--;
114 buf--;
115 *buf = '\0';
118 static inline void default_nametrans(char * buf)
120 char * res = buf;
121 char ** entry;
122 char * ptr;
124 for (entry = transl_names; *entry; entry++) {
125 *res++ = '#';
126 for(ptr = *entry; *ptr; ptr++)
127 *res++ = *ptr;
128 entry++;
129 for(ptr = *entry; *ptr; ptr++)
130 *res++ = *ptr;
131 *res++ = '#';
132 *res++ = ':';
134 res--;
135 *res = '\0';
138 void nametrans_setup(char * line)
140 if(line) {
141 default_trans = (!line[0]);
142 if(!global_trans) {
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);
147 } else {
148 if(default_trans) {
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)
167 char* env;
168 int i;
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++) {
175 char c;
177 get_user(c, env++);
178 if(c != "NAMETRANS="[i])
179 return 0;
181 return env;
183 return 0;
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)
191 char * ptr = name;
192 char * cut;
193 char * env;
194 struct translations * trans;
195 int i, len;
196 char c, tmp;
198 env = env_transl();
199 #ifdef CONFIG_TRANS_RESTRICT
200 if(!env && restricted)
201 goto done;
202 #else
203 (void)restricted; /* inhibit parameter usage warning */
204 #endif
205 if(get_user(c, ptr))
206 goto done;
207 while(c && c != '#') {
208 ptr++;
209 __get_user(c, ptr);
211 if(!c)
212 goto done;
213 cut = ptr++;
214 if(get_user(c, ptr))
215 goto done;
216 while (c && c != '#') {
217 ptr++;
218 get_user(c, ptr);
220 if(!c)
221 goto done;
222 get_user(tmp, ptr);
223 if(tmp)
224 goto done;
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;
231 get_user(c, p1);
232 while(c && c == *p2++) {
233 p1++;
234 get_user(c, p1);
236 if(!c)
237 return cut;
239 done:
240 return NULL;
243 static inline void check_dirty(void)
245 if(translations_dirty && default_trans) {
246 nametrans_setup("");
247 translations_dirty = 0;
251 struct translations * get_translations(char * env)
253 struct translations * res;
255 if(env) {
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);
262 } else {
263 check_dirty();
264 res = global_trans;
266 return res;
269 int nametrans_dostring(ctl_table * table, int write, struct file * filp,
270 void * buffer, size_t * lenp)
272 int res;
273 check_dirty();
274 res = proc_dostring(table, write, filp, buffer, lenp);
275 if(!res && write)
276 nametrans_setup(nametrans_txt);
278 return res;
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)
285 int res;
286 check_dirty();
287 res = sysctl_string(table, name, nlen, oldval, oldlenp, newval, newlen, context);
288 if(!res && newval && newlen)
289 nametrans_setup(nametrans_txt);
291 return res;
294 void init_nametrans(void)
296 if(!global_trans)
297 global_trans = (struct translations*)__get_free_page(GFP_KERNEL);
298 if(!global_trans) {
299 printk("NAMETRANS: No free memory\n");
300 return;
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",
309 nametrans_txt);