diff options
-rw-r--r-- | arch/parisc/kernel/sys_parisc32.c | 141 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall_table.S | 4 |
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 | ||
288 | struct linux32_dirent { | ||
289 | u32 d_ino; | ||
290 | compat_off_t d_off; | ||
291 | u16 d_reclen; | ||
292 | char d_name[1]; | ||
293 | }; | ||
294 | |||
295 | struct old_linux32_dirent { | ||
296 | u32 d_ino; | ||
297 | u32 d_offset; | ||
298 | u16 d_namlen; | ||
299 | char d_name[1]; | ||
300 | }; | ||
301 | |||
302 | struct getdents32_callback { | ||
303 | struct linux32_dirent __user * current_dir; | ||
304 | struct linux32_dirent __user * previous; | ||
305 | int count; | ||
306 | int error; | ||
307 | }; | ||
308 | |||
309 | struct 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))) | ||
315 | static 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 | |||
344 | asmlinkage long | ||
345 | sys32_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 | |||
378 | out_putf: | ||
379 | fput(file); | ||
380 | out: | ||
381 | return error; | ||
382 | } | ||
383 | |||
384 | static 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 | |||
406 | asmlinkage long | ||
407 | sys32_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); | ||
425 | out: | ||
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) |