2 * fs/proc/omirr.c - online mirror support
4 * (C) 1997 Thomas Schoebel-Theuer
7 #include <linux/string.h>
10 #include <linux/omirr.h>
11 #include <asm/uaccess.h>
13 static int nr_omirr_open
= 0;
14 static int cleared_flag
= 0;
16 static char * buffer
= NULL
;
17 static int read_pos
, write_pos
;
18 static int clip_pos
, max_pos
;
19 static DECLARE_WAIT_QUEUE_HEAD(read_wait
);
20 static DECLARE_WAIT_QUEUE_HEAD(write_wait
);
22 static /*inline*/ int reserve_write_space(int len
)
24 int rest
= max_pos
- write_pos
;
31 while(read_pos
> write_pos
&& read_pos
<= write_pos
+len
) {
34 interruptible_sleep_on(&write_wait
);
39 static /*inline*/ void write_space(int len
)
42 wake_up_interruptible(&read_wait
);
45 static /*inline*/ int reserve_read_space(int len
)
47 int rest
= clip_pos
- read_pos
;
56 while(read_pos
== write_pos
) {
57 interruptible_sleep_on(&read_wait
);
59 rest
= write_pos
- read_pos
;
60 if(rest
> 0 && rest
< len
)
65 static /*inline*/ void read_space(int len
)
68 if(read_pos
>= clip_pos
) {
72 wake_up_interruptible(&write_wait
);
75 static /*inline*/ void init_buffer(char * initxt
)
77 int len
= initxt
? strlen(initxt
) : 0;
80 buffer
= (char*)__get_free_page(GFP_USER
);
81 max_pos
= clip_pos
= PAGE_SIZE
;
83 read_pos
= write_pos
= 0;
84 memcpy(buffer
, initxt
, len
);
88 static int omirr_open(struct inode
* inode
, struct file
* file
)
98 static int omirr_release(struct inode
* inode
, struct file
* file
)
105 static long omirr_read(struct inode
* inode
, struct file
* file
,
106 char * buf
, unsigned long count
)
115 if(!buf
|| count
< 0)
118 error
= verify_area(VERIFY_WRITE
, buf
, count
);
123 if((file
->f_flags
& O_NONBLOCK
) && read_pos
== write_pos
)
126 error
= len
= reserve_read_space(count
);
127 tmp
= buffer
+ read_pos
;
129 put_user(*tmp
++, buf
++);
137 int compute_name(struct dentry
* entry
, char * buf
)
145 len
= compute_name(entry
->d_parent
, buf
);
149 memcpy(buf
+len
, entry
->d_name
, entry
->d_len
);
150 return len
+ entry
->d_len
;
153 int _omirr_print(struct dentry
* ent1
, struct dentry
* ent2
,
154 struct qstr
* suffix
, const char * fmt
,
155 va_list args1
, va_list args2
)
157 int count
= strlen(fmt
) + 10; /* estimate */
158 const char * tmp
= fmt
;
165 while(*tmp
&& *tmp
++ != '%') ;
168 char * str
= va_arg(args1
, char*);
169 count
+= strlen(str
);
171 (void)va_arg(args1
, int);
172 count
+= 8; /* estimate */
177 struct dentry
* dent
= ent1
;
178 while(dent
&& !IS_ROOT(dent
)) {
179 count
+= dent
->d_len
+ 1;
180 dent
= dent
->d_parent
;
185 while(dent
&& !IS_ROOT(dent
)) {
186 count
+= dent
->d_len
+ 1;
187 dent
= dent
->d_parent
;
192 count
+= suffix
->len
+ 1;
195 if((nr_omirr_open
| cleared_flag
) && reserve_write_space(count
)) {
197 res
= vsprintf(buffer
+write_pos
+4, fmt
, args2
) + 4;
199 printk("omirr: format estimate was wrong\n");
201 res
+= compute_name(ent1
, buffer
+write_pos
+res
);
203 buffer
[write_pos
+res
++] = '\0';
204 res
+= compute_name(ent2
, buffer
+write_pos
+res
);
207 buffer
[write_pos
+res
++] = '/';
208 memcpy(buffer
+write_pos
+res
,
209 suffix
->name
, suffix
->len
);
212 buffer
[write_pos
+res
++] = '\0';
213 buffer
[write_pos
+res
++] = '\n';
215 sprintf(lenbuf
, "%04d", res
);
216 memcpy(buffer
+write_pos
, lenbuf
, 4);
220 init_buffer("0007 Z\n");
228 int omirr_print(struct dentry
* ent1
, struct dentry
* ent2
,
229 struct qstr
* suffix
, const char * fmt
, ...)
231 va_list args1
, args2
;
234 /* I don't know whether I could make a simple copy of the va_list,
235 * so for the safe way...
237 va_start(args1
, fmt
);
238 va_start(args2
, fmt
);
239 res
= _omirr_print(ent1
, ent2
, suffix
, fmt
, args1
, args2
);
245 int omirr_printall(struct inode
* inode
, const char * fmt
, ...)
248 struct dentry
* tmp
= inode
->i_dentry
;
251 va_list args1
, args2
;
252 va_start(args1
, fmt
);
253 va_start(args2
, fmt
);
254 res
+= _omirr_print(tmp
, NULL
, NULL
, fmt
, args1
, args2
);
258 } while(tmp
!= inode
->i_dentry
);
262 static struct file_operations omirr_operations
= {
263 NULL
, /* omirr_lseek */
265 NULL
, /* omirr_write */
266 NULL
, /* omirr_readdir */
267 NULL
, /* omirr_select */
268 NULL
, /* omirr_ioctl */
275 NULL
, /* check_media_change */
276 NULL
/* revalidate */
279 struct inode_operations proc_omirr_inode_operations
= {
291 NULL
, /* follow_link */
293 NULL
, /* writepage */
296 NULL
, /* permission */