linux_file.c (9313) | linux_file.c (10355) |
---|---|
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 --- 11 unchanged lines hidden (view full) --- 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 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 * | 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 --- 11 unchanged lines hidden (view full) --- 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 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 * $Id: linux_file.c,v 1.2 1995/06/07 21:27:57 sos Exp $ | 28 * $Id: linux_file.c,v 1.1 1995/06/25 17:32:34 sos Exp $ |
29 */ 30 31#include <i386/linux/linux.h> 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/filedesc.h> --- 297 unchanged lines hidden (view full) --- 334 caddr_t outp; /* Linux-format */ 335 int resid, linuxreclen=0; /* Linux-format */ 336 struct file *fp; 337 struct uio auio; 338 struct iovec aiov; 339 struct vattr va; 340 off_t off; 341 struct linux_dirent linux_dirent; | 29 */ 30 31#include <i386/linux/linux.h> 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/fcntl.h> 35#include <sys/file.h> 36#include <sys/filedesc.h> --- 297 unchanged lines hidden (view full) --- 334 caddr_t outp; /* Linux-format */ 335 int resid, linuxreclen=0; /* Linux-format */ 336 struct file *fp; 337 struct uio auio; 338 struct iovec aiov; 339 struct vattr va; 340 off_t off; 341 struct linux_dirent linux_dirent; |
342 int buflen, error, eofflag, nbytes, justone; | 342 int buflen, error, eofflag, nbytes, justone, blockoff; |
343 344#ifdef DEBUG 345 printf("Linux-emul(%d): readdir(%d, *, %d)\n", 346 p->p_pid, args->fd, args->count); 347#endif | 343 344#ifdef DEBUG 345 printf("Linux-emul(%d): readdir(%d, *, %d)\n", 346 p->p_pid, args->fd, args->count); 347#endif |
348 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) | 348 if ((error = getvnode(p->p_fd, args->fd, &fp)) != 0) { |
349 return (error); | 349 return (error); |
350} |
|
350 351 if ((fp->f_flag & FREAD) == 0) 352 return (EBADF); 353 354 vp = (struct vnode *) fp->f_data; 355 356 if (vp->v_type != VDIR) 357 return (EINVAL); 358 | 351 352 if ((fp->f_flag & FREAD) == 0) 353 return (EBADF); 354 355 vp = (struct vnode *) fp->f_data; 356 357 if (vp->v_type != VDIR) 358 return (EINVAL); 359 |
359 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) | 360 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p))) { |
360 return error; | 361 return error; |
362 } |
|
361 362 nbytes = args->count; 363 if (nbytes == 1) { 364 nbytes = sizeof (struct linux_dirent); 365 justone = 1; 366 } 367 else 368 justone = 0; 369 | 363 364 nbytes = args->count; 365 if (nbytes == 1) { 366 nbytes = sizeof (struct linux_dirent); 367 justone = 1; 368 } 369 else 370 justone = 0; 371 |
370 buflen = max(va.va_blocksize, nbytes); | 372 off = fp->f_offset; 373 blockoff = off % va.va_blocksize; 374 buflen = max(va.va_blocksize, (nbytes + blockoff)); |
371 buf = malloc(buflen, M_TEMP, M_WAITOK); 372 VOP_LOCK(vp); | 375 buf = malloc(buflen, M_TEMP, M_WAITOK); 376 VOP_LOCK(vp); |
373 off = fp->f_offset; | |
374again: 375 aiov.iov_base = buf; 376 aiov.iov_len = buflen; 377 auio.uio_iov = &aiov; 378 auio.uio_iovcnt = 1; 379 auio.uio_rw = UIO_READ; 380 auio.uio_segflg = UIO_SYSSPACE; 381 auio.uio_procp = p; 382 auio.uio_resid = buflen; | 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; 383 auio.uio_segflg = UIO_SYSSPACE; 384 auio.uio_procp = p; 385 auio.uio_resid = buflen; |
383 auio.uio_offset = off; | 386 auio.uio_offset = off - (off_t)blockoff; |
384 385 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0); | 387 388 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, (u_long *) 0, 0); |
386 if (error) | 389 if (error) { |
387 goto out; | 390 goto out; |
391} |
|
388 389 inp = buf; | 392 393 inp = buf; |
394 inp += blockoff; |
|
390 outp = (caddr_t) args->dent; 391 resid = nbytes; | 395 outp = (caddr_t) args->dent; 396 resid = nbytes; |
392 if ((len = buflen - auio.uio_resid) == 0) | 397 if ((len = buflen - auio.uio_resid - blockoff) == 0) { |
393 goto eof; | 398 goto eof; |
399 } |
|
394 395 while (len > 0) { | 400 401 while (len > 0) { |
396 reclen = ((struct dirent *) inp)->d_reclen; 397 if (reclen & 3) 398 panic("linux_readdir"); 399 off += reclen; | |
400 bdp = (struct dirent *) inp; | 402 bdp = (struct dirent *) inp; |
403 reclen = bdp->d_reclen; 404 if (reclen & 3) { 405 printf("linux_readdir: reclen=%d\n", reclen); 406 error = EFAULT; 407 goto out; 408 } 409 410 off += reclen; |
|
401 if (bdp->d_fileno == 0) { 402 inp += reclen; | 411 if (bdp->d_fileno == 0) { 412 inp += reclen; |
413 len -= reclen; |
|
403 continue; 404 } 405 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 406 if (reclen > len || resid < linuxreclen) { 407 outp++; 408 break; 409 } 410 linux_dirent.dino = (long) bdp->d_fileno; 411 linux_dirent.doff = (linux_off_t) linuxreclen; 412 linux_dirent.dreclen = (u_short) bdp->d_namlen; 413 strcpy(linux_dirent.dname, bdp->d_name); | 414 continue; 415 } 416 linuxreclen = LINUX_RECLEN(&linux_dirent, bdp->d_namlen); 417 if (reclen > len || resid < linuxreclen) { 418 outp++; 419 break; 420 } 421 linux_dirent.dino = (long) bdp->d_fileno; 422 linux_dirent.doff = (linux_off_t) linuxreclen; 423 linux_dirent.dreclen = (u_short) bdp->d_namlen; 424 strcpy(linux_dirent.dname, bdp->d_name); |
414 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) | 425 if ((error = copyout((caddr_t)&linux_dirent, outp, linuxreclen))) { |
415 goto out; | 426 goto out; |
427 } |
|
416 inp += reclen; 417 outp += linuxreclen; 418 resid -= linuxreclen; 419 len -= reclen; 420 if (justone) 421 break; 422 } 423 424 if (outp == (caddr_t) args->dent) 425 goto again; 426 fp->f_offset = off; 427 428 if (justone) 429 nbytes = resid + linuxreclen; | 428 inp += reclen; 429 outp += linuxreclen; 430 resid -= linuxreclen; 431 len -= reclen; 432 if (justone) 433 break; 434 } 435 436 if (outp == (caddr_t) args->dent) 437 goto again; 438 fp->f_offset = off; 439 440 if (justone) 441 nbytes = resid + linuxreclen; |
442 |
|
430eof: 431 *retval = nbytes - resid; 432out: 433 VOP_UNLOCK(vp); 434 free(buf, M_TEMP); 435 return error; 436} | 443eof: 444 *retval = nbytes - resid; 445out: 446 VOP_UNLOCK(vp); 447 free(buf, M_TEMP); 448 return error; 449} |