aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorKyle McMartin <kyle@parisc-linux.org>2007-06-29 03:38:10 -0400
committerKyle McMartin <kyle@minerva.i.cabal.ca>2007-08-27 00:29:25 -0400
commit88a79078f9ca7d84736799605ff9d9e9545f18e7 (patch)
treeeea5c07f7179bf9dc4943b0d9a998556a8ddf2a9 /arch
parent1eb51c362d5e7b3e2cc741d87872aa4fc867de42 (diff)
[PARISC] Use compat_sys_getdents
Switch to using the generic compat_sys_getdents instead of a homebrew one. Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/parisc/kernel/sys_parisc32.c141
-rw-r--r--arch/parisc/kernel/syscall_table.S4
2 files changed, 1 insertions, 144 deletions
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
index bb23ff71c28e..2989c6682bf6 100644
--- a/arch/parisc/kernel/sys_parisc32.c
+++ b/arch/parisc/kernel/sys_parisc32.c
@@ -285,147 +285,6 @@ int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
285 return err; 285 return err;
286} 286}
287 287
288struct linux32_dirent {
289 u32 d_ino;
290 compat_off_t d_off;
291 u16 d_reclen;
292 char d_name[1];
293};
294
295struct old_linux32_dirent {
296 u32 d_ino;
297 u32 d_offset;
298 u16 d_namlen;
299 char d_name[1];
300};
301
302struct getdents32_callback {
303 struct linux32_dirent __user * current_dir;
304 struct linux32_dirent __user * previous;
305 int count;
306 int error;
307};
308
309struct readdir32_callback {
310 struct old_linux32_dirent __user * dirent;
311 int count;
312};
313
314#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
315static int filldir32 (void *__buf, const char *name, int namlen,
316 loff_t offset, u64 ino, unsigned int d_type)
317{
318 struct linux32_dirent __user * dirent;
319 struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
320 int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, 4);
321 u32 d_ino;
322
323 buf->error = -EINVAL; /* only used if we fail.. */
324 if (reclen > buf->count)
325 return -EINVAL;
326 d_ino = ino;
327 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
328 return -EOVERFLOW;
329 dirent = buf->previous;
330 if (dirent)
331 put_user(offset, &dirent->d_off);
332 dirent = buf->current_dir;
333 buf->previous = dirent;
334 put_user(d_ino, &dirent->d_ino);
335 put_user(reclen, &dirent->d_reclen);
336 copy_to_user(dirent->d_name, name, namlen);
337 put_user(0, dirent->d_name + namlen);
338 dirent = ((void __user *)dirent) + reclen;
339 buf->current_dir = dirent;
340 buf->count -= reclen;
341 return 0;
342}
343
344asmlinkage long
345sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
346{
347 struct file * file;
348 struct linux32_dirent __user * lastdirent;
349 struct getdents32_callback buf;
350 int error;
351
352 error = -EFAULT;
353 if (!access_ok(VERIFY_WRITE, dirent, count))
354 goto out;
355
356 error = -EBADF;
357 file = fget(fd);
358 if (!file)
359 goto out;
360
361 buf.current_dir = (struct linux32_dirent __user *) dirent;
362 buf.previous = NULL;
363 buf.count = count;
364 buf.error = 0;
365
366 error = vfs_readdir(file, filldir32, &buf);
367 if (error < 0)
368 goto out_putf;
369 error = buf.error;
370 lastdirent = buf.previous;
371 if (lastdirent) {
372 if (put_user(file->f_pos, &lastdirent->d_off))
373 error = -EFAULT;
374 else
375 error = count - buf.count;
376 }
377
378out_putf:
379 fput(file);
380out:
381 return error;
382}
383
384static int fillonedir32(void * __buf, const char * name, int namlen,
385 loff_t offset, u64 ino, unsigned int d_type)
386{
387 struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
388 struct old_linux32_dirent __user * dirent;
389 u32 d_ino;
390
391 if (buf->count)
392 return -EINVAL;
393 d_ino = ino;
394 if (sizeof(d_ino) < sizeof(ino) && d_ino != ino)
395 return -EOVERFLOW;
396 buf->count++;
397 dirent = buf->dirent;
398 put_user(d_ino, &dirent->d_ino);
399 put_user(offset, &dirent->d_offset);
400 put_user(namlen, &dirent->d_namlen);
401 copy_to_user(dirent->d_name, name, namlen);
402 put_user(0, dirent->d_name + namlen);
403 return 0;
404}
405
406asmlinkage long
407sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
408{
409 int error;
410 struct file * file;
411 struct readdir32_callback buf;
412
413 error = -EBADF;
414 file = fget(fd);
415 if (!file)
416 goto out;
417
418 buf.count = 0;
419 buf.dirent = dirent;
420
421 error = vfs_readdir(file, fillonedir32, &buf);
422 if (error >= 0)
423 error = buf.count;
424 fput(file);
425out:
426 return error;
427}
428
429/*** copied from mips64 ***/ 288/*** copied from mips64 ***/
430/* 289/*
431 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 290 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 627f3c28ad8c..2540786a970f 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -222,9 +222,7 @@
222 ENTRY_SAME(setfsgid) 222 ENTRY_SAME(setfsgid)
223 /* I think this might work */ 223 /* I think this might work */
224 ENTRY_SAME(llseek) /* 140 */ 224 ENTRY_SAME(llseek) /* 140 */
225 /* struct linux_dirent has longs, like 'unsigned long d_ino' which 225 ENTRY_COMP(getdents)
226 * almost definitely should be 'ino_t d_ino' but it's too late now */
227 ENTRY_DIFF(getdents)
228 /* it is POSSIBLE that select will be OK because even though fd_set 226 /* it is POSSIBLE that select will be OK because even though fd_set
229 * contains longs, the macros and sizes are clever. */ 227 * contains longs, the macros and sizes are clever. */
230 ENTRY_COMP(select) 228 ENTRY_COMP(select)