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 +