1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1994 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <unistd.h> 30 #include <sys/types.h> 31 #include <sys/dirent.h> 32 #include <sys/syscall.h> 33 #include <sys/param.h> 34 #include <sys/errno.h> 35 36 #define ALIGN 4 37 38 extern int errno; 39 40 struct n_dirent{ 41 unsigned long d_ino; 42 long d_off; 43 unsigned short d_reclen; 44 char d_name[1]; 45 }; 46 47 48 int getdents(fd, buf, bytes) 49 int fd; 50 char *buf; 51 int bytes; 52 { 53 return(bc_getdents(fd, buf, bytes)); 54 } 55 56 57 int bc_getdents(fd, buf, bytes) 58 int fd; 59 char *buf; 60 int bytes; 61 { 62 int ret, nbytes; 63 char *nbuf; 64 struct dirent *dir; 65 struct n_dirent *ndir; 66 int count=0; 67 off_t last_off; 68 69 if (buf == (char *)0 || buf == (char *)-1) { 70 errno = EFAULT; 71 return(-1); 72 } 73 74 nbytes = bytes; /* buffer can only be as large as user expects */ 75 76 if ((nbuf = (char *)malloc(nbytes)) == NULL) { 77 return(-1); 78 } 79 80 if ((ret = _syscall(SYS_getdents, fd, nbuf, nbytes)) == -1) { 81 free(nbuf); 82 return(ret); 83 } 84 85 86 dir = (struct dirent *)buf; 87 ndir = (struct n_dirent *)nbuf; /* source directory format */ 88 89 while ((((int)(((char *)dir) + sizeof(struct n_dirent) + 90 strlen(ndir->d_name) + ALIGN) & ~(ALIGN - 1)) < 91 (int)(buf + bytes)) && 92 ((char *)ndir + sizeof(struct n_dirent) <= (nbuf + ret))) { 93 dir->d_off = ndir->d_off; 94 dir->d_fileno = ndir->d_ino; /* NOT VALID */ 95 dir->d_namlen = strlen(ndir->d_name); 96 dir->d_reclen = (short)((sizeof(struct dirent) - MAXNAMLEN + 97 dir->d_namlen + ALIGN) & -ALIGN); 98 strncpy(dir->d_name, ndir->d_name, dir->d_namlen); 99 dir->d_name[dir->d_namlen] = '\0'; 100 count += dir->d_reclen; 101 last_off = ndir->d_off; 102 dir = (struct dirent *)((char *)dir + 103 ((int)( dir->d_reclen))); 104 ndir = (struct n_dirent *)((char *)ndir + 105 ((int)(ndir->d_reclen))); 106 } 107 108 /* 109 * Seek to the next entry in the directory. If all entries 110 * in ndir were not copied to dir, the next getdents syscall 111 * will start reading from there. 112 */ 113 (void)lseek(fd, last_off, SEEK_SET); 114 free(nbuf); 115 return(count); 116 } 117