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) |
