linux_file.c (179651) | linux_file.c (182892) |
---|---|
1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1994-1995 S�ren Schmidt 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include <sys/cdefs.h> |
30__FBSDID("$FreeBSD: head/sys/compat/linux/linux_file.c 179651 2008-06-08 11:09:25Z rdivacky $"); | 30__FBSDID("$FreeBSD: head/sys/compat/linux/linux_file.c 182892 2008-09-09 16:00:17Z rdivacky $"); |
31 32#include "opt_compat.h" 33#include "opt_mac.h" 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/conf.h> 38#include <sys/dirent.h> --- 259 unchanged lines hidden (view full) --- 298struct l_dirent64 { 299 uint64_t d_ino; 300 int64_t d_off; 301 l_ushort d_reclen; 302 u_char d_type; 303 char d_name[LINUX_NAME_MAX + 1]; 304}; 305 | 31 32#include "opt_compat.h" 33#include "opt_mac.h" 34 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/conf.h> 38#include <sys/dirent.h> --- 259 unchanged lines hidden (view full) --- 298struct l_dirent64 { 299 uint64_t d_ino; 300 int64_t d_off; 301 l_ushort d_reclen; 302 u_char d_type; 303 char d_name[LINUX_NAME_MAX + 1]; 304}; 305 |
306#define LINUX_RECLEN(de,namlen) \ 307 ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1)) | 306/* 307 * Linux uses the last byte in the dirent buffer to store d_type, 308 * at least glibc-2.7 requires it. That is why l_dirent is padded with 2 bytes. 309 */ 310#define LINUX_RECLEN(namlen) \ 311 roundup((offsetof(struct l_dirent, d_name) + (namlen) + 2), \ 312 sizeof(l_ulong)) |
308 | 313 |
314#define LINUX_RECLEN64(namlen) \ 315 roundup((offsetof(struct l_dirent64, d_name) + (namlen) + 1), \ 316 sizeof(uint64_t)) 317 318#define LINUX_MAXRECLEN max(LINUX_RECLEN(LINUX_NAME_MAX), \ 319 LINUX_RECLEN64(LINUX_NAME_MAX)) |
|
309#define LINUX_DIRBLKSIZ 512 310 311static int 312getdents_common(struct thread *td, struct linux_getdents64_args *args, 313 int is64bit) 314{ 315 struct dirent *bdp; 316 struct vnode *vp; 317 caddr_t inp, buf; /* BSD-format */ 318 int len, reclen; /* BSD-format */ 319 caddr_t outp; /* Linux-format */ 320 int resid, linuxreclen=0; /* Linux-format */ | 320#define LINUX_DIRBLKSIZ 512 321 322static int 323getdents_common(struct thread *td, struct linux_getdents64_args *args, 324 int is64bit) 325{ 326 struct dirent *bdp; 327 struct vnode *vp; 328 caddr_t inp, buf; /* BSD-format */ 329 int len, reclen; /* BSD-format */ 330 caddr_t outp; /* Linux-format */ 331 int resid, linuxreclen=0; /* Linux-format */ |
332 caddr_t lbuf; /* Linux-format */ |
|
321 struct file *fp; 322 struct uio auio; 323 struct iovec aiov; 324 off_t off; | 333 struct file *fp; 334 struct uio auio; 335 struct iovec aiov; 336 off_t off; |
325 struct l_dirent linux_dirent; 326 struct l_dirent64 linux_dirent64; | 337 struct l_dirent *linux_dirent; 338 struct l_dirent64 *linux_dirent64; |
327 int buflen, error, eofflag, nbytes, justone; 328 u_long *cookies = NULL, *cookiep; 329 int ncookies, vfslocked; 330 331 nbytes = args->count; 332 if (nbytes == 1) { 333 /* readdir(2) case. Always struct dirent. */ 334 if (is64bit) --- 19 unchanged lines hidden (view full) --- 354 return (EINVAL); 355 } 356 357 off = fp->f_offset; 358 359 buflen = max(LINUX_DIRBLKSIZ, nbytes); 360 buflen = min(buflen, MAXBSIZE); 361 buf = malloc(buflen, M_TEMP, M_WAITOK); | 339 int buflen, error, eofflag, nbytes, justone; 340 u_long *cookies = NULL, *cookiep; 341 int ncookies, vfslocked; 342 343 nbytes = args->count; 344 if (nbytes == 1) { 345 /* readdir(2) case. Always struct dirent. */ 346 if (is64bit) --- 19 unchanged lines hidden (view full) --- 366 return (EINVAL); 367 } 368 369 off = fp->f_offset; 370 371 buflen = max(LINUX_DIRBLKSIZ, nbytes); 372 buflen = min(buflen, MAXBSIZE); 373 buf = malloc(buflen, M_TEMP, M_WAITOK); |
374 lbuf = malloc(LINUX_MAXRECLEN, M_TEMP, M_WAITOK | M_ZERO); |
|
362 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 363 364again: 365 aiov.iov_base = buf; 366 aiov.iov_len = buflen; 367 auio.uio_iov = &aiov; 368 auio.uio_iovcnt = 1; 369 auio.uio_rw = UIO_READ; --- 61 unchanged lines hidden (view full) --- 431 } else 432 off += reclen; 433 434 len -= reclen; 435 continue; 436 } 437 438 linuxreclen = (is64bit) | 375 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 376 377again: 378 aiov.iov_base = buf; 379 aiov.iov_len = buflen; 380 auio.uio_iov = &aiov; 381 auio.uio_iovcnt = 1; 382 auio.uio_rw = UIO_READ; --- 61 unchanged lines hidden (view full) --- 444 } else 445 off += reclen; 446 447 len -= reclen; 448 continue; 449 } 450 451 linuxreclen = (is64bit) |
439 ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen) 440 : LINUX_RECLEN(&linux_dirent, bdp->d_namlen); | 452 ? LINUX_RECLEN64(bdp->d_namlen) 453 : LINUX_RECLEN(bdp->d_namlen); |
441 442 if (reclen > len || resid < linuxreclen) { 443 outp++; 444 break; 445 } 446 447 if (justone) { 448 /* readdir(2) case. */ | 454 455 if (reclen > len || resid < linuxreclen) { 456 outp++; 457 break; 458 } 459 460 if (justone) { 461 /* readdir(2) case. */ |
449 linux_dirent.d_ino = bdp->d_fileno; 450 linux_dirent.d_off = (l_off_t)linuxreclen; 451 linux_dirent.d_reclen = (l_ushort)bdp->d_namlen; 452 strcpy(linux_dirent.d_name, bdp->d_name); 453 error = copyout(&linux_dirent, outp, linuxreclen); 454 } else { 455 if (is64bit) { 456 linux_dirent64.d_ino = bdp->d_fileno; 457 linux_dirent64.d_off = (cookiep) 458 ? (l_off_t)*cookiep 459 : (l_off_t)(off + reclen); 460 linux_dirent64.d_reclen = 461 (l_ushort)linuxreclen; 462 linux_dirent64.d_type = bdp->d_type; 463 strcpy(linux_dirent64.d_name, bdp->d_name); 464 error = copyout(&linux_dirent64, outp, 465 linuxreclen); 466 } else { 467 linux_dirent.d_ino = bdp->d_fileno; 468 linux_dirent.d_off = (cookiep) 469 ? (l_off_t)*cookiep 470 : (l_off_t)(off + reclen); 471 linux_dirent.d_reclen = (l_ushort)linuxreclen; 472 strcpy(linux_dirent.d_name, bdp->d_name); 473 error = copyout(&linux_dirent, outp, 474 linuxreclen); 475 } | 462 linux_dirent = (struct l_dirent*)lbuf; 463 linux_dirent->d_ino = bdp->d_fileno; 464 linux_dirent->d_off = (l_off_t)linuxreclen; 465 linux_dirent->d_reclen = (l_ushort)bdp->d_namlen; 466 strlcpy(linux_dirent->d_name, bdp->d_name, 467 linuxreclen - offsetof(struct l_dirent, d_name)); 468 error = copyout(linux_dirent, outp, linuxreclen); |
476 } | 469 } |
470 if (is64bit) { 471 linux_dirent64 = (struct l_dirent64*)lbuf; 472 linux_dirent64->d_ino = bdp->d_fileno; 473 linux_dirent64->d_off = (cookiep) 474 ? (l_off_t)*cookiep 475 : (l_off_t)(off + reclen); 476 linux_dirent64->d_reclen = (l_ushort)linuxreclen; 477 linux_dirent64->d_type = bdp->d_type; 478 strlcpy(linux_dirent64->d_name, bdp->d_name, 479 linuxreclen - offsetof(struct l_dirent64, d_name)); 480 error = copyout(linux_dirent64, outp, linuxreclen); 481 } else if (!justone) { 482 linux_dirent = (struct l_dirent*)lbuf; 483 linux_dirent->d_ino = bdp->d_fileno; 484 linux_dirent->d_off = (cookiep) 485 ? (l_off_t)*cookiep 486 : (l_off_t)(off + reclen); 487 linux_dirent->d_reclen = (l_ushort)linuxreclen; 488 /* 489 * Copy d_type to last byte of l_dirent buffer 490 */ 491 lbuf[linuxreclen-1] = bdp->d_type; 492 strlcpy(linux_dirent->d_name, bdp->d_name, 493 linuxreclen - offsetof(struct l_dirent, d_name)-1); 494 error = copyout(linux_dirent, outp, linuxreclen); 495 } 496 |
|
477 if (error) 478 goto out; 479 480 inp += reclen; 481 if (cookiep) { 482 off = *cookiep++; 483 ncookies--; 484 } else --- 19 unchanged lines hidden (view full) --- 504out: 505 if (cookies) 506 free(cookies, M_TEMP); 507 508 VOP_UNLOCK(vp, 0); 509 VFS_UNLOCK_GIANT(vfslocked); 510 fdrop(fp, td); 511 free(buf, M_TEMP); | 497 if (error) 498 goto out; 499 500 inp += reclen; 501 if (cookiep) { 502 off = *cookiep++; 503 ncookies--; 504 } else --- 19 unchanged lines hidden (view full) --- 524out: 525 if (cookies) 526 free(cookies, M_TEMP); 527 528 VOP_UNLOCK(vp, 0); 529 VFS_UNLOCK_GIANT(vfslocked); 530 fdrop(fp, td); 531 free(buf, M_TEMP); |
532 free(lbuf, M_TEMP); |
|
512 return (error); 513} 514 515int 516linux_getdents(struct thread *td, struct linux_getdents_args *args) 517{ 518 519#ifdef DEBUG --- 986 unchanged lines hidden --- | 533 return (error); 534} 535 536int 537linux_getdents(struct thread *td, struct linux_getdents_args *args) 538{ 539 540#ifdef DEBUG --- 986 unchanged lines hidden --- |