nsprpub/pr/src/md/beos/bfile.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/src/md/beos/bfile.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,873 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "primpl.h"
    1.10 +
    1.11 +/*
    1.12 +** Global lock variable used to bracket calls into rusty libraries that
    1.13 +** aren't thread safe (like libc, libX, etc).
    1.14 +*/
    1.15 +static PRLock *_pr_rename_lock = NULL; 
    1.16 +
    1.17 +void
    1.18 +_MD_InitIO (void)
    1.19 +{
    1.20 +}
    1.21 +
    1.22 +PRStatus
    1.23 +_MD_open_dir (_MDDir *md,const char *name)
    1.24 +{
    1.25 +int err;
    1.26 +
    1.27 +	md->d = opendir(name);
    1.28 +	if (!md->d) {
    1.29 +		err = _MD_ERRNO();
    1.30 +		_PR_MD_MAP_OPENDIR_ERROR(err);
    1.31 +		return PR_FAILURE;
    1.32 +	}
    1.33 +	return PR_SUCCESS;
    1.34 +}
    1.35 +
    1.36 +char*
    1.37 +_MD_read_dir (_MDDir *md, PRIntn flags)
    1.38 +{
    1.39 +struct dirent *de;
    1.40 +int err;
    1.41 +
    1.42 +	for (;;) {
    1.43 +		/*
    1.44 +		 * XXX: readdir() is not MT-safe
    1.45 +		 */
    1.46 +		_MD_ERRNO() = 0;
    1.47 +		de = readdir(md->d);
    1.48 +
    1.49 +		if (!de) {
    1.50 +			err = _MD_ERRNO();
    1.51 +			_PR_MD_MAP_READDIR_ERROR(err);
    1.52 +			return 0;
    1.53 +		}
    1.54 +
    1.55 +		if ((flags & PR_SKIP_DOT) &&
    1.56 +		    (de->d_name[0] == '.') && (de->d_name[1] == 0))
    1.57 +			continue;
    1.58 +
    1.59 +		if ((flags & PR_SKIP_DOT_DOT) &&
    1.60 +		    (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
    1.61 +		    (de->d_name[2] == 0))
    1.62 +			continue;
    1.63 +
    1.64 +		if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
    1.65 +			continue;
    1.66 +
    1.67 +		break;
    1.68 +	}
    1.69 +	return de->d_name;
    1.70 +}
    1.71 +
    1.72 +
    1.73 +PRInt32
    1.74 +_MD_close_dir (_MDDir *md)
    1.75 +{
    1.76 +int rv = 0, err;
    1.77 +
    1.78 +	if (md->d) {
    1.79 +		rv = closedir(md->d);
    1.80 +		if (rv == -1) {
    1.81 +			err = _MD_ERRNO();
    1.82 +			_PR_MD_MAP_CLOSEDIR_ERROR(err);
    1.83 +		}
    1.84 +	}
    1.85 +	return(rv);
    1.86 +}
    1.87 +
    1.88 +void
    1.89 +_MD_make_nonblock (PRFileDesc *fd)
    1.90 +{
    1.91 +	int blocking = 1;
    1.92 +	setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
    1.93 +
    1.94 +}
    1.95 +
    1.96 +PRStatus
    1.97 +_MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
    1.98 +{
    1.99 +        int rv;
   1.100 +	
   1.101 +        rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
   1.102 +        if (-1 == rv) {
   1.103 +                PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
   1.104 +                return PR_FAILURE;
   1.105 +        }
   1.106 +        return PR_SUCCESS;
   1.107 +}
   1.108 +
   1.109 +void
   1.110 +_MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
   1.111 +{
   1.112 +	if (imported) {
   1.113 +		fd->secret->inheritable = _PR_TRI_UNKNOWN;
   1.114 +	} else {
   1.115 +		int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
   1.116 +		if (flags == -1) {
   1.117 +			PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
   1.118 +			return;
   1.119 +		}
   1.120 +		fd->secret->inheritable = (flags & FD_CLOEXEC) ? 
   1.121 +			_PR_TRI_TRUE : _PR_TRI_FALSE;
   1.122 +	}
   1.123 +}
   1.124 +
   1.125 +void
   1.126 +_MD_query_fd_inheritable (PRFileDesc *fd)
   1.127 +{
   1.128 +	int flags;
   1.129 +	
   1.130 +	PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
   1.131 +	flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
   1.132 +	PR_ASSERT(-1 != flags);
   1.133 +	fd->secret->inheritable = (flags & FD_CLOEXEC) ?
   1.134 +		_PR_TRI_FALSE : _PR_TRI_TRUE;
   1.135 +}
   1.136 +
   1.137 +PRInt32
   1.138 +_MD_open (const char *name, PRIntn flags, PRIntn mode)
   1.139 +{
   1.140 +	PRInt32 osflags;
   1.141 +	PRInt32 rv, err;
   1.142 +
   1.143 +	if (flags & PR_RDWR) {
   1.144 +		osflags = O_RDWR;
   1.145 +	} else if (flags & PR_WRONLY) {
   1.146 +		osflags = O_WRONLY;
   1.147 +	} else {
   1.148 +		osflags = O_RDONLY;
   1.149 +	}
   1.150 +
   1.151 +	if (flags & PR_EXCL)
   1.152 +		osflags |= O_EXCL;
   1.153 +	if (flags & PR_APPEND)
   1.154 +		osflags |= O_APPEND;
   1.155 +	if (flags & PR_TRUNCATE)
   1.156 +		osflags |= O_TRUNC;
   1.157 +	if (flags & PR_SYNC) {
   1.158 +/* Ummmm.  BeOS doesn't appear to
   1.159 +   support sync in any way shape or
   1.160 +   form. */
   1.161 +		return PR_NOT_IMPLEMENTED_ERROR;
   1.162 +	}
   1.163 +
   1.164 +	/*
   1.165 +	** On creations we hold the 'create' lock in order to enforce
   1.166 +	** the semantics of PR_Rename. (see the latter for more details)
   1.167 +	*/
   1.168 +	if (flags & PR_CREATE_FILE)
   1.169 +	{
   1.170 +		osflags |= O_CREAT ;
   1.171 +		if (NULL !=_pr_rename_lock)
   1.172 +		    PR_Lock(_pr_rename_lock);
   1.173 +	}
   1.174 +
   1.175 +        rv = open(name, osflags, mode);
   1.176 +
   1.177 +        if (rv < 0) {
   1.178 +                err = _MD_ERRNO();
   1.179 +                _PR_MD_MAP_OPEN_ERROR(err);
   1.180 +        }                                                                      
   1.181 +
   1.182 +    if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
   1.183 +        PR_Unlock(_pr_rename_lock);
   1.184 +        return rv;
   1.185 +}
   1.186 +
   1.187 +PRInt32
   1.188 +_MD_close_file (PRInt32 osfd)
   1.189 +{
   1.190 +PRInt32 rv, err;
   1.191 +
   1.192 +	rv = close(osfd);
   1.193 +	if (rv == -1) {
   1.194 +		err = _MD_ERRNO();
   1.195 +		_PR_MD_MAP_CLOSE_ERROR(err);
   1.196 +	}
   1.197 +	return(rv);
   1.198 +}
   1.199 +
   1.200 +PRInt32
   1.201 +_MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
   1.202 +{
   1.203 +    PRInt32 rv, err;
   1.204 +    PRInt32 osfd = fd->secret->md.osfd;
   1.205 +
   1.206 +    rv = read( osfd, buf, amount );
   1.207 +    if (rv < 0) {
   1.208 +	err = _MD_ERRNO();
   1.209 +	_PR_MD_MAP_READ_ERROR(err);
   1.210 +    }
   1.211 +    return(rv);
   1.212 +}
   1.213 +
   1.214 +PRInt32
   1.215 +_MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
   1.216 +{
   1.217 +    PRInt32 rv, err;
   1.218 +    PRInt32 osfd = fd->secret->md.osfd;
   1.219 +
   1.220 +    rv = write( osfd, buf, amount );
   1.221 +
   1.222 +    if( rv < 0 ) {
   1.223 +
   1.224 +	err = _MD_ERRNO();
   1.225 +	_PR_MD_MAP_WRITE_ERROR(err);
   1.226 +    }
   1.227 +    return( rv );
   1.228 +}
   1.229 +
   1.230 +#ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
   1.231 +PRInt32
   1.232 +_MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
   1.233 +	    PRIntervalTime timeout)
   1.234 +{
   1.235 +    return PR_NOT_IMPLEMENTED_ERROR;
   1.236 +}
   1.237 +#endif
   1.238 +
   1.239 +PRInt32
   1.240 +_MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
   1.241 +{
   1.242 +PRInt32 rv, err;
   1.243 +
   1.244 +    rv = lseek (fd->secret->md.osfd, offset, whence);
   1.245 +    if (rv == -1) {
   1.246 +        err = _MD_ERRNO();
   1.247 +	_PR_MD_MAP_LSEEK_ERROR(err);
   1.248 +    }
   1.249 +    return( rv );
   1.250 +}
   1.251 +
   1.252 +PRInt64
   1.253 +_MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
   1.254 +{
   1.255 +PRInt32 rv, err;
   1.256 +
   1.257 +/* According to the BeOS headers, lseek accepts a
   1.258 + * variable of type off_t for the offset, and off_t
   1.259 + * is defined to be a 64-bit value.  So no special
   1.260 + * cracking needs to be done on "offset".
   1.261 + */
   1.262 +
   1.263 +    rv = lseek (fd->secret->md.osfd, offset, whence);
   1.264 +    if (rv == -1) {
   1.265 +        err = _MD_ERRNO();
   1.266 +	_PR_MD_MAP_LSEEK_ERROR(err);
   1.267 +    }
   1.268 +    return( rv );
   1.269 +}
   1.270 +
   1.271 +PRInt32
   1.272 +_MD_fsync (PRFileDesc *fd)
   1.273 +{
   1.274 +PRInt32 rv, err;
   1.275 +
   1.276 +    rv = fsync(fd->secret->md.osfd);
   1.277 +    if (rv == -1) {
   1.278 +	err = _MD_ERRNO();
   1.279 +	_PR_MD_MAP_FSYNC_ERROR(err);
   1.280 +    }
   1.281 +    return(rv);
   1.282 +}
   1.283 +
   1.284 +PRInt32
   1.285 +_MD_delete (const char *name)
   1.286 +{
   1.287 +PRInt32 rv, err;
   1.288 +
   1.289 +    rv = unlink(name);
   1.290 +    if (rv == -1)
   1.291 +    {
   1.292 +	err = _MD_ERRNO();
   1.293 +        _PR_MD_MAP_UNLINK_ERROR(err);
   1.294 +    }
   1.295 +    return (rv);
   1.296 +}
   1.297 +
   1.298 +PRInt32
   1.299 +_MD_getfileinfo (const char *fn, PRFileInfo *info)
   1.300 +{
   1.301 +struct stat sb;
   1.302 +PRInt32 rv, err;
   1.303 +PRInt64 s, s2us;
   1.304 +
   1.305 +	rv = stat(fn, &sb);
   1.306 +	if (rv < 0) {
   1.307 +		err = _MD_ERRNO();
   1.308 +		_PR_MD_MAP_STAT_ERROR(err);
   1.309 +	} else if (info) {
   1.310 +		if (S_IFREG & sb.st_mode)
   1.311 +			info->type = PR_FILE_FILE;
   1.312 +		else if (S_IFDIR & sb.st_mode)
   1.313 +			info->type = PR_FILE_DIRECTORY;
   1.314 +		else
   1.315 +			info->type = PR_FILE_OTHER;
   1.316 +
   1.317 +		/* Must truncate file size for the 32 bit
   1.318 +		   version */
   1.319 +		info->size = (sb.st_size & 0xffffffff);
   1.320 +		LL_I2L(s, sb.st_mtime);
   1.321 +		LL_I2L(s2us, PR_USEC_PER_SEC);
   1.322 +		LL_MUL(s, s, s2us);
   1.323 +		info->modifyTime = s;
   1.324 +		LL_I2L(s, sb.st_ctime);
   1.325 +		LL_MUL(s, s, s2us);
   1.326 +		info->creationTime = s;
   1.327 +	}
   1.328 +	return rv;
   1.329 +}
   1.330 +
   1.331 +PRInt32
   1.332 +_MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
   1.333 +{
   1.334 +struct stat sb;
   1.335 +PRInt32 rv, err;
   1.336 +PRInt64 s, s2us;
   1.337 +
   1.338 +	rv = stat(fn, &sb);
   1.339 +	if (rv < 0) {
   1.340 +		err = _MD_ERRNO();
   1.341 +		_PR_MD_MAP_STAT_ERROR(err);
   1.342 +	} else if (info) {
   1.343 +		if (S_IFREG & sb.st_mode)
   1.344 +			info->type = PR_FILE_FILE;
   1.345 +		else if (S_IFDIR & sb.st_mode)
   1.346 +			info->type = PR_FILE_DIRECTORY;
   1.347 +		else
   1.348 +			info->type = PR_FILE_OTHER;
   1.349 +	
   1.350 +		/* For the 64 bit version we can use
   1.351 +		 * the native st_size without modification
   1.352 +		 */
   1.353 +		info->size = sb.st_size;
   1.354 +		LL_I2L(s, sb.st_mtime);
   1.355 +		LL_I2L(s2us, PR_USEC_PER_SEC);
   1.356 +		LL_MUL(s, s, s2us);
   1.357 +		info->modifyTime = s;
   1.358 +		LL_I2L(s, sb.st_ctime);
   1.359 +		LL_MUL(s, s, s2us);
   1.360 +		info->creationTime = s;
   1.361 +	}
   1.362 +	return rv;
   1.363 +}
   1.364 +
   1.365 +PRInt32
   1.366 +_MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
   1.367 +{
   1.368 +        struct stat sb;
   1.369 +        PRInt64 s, s2us;
   1.370 +        PRInt32 rv, err;
   1.371 +
   1.372 +        rv = fstat(fd->secret->md.osfd, &sb);
   1.373 +        if (rv < 0) {
   1.374 +                        err = _MD_ERRNO();
   1.375 +                        _PR_MD_MAP_FSTAT_ERROR(err);
   1.376 +        } else if (info) {
   1.377 +                if (info) {
   1.378 +                        if (S_IFREG & sb.st_mode)
   1.379 +                                info->type = PR_FILE_FILE ;
   1.380 +                        else if (S_IFDIR & sb.st_mode)
   1.381 +                                info->type = PR_FILE_DIRECTORY;
   1.382 +                        else
   1.383 +                                info->type = PR_FILE_OTHER;
   1.384 +			/* Use lower 32 bits of file size */
   1.385 +                        info->size = ( sb.st_size & 0xffffffff);
   1.386 +                        LL_I2L(s, sb.st_mtime);
   1.387 +                        LL_I2L(s2us, PR_USEC_PER_SEC);
   1.388 +                        LL_MUL(s, s, s2us);
   1.389 +                        info->modifyTime = s;
   1.390 +                        LL_I2L(s, sb.st_ctime);
   1.391 +                        LL_MUL(s, s, s2us);
   1.392 +                        info->creationTime = s;
   1.393 +                }
   1.394 +        }
   1.395 +        return rv;
   1.396 +}
   1.397 +
   1.398 +PRInt32
   1.399 +_MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
   1.400 +{
   1.401 +        struct stat sb;
   1.402 +        PRInt64 s, s2us;
   1.403 +        PRInt32 rv, err;
   1.404 +
   1.405 +        rv = fstat(fd->secret->md.osfd, &sb);
   1.406 +        if (rv < 0) {
   1.407 +                        err = _MD_ERRNO();
   1.408 +                        _PR_MD_MAP_FSTAT_ERROR(err);
   1.409 +        } else if (info) {
   1.410 +                if (info) {
   1.411 +                        if (S_IFREG & sb.st_mode)
   1.412 +                                info->type = PR_FILE_FILE ;
   1.413 +                        else if (S_IFDIR & sb.st_mode)
   1.414 +                                info->type = PR_FILE_DIRECTORY;
   1.415 +                        else
   1.416 +                                info->type = PR_FILE_OTHER;
   1.417 +                        info->size = sb.st_size;
   1.418 +                        LL_I2L(s, sb.st_mtime);
   1.419 +                        LL_I2L(s2us, PR_USEC_PER_SEC);
   1.420 +                        LL_MUL(s, s, s2us);
   1.421 +                        info->modifyTime = s;
   1.422 +                        LL_I2L(s, sb.st_ctime);
   1.423 +                        LL_MUL(s, s, s2us);
   1.424 +                        info->creationTime = s;
   1.425 +                }
   1.426 +        }
   1.427 +        return rv;
   1.428 +}
   1.429 +
   1.430 +PRInt32
   1.431 +_MD_rename (const char *from, const char *to)
   1.432 +{
   1.433 +    PRInt32 rv = -1, err;
   1.434 +
   1.435 +    /*
   1.436 +    ** This is trying to enforce the semantics of WINDOZE' rename
   1.437 +    ** operation. That means one is not allowed to rename over top
   1.438 +    ** of an existing file. Holding a lock across these two function
   1.439 +    ** and the open function is known to be a bad idea, but ....
   1.440 +    */
   1.441 +    if (NULL != _pr_rename_lock)
   1.442 +        PR_Lock(_pr_rename_lock);
   1.443 +    if (0 == access(to, F_OK))
   1.444 +        PR_SetError(PR_FILE_EXISTS_ERROR, 0);
   1.445 +    else
   1.446 +    {
   1.447 +            rv = rename(from, to);
   1.448 +            if (rv < 0) {
   1.449 +                    err = _MD_ERRNO();
   1.450 +                    _PR_MD_MAP_RENAME_ERROR(err);
   1.451 +            }
   1.452 +    }
   1.453 +    if (NULL != _pr_rename_lock)
   1.454 +        PR_Unlock(_pr_rename_lock);
   1.455 +    return rv; 
   1.456 +}
   1.457 +
   1.458 +PRInt32
   1.459 +_MD_access (const char *name, PRIntn how)
   1.460 +{
   1.461 +PRInt32 rv, err;
   1.462 +int checkFlags;
   1.463 +struct stat buf;
   1.464 +
   1.465 +	switch (how) {
   1.466 +		case PR_ACCESS_WRITE_OK:
   1.467 +			checkFlags = S_IWUSR | S_IWGRP | S_IWOTH;
   1.468 +			break;
   1.469 +		
   1.470 +		case PR_ACCESS_READ_OK:
   1.471 +			checkFlags = S_IRUSR | S_IRGRP | S_IROTH;
   1.472 +			break;
   1.473 +		
   1.474 +		case PR_ACCESS_EXISTS:
   1.475 +			/* we don't need to examine st_mode. */
   1.476 +			break;
   1.477 +		
   1.478 +		default:
   1.479 +			PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
   1.480 +			return -1;
   1.481 +	}
   1.482 +
   1.483 +	rv = stat(name, &buf);
   1.484 +	if (rv == 0 && how != PR_ACCESS_EXISTS && (!(buf.st_mode & checkFlags))) {
   1.485 +		PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
   1.486 +		return -1;
   1.487 +	}
   1.488 +
   1.489 +	if (rv < 0) {
   1.490 +		err = _MD_ERRNO();
   1.491 +		_PR_MD_MAP_STAT_ERROR(err);
   1.492 +	}
   1.493 +
   1.494 +	return(rv);
   1.495 +}
   1.496 +
   1.497 +PRInt32
   1.498 +_MD_stat (const char *name, struct stat *buf)
   1.499 +{
   1.500 +    return PR_NOT_IMPLEMENTED_ERROR;
   1.501 +}
   1.502 +
   1.503 +PRInt32
   1.504 +_MD_mkdir (const char *name, PRIntn mode)
   1.505 +{
   1.506 +    status_t rv;
   1.507 +    int err;
   1.508 +
   1.509 +    /*
   1.510 +    ** This lock is used to enforce rename semantics as described
   1.511 +    ** in PR_Rename. Look there for more fun details.
   1.512 +    */
   1.513 +    if (NULL !=_pr_rename_lock)
   1.514 +        PR_Lock(_pr_rename_lock);
   1.515 +
   1.516 +    rv = mkdir(name, mode);
   1.517 +    if (rv < 0) {
   1.518 +	err = _MD_ERRNO();
   1.519 +	_PR_MD_MAP_MKDIR_ERROR(err);
   1.520 +    }
   1.521 +    if (NULL !=_pr_rename_lock)
   1.522 +        PR_Unlock(_pr_rename_lock);
   1.523 +    return rv; 
   1.524 +}
   1.525 +
   1.526 +PRInt32
   1.527 +_MD_rmdir (const char *name)
   1.528 +{
   1.529 +int rv, err;
   1.530 +
   1.531 +        rv = rmdir(name);
   1.532 +        if (rv == -1) {
   1.533 +                        err = _MD_ERRNO();
   1.534 +                        _PR_MD_MAP_RMDIR_ERROR(err);
   1.535 +        }
   1.536 +        return rv;
   1.537 +}
   1.538 +
   1.539 +PRInt32
   1.540 +_MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
   1.541 +{
   1.542 +	PRInt32 rv = 0;
   1.543 +	PRThread *me = _PR_MD_CURRENT_THREAD();
   1.544 +	/*
   1.545 +	 * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
   1.546 +	 */
   1.547 +	fd_set rd, wt, ex;
   1.548 +	PRFileDesc *bottom;
   1.549 +	PRPollDesc *pd, *epd;
   1.550 +	PRInt32 maxfd = -1, ready, err;
   1.551 +	PRIntervalTime remaining, elapsed, start;
   1.552 +
   1.553 +	struct timeval tv, *tvp = NULL;
   1.554 +
   1.555 +	if (_PR_PENDING_INTERRUPT(me))
   1.556 +	{
   1.557 +		me->flags &= ~_PR_INTERRUPT;
   1.558 +		PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
   1.559 +		return -1;
   1.560 +	}
   1.561 +
   1.562 +	if (0 == npds) {
   1.563 +		PR_Sleep(timeout);
   1.564 +		return rv;
   1.565 +	}
   1.566 +
   1.567 +	FD_ZERO(&rd);
   1.568 +	FD_ZERO(&wt);
   1.569 +	FD_ZERO(&ex);
   1.570 +
   1.571 +	ready = 0;
   1.572 +	for (pd = pds, epd = pd + npds; pd < epd; pd++)
   1.573 +	{
   1.574 +		PRInt16 in_flags_read = 0, in_flags_write = 0;
   1.575 +		PRInt16 out_flags_read = 0, out_flags_write = 0; 
   1.576 +		
   1.577 +		if ((NULL != pd->fd) && (0 != pd->in_flags))
   1.578 +		{
   1.579 +			if (pd->in_flags & PR_POLL_READ)
   1.580 +			{
   1.581 +				in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
   1.582 +			}
   1.583 +			if (pd->in_flags & PR_POLL_WRITE)
   1.584 +			{
   1.585 +				in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
   1.586 +			}
   1.587 +			if ((0 != (in_flags_read & out_flags_read))
   1.588 +			    || (0 != (in_flags_write & out_flags_write)))
   1.589 +			{
   1.590 +				/* this one's ready right now */
   1.591 +				if (0 == ready)
   1.592 +				{
   1.593 +					/*
   1.594 +					 * We will have to return without calling the
   1.595 +					 * system poll/select function.  So zero the
   1.596 +					 * out_flags fields of all the poll descriptors
   1.597 +					 * before this one. 
   1.598 +					 */
   1.599 +					PRPollDesc *prev;
   1.600 +					for (prev = pds; prev < pd; prev++)
   1.601 +					{
   1.602 +						prev->out_flags = 0;
   1.603 +					}
   1.604 +				}
   1.605 +				ready += 1;
   1.606 +				pd->out_flags = out_flags_read | out_flags_write;
   1.607 +			}
   1.608 +			else
   1.609 +			{
   1.610 +				pd->out_flags = 0;  /* pre-condition */
   1.611 +				
   1.612 +				/* make sure this is an NSPR supported stack */
   1.613 +				bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   1.614 +				PR_ASSERT(NULL != bottom);  /* what to do about that? */
   1.615 +				if ((NULL != bottom)
   1.616 +				    && (_PR_FILEDESC_OPEN == bottom->secret->state))
   1.617 +				{
   1.618 +					if (0 == ready)
   1.619 +					{
   1.620 +						PRInt32 osfd = bottom->secret->md.osfd; 
   1.621 +						if (osfd > maxfd) maxfd = osfd;
   1.622 +						if (in_flags_read & PR_POLL_READ)
   1.623 +						{
   1.624 +							pd->out_flags |= _PR_POLL_READ_SYS_READ;
   1.625 +							FD_SET(osfd, &rd);
   1.626 +						}
   1.627 +						if (in_flags_read & PR_POLL_WRITE)
   1.628 +						{
   1.629 +							pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
   1.630 +							FD_SET(osfd, &wt);
   1.631 +						}
   1.632 +						if (in_flags_write & PR_POLL_READ)
   1.633 +						{
   1.634 +							pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
   1.635 +							FD_SET(osfd, &rd);
   1.636 +						}
   1.637 +						if (in_flags_write & PR_POLL_WRITE)
   1.638 +						{
   1.639 +							pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
   1.640 +							FD_SET(osfd, &wt);
   1.641 +						}
   1.642 +						if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
   1.643 +					}
   1.644 +				}
   1.645 +				else
   1.646 +				{
   1.647 +					if (0 == ready)
   1.648 +					{
   1.649 +						PRPollDesc *prev;
   1.650 +						for (prev = pds; prev < pd; prev++)
   1.651 +						{
   1.652 +							prev->out_flags = 0;
   1.653 +						}
   1.654 +					}
   1.655 +					ready += 1;  /* this will cause an abrupt return */
   1.656 +					pd->out_flags = PR_POLL_NVAL;  /* bogii */
   1.657 +				}
   1.658 +			}
   1.659 +		}
   1.660 +		else
   1.661 +		{
   1.662 +			pd->out_flags = 0;
   1.663 +		}
   1.664 +	}
   1.665 +
   1.666 +	if (0 != ready) return ready;  /* no need to block */
   1.667 +
   1.668 +	remaining = timeout;
   1.669 +	start = PR_IntervalNow(); 
   1.670 +
   1.671 + retry:
   1.672 +	if (timeout != PR_INTERVAL_NO_TIMEOUT)
   1.673 +	{
   1.674 +		PRInt32 ticksPerSecond = PR_TicksPerSecond();
   1.675 +		tv.tv_sec = remaining / ticksPerSecond;
   1.676 +		tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
   1.677 +		tvp = &tv;
   1.678 +	}
   1.679 +	
   1.680 +	ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
   1.681 +	
   1.682 +	if (ready == -1 && errno == EINTR)
   1.683 +	{
   1.684 +		if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
   1.685 +		else
   1.686 +		{
   1.687 +			elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
   1.688 +			if (elapsed > timeout) ready = 0;  /* timed out */
   1.689 +			else
   1.690 +			{
   1.691 +				remaining = timeout - elapsed;
   1.692 +				goto retry; 
   1.693 +			}
   1.694 +		}
   1.695 +	} 
   1.696 +
   1.697 +	/*
   1.698 +	** Now to unravel the select sets back into the client's poll
   1.699 +	** descriptor list. Is this possibly an area for pissing away
   1.700 +	** a few cycles or what?
   1.701 +	*/
   1.702 +	if (ready > 0)
   1.703 +	{
   1.704 +		ready = 0;
   1.705 +		for (pd = pds, epd = pd + npds; pd < epd; pd++)
   1.706 +		{
   1.707 +			PRInt16 out_flags = 0;
   1.708 +			if ((NULL != pd->fd) && (0 != pd->in_flags))
   1.709 +			{
   1.710 +				PRInt32 osfd;
   1.711 +				bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   1.712 +				PR_ASSERT(NULL != bottom);
   1.713 +				
   1.714 +				osfd = bottom->secret->md.osfd; 
   1.715 +				
   1.716 +				if (FD_ISSET(osfd, &rd))
   1.717 +				{
   1.718 +					if (pd->out_flags & _PR_POLL_READ_SYS_READ)
   1.719 +						out_flags |= PR_POLL_READ;
   1.720 +					if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
   1.721 +						out_flags |= PR_POLL_WRITE;
   1.722 +				}
   1.723 +				if (FD_ISSET(osfd, &wt))
   1.724 +				{
   1.725 +					if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
   1.726 +						out_flags |= PR_POLL_READ;
   1.727 +					if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
   1.728 +						out_flags |= PR_POLL_WRITE;
   1.729 +				}
   1.730 +				if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
   1.731 +
   1.732 +/* Workaround for nonblocking connects under net_server */
   1.733 +#ifndef BONE_VERSION 		
   1.734 +				if (out_flags)
   1.735 +				{
   1.736 +					/* check if it is a pending connect */
   1.737 +					int i = 0, j = 0;
   1.738 +					PR_Lock( _connectLock );
   1.739 +					for( i = 0; i < connectCount; i++ ) 
   1.740 +					{
   1.741 +						if(connectList[i].osfd == osfd)
   1.742 +						{
   1.743 +							int connectError;
   1.744 +							int connectResult;
   1.745 +					
   1.746 +							connectResult = connect(connectList[i].osfd,
   1.747 +							                        &connectList[i].addr,
   1.748 +							                        connectList[i].addrlen);
   1.749 +							connectError = errno;
   1.750 +					
   1.751 +							if(connectResult < 0 ) 
   1.752 +							{
   1.753 +								if(connectError == EINTR || connectError == EWOULDBLOCK ||
   1.754 +					  		   connectError == EINPROGRESS || connectError == EALREADY)
   1.755 +								{
   1.756 +									break;
   1.757 +								}
   1.758 +							}
   1.759 +					
   1.760 +							if(i == (connectCount - 1))
   1.761 +							{
   1.762 +								connectList[i].osfd = -1;
   1.763 +							} else {
   1.764 +								for(j = i; j < connectCount; j++ )
   1.765 +								{
   1.766 +									memcpy( &connectList[j], &connectList[j+1],
   1.767 +									        sizeof(connectList[j]));
   1.768 +								}
   1.769 +							}
   1.770 +							connectCount--;
   1.771 +					
   1.772 +							bottom->secret->md.connectReturnValue = connectResult;
   1.773 +							bottom->secret->md.connectReturnError = connectError;
   1.774 +							bottom->secret->md.connectValueValid = PR_TRUE;
   1.775 +							break;
   1.776 +						}
   1.777 +					}
   1.778 +					PR_Unlock( _connectLock );
   1.779 +				}
   1.780 +#endif
   1.781 +			}
   1.782 +			pd->out_flags = out_flags;
   1.783 +			if (out_flags) ready++;
   1.784 +		}
   1.785 +		PR_ASSERT(ready > 0);
   1.786 +	}
   1.787 +	else if (ready < 0)
   1.788 +	{ 
   1.789 +		err = _MD_ERRNO();
   1.790 +		if (err == EBADF)
   1.791 +		{
   1.792 +			/* Find the bad fds */
   1.793 +			ready = 0;
   1.794 +			for (pd = pds, epd = pd + npds; pd < epd; pd++)
   1.795 +			{
   1.796 +				pd->out_flags = 0;
   1.797 +				if ((NULL != pd->fd) && (0 != pd->in_flags))
   1.798 +				{
   1.799 +					bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
   1.800 +					if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
   1.801 +					{
   1.802 +						pd->out_flags = PR_POLL_NVAL;
   1.803 +						ready++;
   1.804 +					}
   1.805 +				}
   1.806 +			}
   1.807 +			PR_ASSERT(ready > 0);
   1.808 +		}
   1.809 +		else _PR_MD_MAP_SELECT_ERROR(err);
   1.810 +	}
   1.811 +	
   1.812 +	return ready;
   1.813 +}  /* _MD_pr_poll */
   1.814 +
   1.815 +/*
   1.816 + * File locking.
   1.817 + */
   1.818 +
   1.819 +PRStatus
   1.820 +_MD_lockfile (PRInt32 osfd)
   1.821 +{
   1.822 +    PRInt32 rv;
   1.823 +    struct flock linfo;
   1.824 +
   1.825 +    linfo.l_type = 
   1.826 +    linfo.l_whence = SEEK_SET;
   1.827 +    linfo.l_start = 0;
   1.828 +    linfo.l_len = 0;
   1.829 +
   1.830 +    rv = fcntl(osfd, F_SETLKW, &linfo);
   1.831 +    if (rv == 0)
   1.832 +	return PR_SUCCESS;
   1.833 +
   1.834 +    _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
   1.835 +    return PR_FAILURE;
   1.836 +}
   1.837 +
   1.838 +PRStatus
   1.839 +_MD_tlockfile (PRInt32 osfd)
   1.840 +{
   1.841 +    PRInt32 rv;
   1.842 +    struct flock linfo;
   1.843 +
   1.844 +    linfo.l_type = 
   1.845 +    linfo.l_whence = SEEK_SET;
   1.846 +    linfo.l_start = 0;
   1.847 +    linfo.l_len = 0;
   1.848 +
   1.849 +    rv = fcntl(osfd, F_SETLK, &linfo);
   1.850 +    if (rv == 0)
   1.851 +	return PR_SUCCESS;
   1.852 +
   1.853 +    _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
   1.854 +    return PR_FAILURE;
   1.855 +}
   1.856 +
   1.857 +PRStatus
   1.858 +_MD_unlockfile (PRInt32 osfd)
   1.859 +{
   1.860 +    PRInt32 rv;
   1.861 +    struct flock linfo;
   1.862 +
   1.863 +    linfo.l_type = 
   1.864 +    linfo.l_whence = SEEK_SET;
   1.865 +    linfo.l_start = 0;
   1.866 +    linfo.l_len = 0;
   1.867 +
   1.868 +    rv = fcntl(osfd, F_UNLCK, &linfo);
   1.869 +
   1.870 +    if (rv == 0)
   1.871 +	return PR_SUCCESS;
   1.872 +
   1.873 +    _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
   1.874 +    return PR_FAILURE;
   1.875 +}
   1.876 +

mercurial