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

authored by Kyle McMartin and committed by Kyle McMartin 88a79078 1eb51c36

+1 -144
-141
arch/parisc/kernel/sys_parisc32.c
··· 285 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 288 /*** copied from mips64 ***/ 430 289 /* 431 290 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
+1 -3
arch/parisc/kernel/syscall_table.S
··· 222 222 ENTRY_SAME(setfsgid) 223 223 /* I think this might work */ 224 224 ENTRY_SAME(llseek) /* 140 */ 225 - /* struct linux_dirent has longs, like 'unsigned long d_ino' which 226 - * almost definitely should be 'ino_t d_ino' but it's too late now */ 227 - ENTRY_DIFF(getdents) 225 + ENTRY_COMP(getdents) 228 226 /* it is POSSIBLE that select will be OK because even though fd_set 229 227 * contains longs, the macros and sizes are clever. */ 230 228 ENTRY_COMP(select)