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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "primpl.h"
michael@0 7
michael@0 8 /*
michael@0 9 ** Global lock variable used to bracket calls into rusty libraries that
michael@0 10 ** aren't thread safe (like libc, libX, etc).
michael@0 11 */
michael@0 12 static PRLock *_pr_rename_lock = NULL;
michael@0 13
michael@0 14 void
michael@0 15 _MD_InitIO (void)
michael@0 16 {
michael@0 17 }
michael@0 18
michael@0 19 PRStatus
michael@0 20 _MD_open_dir (_MDDir *md,const char *name)
michael@0 21 {
michael@0 22 int err;
michael@0 23
michael@0 24 md->d = opendir(name);
michael@0 25 if (!md->d) {
michael@0 26 err = _MD_ERRNO();
michael@0 27 _PR_MD_MAP_OPENDIR_ERROR(err);
michael@0 28 return PR_FAILURE;
michael@0 29 }
michael@0 30 return PR_SUCCESS;
michael@0 31 }
michael@0 32
michael@0 33 char*
michael@0 34 _MD_read_dir (_MDDir *md, PRIntn flags)
michael@0 35 {
michael@0 36 struct dirent *de;
michael@0 37 int err;
michael@0 38
michael@0 39 for (;;) {
michael@0 40 /*
michael@0 41 * XXX: readdir() is not MT-safe
michael@0 42 */
michael@0 43 _MD_ERRNO() = 0;
michael@0 44 de = readdir(md->d);
michael@0 45
michael@0 46 if (!de) {
michael@0 47 err = _MD_ERRNO();
michael@0 48 _PR_MD_MAP_READDIR_ERROR(err);
michael@0 49 return 0;
michael@0 50 }
michael@0 51
michael@0 52 if ((flags & PR_SKIP_DOT) &&
michael@0 53 (de->d_name[0] == '.') && (de->d_name[1] == 0))
michael@0 54 continue;
michael@0 55
michael@0 56 if ((flags & PR_SKIP_DOT_DOT) &&
michael@0 57 (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
michael@0 58 (de->d_name[2] == 0))
michael@0 59 continue;
michael@0 60
michael@0 61 if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
michael@0 62 continue;
michael@0 63
michael@0 64 break;
michael@0 65 }
michael@0 66 return de->d_name;
michael@0 67 }
michael@0 68
michael@0 69
michael@0 70 PRInt32
michael@0 71 _MD_close_dir (_MDDir *md)
michael@0 72 {
michael@0 73 int rv = 0, err;
michael@0 74
michael@0 75 if (md->d) {
michael@0 76 rv = closedir(md->d);
michael@0 77 if (rv == -1) {
michael@0 78 err = _MD_ERRNO();
michael@0 79 _PR_MD_MAP_CLOSEDIR_ERROR(err);
michael@0 80 }
michael@0 81 }
michael@0 82 return(rv);
michael@0 83 }
michael@0 84
michael@0 85 void
michael@0 86 _MD_make_nonblock (PRFileDesc *fd)
michael@0 87 {
michael@0 88 int blocking = 1;
michael@0 89 setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
michael@0 90
michael@0 91 }
michael@0 92
michael@0 93 PRStatus
michael@0 94 _MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
michael@0 95 {
michael@0 96 int rv;
michael@0 97
michael@0 98 rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
michael@0 99 if (-1 == rv) {
michael@0 100 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
michael@0 101 return PR_FAILURE;
michael@0 102 }
michael@0 103 return PR_SUCCESS;
michael@0 104 }
michael@0 105
michael@0 106 void
michael@0 107 _MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
michael@0 108 {
michael@0 109 if (imported) {
michael@0 110 fd->secret->inheritable = _PR_TRI_UNKNOWN;
michael@0 111 } else {
michael@0 112 int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
michael@0 113 if (flags == -1) {
michael@0 114 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
michael@0 115 return;
michael@0 116 }
michael@0 117 fd->secret->inheritable = (flags & FD_CLOEXEC) ?
michael@0 118 _PR_TRI_TRUE : _PR_TRI_FALSE;
michael@0 119 }
michael@0 120 }
michael@0 121
michael@0 122 void
michael@0 123 _MD_query_fd_inheritable (PRFileDesc *fd)
michael@0 124 {
michael@0 125 int flags;
michael@0 126
michael@0 127 PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
michael@0 128 flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
michael@0 129 PR_ASSERT(-1 != flags);
michael@0 130 fd->secret->inheritable = (flags & FD_CLOEXEC) ?
michael@0 131 _PR_TRI_FALSE : _PR_TRI_TRUE;
michael@0 132 }
michael@0 133
michael@0 134 PRInt32
michael@0 135 _MD_open (const char *name, PRIntn flags, PRIntn mode)
michael@0 136 {
michael@0 137 PRInt32 osflags;
michael@0 138 PRInt32 rv, err;
michael@0 139
michael@0 140 if (flags & PR_RDWR) {
michael@0 141 osflags = O_RDWR;
michael@0 142 } else if (flags & PR_WRONLY) {
michael@0 143 osflags = O_WRONLY;
michael@0 144 } else {
michael@0 145 osflags = O_RDONLY;
michael@0 146 }
michael@0 147
michael@0 148 if (flags & PR_EXCL)
michael@0 149 osflags |= O_EXCL;
michael@0 150 if (flags & PR_APPEND)
michael@0 151 osflags |= O_APPEND;
michael@0 152 if (flags & PR_TRUNCATE)
michael@0 153 osflags |= O_TRUNC;
michael@0 154 if (flags & PR_SYNC) {
michael@0 155 /* Ummmm. BeOS doesn't appear to
michael@0 156 support sync in any way shape or
michael@0 157 form. */
michael@0 158 return PR_NOT_IMPLEMENTED_ERROR;
michael@0 159 }
michael@0 160
michael@0 161 /*
michael@0 162 ** On creations we hold the 'create' lock in order to enforce
michael@0 163 ** the semantics of PR_Rename. (see the latter for more details)
michael@0 164 */
michael@0 165 if (flags & PR_CREATE_FILE)
michael@0 166 {
michael@0 167 osflags |= O_CREAT ;
michael@0 168 if (NULL !=_pr_rename_lock)
michael@0 169 PR_Lock(_pr_rename_lock);
michael@0 170 }
michael@0 171
michael@0 172 rv = open(name, osflags, mode);
michael@0 173
michael@0 174 if (rv < 0) {
michael@0 175 err = _MD_ERRNO();
michael@0 176 _PR_MD_MAP_OPEN_ERROR(err);
michael@0 177 }
michael@0 178
michael@0 179 if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
michael@0 180 PR_Unlock(_pr_rename_lock);
michael@0 181 return rv;
michael@0 182 }
michael@0 183
michael@0 184 PRInt32
michael@0 185 _MD_close_file (PRInt32 osfd)
michael@0 186 {
michael@0 187 PRInt32 rv, err;
michael@0 188
michael@0 189 rv = close(osfd);
michael@0 190 if (rv == -1) {
michael@0 191 err = _MD_ERRNO();
michael@0 192 _PR_MD_MAP_CLOSE_ERROR(err);
michael@0 193 }
michael@0 194 return(rv);
michael@0 195 }
michael@0 196
michael@0 197 PRInt32
michael@0 198 _MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
michael@0 199 {
michael@0 200 PRInt32 rv, err;
michael@0 201 PRInt32 osfd = fd->secret->md.osfd;
michael@0 202
michael@0 203 rv = read( osfd, buf, amount );
michael@0 204 if (rv < 0) {
michael@0 205 err = _MD_ERRNO();
michael@0 206 _PR_MD_MAP_READ_ERROR(err);
michael@0 207 }
michael@0 208 return(rv);
michael@0 209 }
michael@0 210
michael@0 211 PRInt32
michael@0 212 _MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
michael@0 213 {
michael@0 214 PRInt32 rv, err;
michael@0 215 PRInt32 osfd = fd->secret->md.osfd;
michael@0 216
michael@0 217 rv = write( osfd, buf, amount );
michael@0 218
michael@0 219 if( rv < 0 ) {
michael@0 220
michael@0 221 err = _MD_ERRNO();
michael@0 222 _PR_MD_MAP_WRITE_ERROR(err);
michael@0 223 }
michael@0 224 return( rv );
michael@0 225 }
michael@0 226
michael@0 227 #ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
michael@0 228 PRInt32
michael@0 229 _MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
michael@0 230 PRIntervalTime timeout)
michael@0 231 {
michael@0 232 return PR_NOT_IMPLEMENTED_ERROR;
michael@0 233 }
michael@0 234 #endif
michael@0 235
michael@0 236 PRInt32
michael@0 237 _MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
michael@0 238 {
michael@0 239 PRInt32 rv, err;
michael@0 240
michael@0 241 rv = lseek (fd->secret->md.osfd, offset, whence);
michael@0 242 if (rv == -1) {
michael@0 243 err = _MD_ERRNO();
michael@0 244 _PR_MD_MAP_LSEEK_ERROR(err);
michael@0 245 }
michael@0 246 return( rv );
michael@0 247 }
michael@0 248
michael@0 249 PRInt64
michael@0 250 _MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
michael@0 251 {
michael@0 252 PRInt32 rv, err;
michael@0 253
michael@0 254 /* According to the BeOS headers, lseek accepts a
michael@0 255 * variable of type off_t for the offset, and off_t
michael@0 256 * is defined to be a 64-bit value. So no special
michael@0 257 * cracking needs to be done on "offset".
michael@0 258 */
michael@0 259
michael@0 260 rv = lseek (fd->secret->md.osfd, offset, whence);
michael@0 261 if (rv == -1) {
michael@0 262 err = _MD_ERRNO();
michael@0 263 _PR_MD_MAP_LSEEK_ERROR(err);
michael@0 264 }
michael@0 265 return( rv );
michael@0 266 }
michael@0 267
michael@0 268 PRInt32
michael@0 269 _MD_fsync (PRFileDesc *fd)
michael@0 270 {
michael@0 271 PRInt32 rv, err;
michael@0 272
michael@0 273 rv = fsync(fd->secret->md.osfd);
michael@0 274 if (rv == -1) {
michael@0 275 err = _MD_ERRNO();
michael@0 276 _PR_MD_MAP_FSYNC_ERROR(err);
michael@0 277 }
michael@0 278 return(rv);
michael@0 279 }
michael@0 280
michael@0 281 PRInt32
michael@0 282 _MD_delete (const char *name)
michael@0 283 {
michael@0 284 PRInt32 rv, err;
michael@0 285
michael@0 286 rv = unlink(name);
michael@0 287 if (rv == -1)
michael@0 288 {
michael@0 289 err = _MD_ERRNO();
michael@0 290 _PR_MD_MAP_UNLINK_ERROR(err);
michael@0 291 }
michael@0 292 return (rv);
michael@0 293 }
michael@0 294
michael@0 295 PRInt32
michael@0 296 _MD_getfileinfo (const char *fn, PRFileInfo *info)
michael@0 297 {
michael@0 298 struct stat sb;
michael@0 299 PRInt32 rv, err;
michael@0 300 PRInt64 s, s2us;
michael@0 301
michael@0 302 rv = stat(fn, &sb);
michael@0 303 if (rv < 0) {
michael@0 304 err = _MD_ERRNO();
michael@0 305 _PR_MD_MAP_STAT_ERROR(err);
michael@0 306 } else if (info) {
michael@0 307 if (S_IFREG & sb.st_mode)
michael@0 308 info->type = PR_FILE_FILE;
michael@0 309 else if (S_IFDIR & sb.st_mode)
michael@0 310 info->type = PR_FILE_DIRECTORY;
michael@0 311 else
michael@0 312 info->type = PR_FILE_OTHER;
michael@0 313
michael@0 314 /* Must truncate file size for the 32 bit
michael@0 315 version */
michael@0 316 info->size = (sb.st_size & 0xffffffff);
michael@0 317 LL_I2L(s, sb.st_mtime);
michael@0 318 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 319 LL_MUL(s, s, s2us);
michael@0 320 info->modifyTime = s;
michael@0 321 LL_I2L(s, sb.st_ctime);
michael@0 322 LL_MUL(s, s, s2us);
michael@0 323 info->creationTime = s;
michael@0 324 }
michael@0 325 return rv;
michael@0 326 }
michael@0 327
michael@0 328 PRInt32
michael@0 329 _MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
michael@0 330 {
michael@0 331 struct stat sb;
michael@0 332 PRInt32 rv, err;
michael@0 333 PRInt64 s, s2us;
michael@0 334
michael@0 335 rv = stat(fn, &sb);
michael@0 336 if (rv < 0) {
michael@0 337 err = _MD_ERRNO();
michael@0 338 _PR_MD_MAP_STAT_ERROR(err);
michael@0 339 } else if (info) {
michael@0 340 if (S_IFREG & sb.st_mode)
michael@0 341 info->type = PR_FILE_FILE;
michael@0 342 else if (S_IFDIR & sb.st_mode)
michael@0 343 info->type = PR_FILE_DIRECTORY;
michael@0 344 else
michael@0 345 info->type = PR_FILE_OTHER;
michael@0 346
michael@0 347 /* For the 64 bit version we can use
michael@0 348 * the native st_size without modification
michael@0 349 */
michael@0 350 info->size = sb.st_size;
michael@0 351 LL_I2L(s, sb.st_mtime);
michael@0 352 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 353 LL_MUL(s, s, s2us);
michael@0 354 info->modifyTime = s;
michael@0 355 LL_I2L(s, sb.st_ctime);
michael@0 356 LL_MUL(s, s, s2us);
michael@0 357 info->creationTime = s;
michael@0 358 }
michael@0 359 return rv;
michael@0 360 }
michael@0 361
michael@0 362 PRInt32
michael@0 363 _MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
michael@0 364 {
michael@0 365 struct stat sb;
michael@0 366 PRInt64 s, s2us;
michael@0 367 PRInt32 rv, err;
michael@0 368
michael@0 369 rv = fstat(fd->secret->md.osfd, &sb);
michael@0 370 if (rv < 0) {
michael@0 371 err = _MD_ERRNO();
michael@0 372 _PR_MD_MAP_FSTAT_ERROR(err);
michael@0 373 } else if (info) {
michael@0 374 if (info) {
michael@0 375 if (S_IFREG & sb.st_mode)
michael@0 376 info->type = PR_FILE_FILE ;
michael@0 377 else if (S_IFDIR & sb.st_mode)
michael@0 378 info->type = PR_FILE_DIRECTORY;
michael@0 379 else
michael@0 380 info->type = PR_FILE_OTHER;
michael@0 381 /* Use lower 32 bits of file size */
michael@0 382 info->size = ( sb.st_size & 0xffffffff);
michael@0 383 LL_I2L(s, sb.st_mtime);
michael@0 384 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 385 LL_MUL(s, s, s2us);
michael@0 386 info->modifyTime = s;
michael@0 387 LL_I2L(s, sb.st_ctime);
michael@0 388 LL_MUL(s, s, s2us);
michael@0 389 info->creationTime = s;
michael@0 390 }
michael@0 391 }
michael@0 392 return rv;
michael@0 393 }
michael@0 394
michael@0 395 PRInt32
michael@0 396 _MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
michael@0 397 {
michael@0 398 struct stat sb;
michael@0 399 PRInt64 s, s2us;
michael@0 400 PRInt32 rv, err;
michael@0 401
michael@0 402 rv = fstat(fd->secret->md.osfd, &sb);
michael@0 403 if (rv < 0) {
michael@0 404 err = _MD_ERRNO();
michael@0 405 _PR_MD_MAP_FSTAT_ERROR(err);
michael@0 406 } else if (info) {
michael@0 407 if (info) {
michael@0 408 if (S_IFREG & sb.st_mode)
michael@0 409 info->type = PR_FILE_FILE ;
michael@0 410 else if (S_IFDIR & sb.st_mode)
michael@0 411 info->type = PR_FILE_DIRECTORY;
michael@0 412 else
michael@0 413 info->type = PR_FILE_OTHER;
michael@0 414 info->size = sb.st_size;
michael@0 415 LL_I2L(s, sb.st_mtime);
michael@0 416 LL_I2L(s2us, PR_USEC_PER_SEC);
michael@0 417 LL_MUL(s, s, s2us);
michael@0 418 info->modifyTime = s;
michael@0 419 LL_I2L(s, sb.st_ctime);
michael@0 420 LL_MUL(s, s, s2us);
michael@0 421 info->creationTime = s;
michael@0 422 }
michael@0 423 }
michael@0 424 return rv;
michael@0 425 }
michael@0 426
michael@0 427 PRInt32
michael@0 428 _MD_rename (const char *from, const char *to)
michael@0 429 {
michael@0 430 PRInt32 rv = -1, err;
michael@0 431
michael@0 432 /*
michael@0 433 ** This is trying to enforce the semantics of WINDOZE' rename
michael@0 434 ** operation. That means one is not allowed to rename over top
michael@0 435 ** of an existing file. Holding a lock across these two function
michael@0 436 ** and the open function is known to be a bad idea, but ....
michael@0 437 */
michael@0 438 if (NULL != _pr_rename_lock)
michael@0 439 PR_Lock(_pr_rename_lock);
michael@0 440 if (0 == access(to, F_OK))
michael@0 441 PR_SetError(PR_FILE_EXISTS_ERROR, 0);
michael@0 442 else
michael@0 443 {
michael@0 444 rv = rename(from, to);
michael@0 445 if (rv < 0) {
michael@0 446 err = _MD_ERRNO();
michael@0 447 _PR_MD_MAP_RENAME_ERROR(err);
michael@0 448 }
michael@0 449 }
michael@0 450 if (NULL != _pr_rename_lock)
michael@0 451 PR_Unlock(_pr_rename_lock);
michael@0 452 return rv;
michael@0 453 }
michael@0 454
michael@0 455 PRInt32
michael@0 456 _MD_access (const char *name, PRIntn how)
michael@0 457 {
michael@0 458 PRInt32 rv, err;
michael@0 459 int checkFlags;
michael@0 460 struct stat buf;
michael@0 461
michael@0 462 switch (how) {
michael@0 463 case PR_ACCESS_WRITE_OK:
michael@0 464 checkFlags = S_IWUSR | S_IWGRP | S_IWOTH;
michael@0 465 break;
michael@0 466
michael@0 467 case PR_ACCESS_READ_OK:
michael@0 468 checkFlags = S_IRUSR | S_IRGRP | S_IROTH;
michael@0 469 break;
michael@0 470
michael@0 471 case PR_ACCESS_EXISTS:
michael@0 472 /* we don't need to examine st_mode. */
michael@0 473 break;
michael@0 474
michael@0 475 default:
michael@0 476 PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
michael@0 477 return -1;
michael@0 478 }
michael@0 479
michael@0 480 rv = stat(name, &buf);
michael@0 481 if (rv == 0 && how != PR_ACCESS_EXISTS && (!(buf.st_mode & checkFlags))) {
michael@0 482 PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
michael@0 483 return -1;
michael@0 484 }
michael@0 485
michael@0 486 if (rv < 0) {
michael@0 487 err = _MD_ERRNO();
michael@0 488 _PR_MD_MAP_STAT_ERROR(err);
michael@0 489 }
michael@0 490
michael@0 491 return(rv);
michael@0 492 }
michael@0 493
michael@0 494 PRInt32
michael@0 495 _MD_stat (const char *name, struct stat *buf)
michael@0 496 {
michael@0 497 return PR_NOT_IMPLEMENTED_ERROR;
michael@0 498 }
michael@0 499
michael@0 500 PRInt32
michael@0 501 _MD_mkdir (const char *name, PRIntn mode)
michael@0 502 {
michael@0 503 status_t rv;
michael@0 504 int err;
michael@0 505
michael@0 506 /*
michael@0 507 ** This lock is used to enforce rename semantics as described
michael@0 508 ** in PR_Rename. Look there for more fun details.
michael@0 509 */
michael@0 510 if (NULL !=_pr_rename_lock)
michael@0 511 PR_Lock(_pr_rename_lock);
michael@0 512
michael@0 513 rv = mkdir(name, mode);
michael@0 514 if (rv < 0) {
michael@0 515 err = _MD_ERRNO();
michael@0 516 _PR_MD_MAP_MKDIR_ERROR(err);
michael@0 517 }
michael@0 518 if (NULL !=_pr_rename_lock)
michael@0 519 PR_Unlock(_pr_rename_lock);
michael@0 520 return rv;
michael@0 521 }
michael@0 522
michael@0 523 PRInt32
michael@0 524 _MD_rmdir (const char *name)
michael@0 525 {
michael@0 526 int rv, err;
michael@0 527
michael@0 528 rv = rmdir(name);
michael@0 529 if (rv == -1) {
michael@0 530 err = _MD_ERRNO();
michael@0 531 _PR_MD_MAP_RMDIR_ERROR(err);
michael@0 532 }
michael@0 533 return rv;
michael@0 534 }
michael@0 535
michael@0 536 PRInt32
michael@0 537 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
michael@0 538 {
michael@0 539 PRInt32 rv = 0;
michael@0 540 PRThread *me = _PR_MD_CURRENT_THREAD();
michael@0 541 /*
michael@0 542 * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
michael@0 543 */
michael@0 544 fd_set rd, wt, ex;
michael@0 545 PRFileDesc *bottom;
michael@0 546 PRPollDesc *pd, *epd;
michael@0 547 PRInt32 maxfd = -1, ready, err;
michael@0 548 PRIntervalTime remaining, elapsed, start;
michael@0 549
michael@0 550 struct timeval tv, *tvp = NULL;
michael@0 551
michael@0 552 if (_PR_PENDING_INTERRUPT(me))
michael@0 553 {
michael@0 554 me->flags &= ~_PR_INTERRUPT;
michael@0 555 PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
michael@0 556 return -1;
michael@0 557 }
michael@0 558
michael@0 559 if (0 == npds) {
michael@0 560 PR_Sleep(timeout);
michael@0 561 return rv;
michael@0 562 }
michael@0 563
michael@0 564 FD_ZERO(&rd);
michael@0 565 FD_ZERO(&wt);
michael@0 566 FD_ZERO(&ex);
michael@0 567
michael@0 568 ready = 0;
michael@0 569 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 570 {
michael@0 571 PRInt16 in_flags_read = 0, in_flags_write = 0;
michael@0 572 PRInt16 out_flags_read = 0, out_flags_write = 0;
michael@0 573
michael@0 574 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 575 {
michael@0 576 if (pd->in_flags & PR_POLL_READ)
michael@0 577 {
michael@0 578 in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
michael@0 579 }
michael@0 580 if (pd->in_flags & PR_POLL_WRITE)
michael@0 581 {
michael@0 582 in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
michael@0 583 }
michael@0 584 if ((0 != (in_flags_read & out_flags_read))
michael@0 585 || (0 != (in_flags_write & out_flags_write)))
michael@0 586 {
michael@0 587 /* this one's ready right now */
michael@0 588 if (0 == ready)
michael@0 589 {
michael@0 590 /*
michael@0 591 * We will have to return without calling the
michael@0 592 * system poll/select function. So zero the
michael@0 593 * out_flags fields of all the poll descriptors
michael@0 594 * before this one.
michael@0 595 */
michael@0 596 PRPollDesc *prev;
michael@0 597 for (prev = pds; prev < pd; prev++)
michael@0 598 {
michael@0 599 prev->out_flags = 0;
michael@0 600 }
michael@0 601 }
michael@0 602 ready += 1;
michael@0 603 pd->out_flags = out_flags_read | out_flags_write;
michael@0 604 }
michael@0 605 else
michael@0 606 {
michael@0 607 pd->out_flags = 0; /* pre-condition */
michael@0 608
michael@0 609 /* make sure this is an NSPR supported stack */
michael@0 610 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 611 PR_ASSERT(NULL != bottom); /* what to do about that? */
michael@0 612 if ((NULL != bottom)
michael@0 613 && (_PR_FILEDESC_OPEN == bottom->secret->state))
michael@0 614 {
michael@0 615 if (0 == ready)
michael@0 616 {
michael@0 617 PRInt32 osfd = bottom->secret->md.osfd;
michael@0 618 if (osfd > maxfd) maxfd = osfd;
michael@0 619 if (in_flags_read & PR_POLL_READ)
michael@0 620 {
michael@0 621 pd->out_flags |= _PR_POLL_READ_SYS_READ;
michael@0 622 FD_SET(osfd, &rd);
michael@0 623 }
michael@0 624 if (in_flags_read & PR_POLL_WRITE)
michael@0 625 {
michael@0 626 pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
michael@0 627 FD_SET(osfd, &wt);
michael@0 628 }
michael@0 629 if (in_flags_write & PR_POLL_READ)
michael@0 630 {
michael@0 631 pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
michael@0 632 FD_SET(osfd, &rd);
michael@0 633 }
michael@0 634 if (in_flags_write & PR_POLL_WRITE)
michael@0 635 {
michael@0 636 pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
michael@0 637 FD_SET(osfd, &wt);
michael@0 638 }
michael@0 639 if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
michael@0 640 }
michael@0 641 }
michael@0 642 else
michael@0 643 {
michael@0 644 if (0 == ready)
michael@0 645 {
michael@0 646 PRPollDesc *prev;
michael@0 647 for (prev = pds; prev < pd; prev++)
michael@0 648 {
michael@0 649 prev->out_flags = 0;
michael@0 650 }
michael@0 651 }
michael@0 652 ready += 1; /* this will cause an abrupt return */
michael@0 653 pd->out_flags = PR_POLL_NVAL; /* bogii */
michael@0 654 }
michael@0 655 }
michael@0 656 }
michael@0 657 else
michael@0 658 {
michael@0 659 pd->out_flags = 0;
michael@0 660 }
michael@0 661 }
michael@0 662
michael@0 663 if (0 != ready) return ready; /* no need to block */
michael@0 664
michael@0 665 remaining = timeout;
michael@0 666 start = PR_IntervalNow();
michael@0 667
michael@0 668 retry:
michael@0 669 if (timeout != PR_INTERVAL_NO_TIMEOUT)
michael@0 670 {
michael@0 671 PRInt32 ticksPerSecond = PR_TicksPerSecond();
michael@0 672 tv.tv_sec = remaining / ticksPerSecond;
michael@0 673 tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
michael@0 674 tvp = &tv;
michael@0 675 }
michael@0 676
michael@0 677 ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
michael@0 678
michael@0 679 if (ready == -1 && errno == EINTR)
michael@0 680 {
michael@0 681 if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
michael@0 682 else
michael@0 683 {
michael@0 684 elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
michael@0 685 if (elapsed > timeout) ready = 0; /* timed out */
michael@0 686 else
michael@0 687 {
michael@0 688 remaining = timeout - elapsed;
michael@0 689 goto retry;
michael@0 690 }
michael@0 691 }
michael@0 692 }
michael@0 693
michael@0 694 /*
michael@0 695 ** Now to unravel the select sets back into the client's poll
michael@0 696 ** descriptor list. Is this possibly an area for pissing away
michael@0 697 ** a few cycles or what?
michael@0 698 */
michael@0 699 if (ready > 0)
michael@0 700 {
michael@0 701 ready = 0;
michael@0 702 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 703 {
michael@0 704 PRInt16 out_flags = 0;
michael@0 705 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 706 {
michael@0 707 PRInt32 osfd;
michael@0 708 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 709 PR_ASSERT(NULL != bottom);
michael@0 710
michael@0 711 osfd = bottom->secret->md.osfd;
michael@0 712
michael@0 713 if (FD_ISSET(osfd, &rd))
michael@0 714 {
michael@0 715 if (pd->out_flags & _PR_POLL_READ_SYS_READ)
michael@0 716 out_flags |= PR_POLL_READ;
michael@0 717 if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
michael@0 718 out_flags |= PR_POLL_WRITE;
michael@0 719 }
michael@0 720 if (FD_ISSET(osfd, &wt))
michael@0 721 {
michael@0 722 if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
michael@0 723 out_flags |= PR_POLL_READ;
michael@0 724 if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
michael@0 725 out_flags |= PR_POLL_WRITE;
michael@0 726 }
michael@0 727 if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
michael@0 728
michael@0 729 /* Workaround for nonblocking connects under net_server */
michael@0 730 #ifndef BONE_VERSION
michael@0 731 if (out_flags)
michael@0 732 {
michael@0 733 /* check if it is a pending connect */
michael@0 734 int i = 0, j = 0;
michael@0 735 PR_Lock( _connectLock );
michael@0 736 for( i = 0; i < connectCount; i++ )
michael@0 737 {
michael@0 738 if(connectList[i].osfd == osfd)
michael@0 739 {
michael@0 740 int connectError;
michael@0 741 int connectResult;
michael@0 742
michael@0 743 connectResult = connect(connectList[i].osfd,
michael@0 744 &connectList[i].addr,
michael@0 745 connectList[i].addrlen);
michael@0 746 connectError = errno;
michael@0 747
michael@0 748 if(connectResult < 0 )
michael@0 749 {
michael@0 750 if(connectError == EINTR || connectError == EWOULDBLOCK ||
michael@0 751 connectError == EINPROGRESS || connectError == EALREADY)
michael@0 752 {
michael@0 753 break;
michael@0 754 }
michael@0 755 }
michael@0 756
michael@0 757 if(i == (connectCount - 1))
michael@0 758 {
michael@0 759 connectList[i].osfd = -1;
michael@0 760 } else {
michael@0 761 for(j = i; j < connectCount; j++ )
michael@0 762 {
michael@0 763 memcpy( &connectList[j], &connectList[j+1],
michael@0 764 sizeof(connectList[j]));
michael@0 765 }
michael@0 766 }
michael@0 767 connectCount--;
michael@0 768
michael@0 769 bottom->secret->md.connectReturnValue = connectResult;
michael@0 770 bottom->secret->md.connectReturnError = connectError;
michael@0 771 bottom->secret->md.connectValueValid = PR_TRUE;
michael@0 772 break;
michael@0 773 }
michael@0 774 }
michael@0 775 PR_Unlock( _connectLock );
michael@0 776 }
michael@0 777 #endif
michael@0 778 }
michael@0 779 pd->out_flags = out_flags;
michael@0 780 if (out_flags) ready++;
michael@0 781 }
michael@0 782 PR_ASSERT(ready > 0);
michael@0 783 }
michael@0 784 else if (ready < 0)
michael@0 785 {
michael@0 786 err = _MD_ERRNO();
michael@0 787 if (err == EBADF)
michael@0 788 {
michael@0 789 /* Find the bad fds */
michael@0 790 ready = 0;
michael@0 791 for (pd = pds, epd = pd + npds; pd < epd; pd++)
michael@0 792 {
michael@0 793 pd->out_flags = 0;
michael@0 794 if ((NULL != pd->fd) && (0 != pd->in_flags))
michael@0 795 {
michael@0 796 bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
michael@0 797 if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
michael@0 798 {
michael@0 799 pd->out_flags = PR_POLL_NVAL;
michael@0 800 ready++;
michael@0 801 }
michael@0 802 }
michael@0 803 }
michael@0 804 PR_ASSERT(ready > 0);
michael@0 805 }
michael@0 806 else _PR_MD_MAP_SELECT_ERROR(err);
michael@0 807 }
michael@0 808
michael@0 809 return ready;
michael@0 810 } /* _MD_pr_poll */
michael@0 811
michael@0 812 /*
michael@0 813 * File locking.
michael@0 814 */
michael@0 815
michael@0 816 PRStatus
michael@0 817 _MD_lockfile (PRInt32 osfd)
michael@0 818 {
michael@0 819 PRInt32 rv;
michael@0 820 struct flock linfo;
michael@0 821
michael@0 822 linfo.l_type =
michael@0 823 linfo.l_whence = SEEK_SET;
michael@0 824 linfo.l_start = 0;
michael@0 825 linfo.l_len = 0;
michael@0 826
michael@0 827 rv = fcntl(osfd, F_SETLKW, &linfo);
michael@0 828 if (rv == 0)
michael@0 829 return PR_SUCCESS;
michael@0 830
michael@0 831 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
michael@0 832 return PR_FAILURE;
michael@0 833 }
michael@0 834
michael@0 835 PRStatus
michael@0 836 _MD_tlockfile (PRInt32 osfd)
michael@0 837 {
michael@0 838 PRInt32 rv;
michael@0 839 struct flock linfo;
michael@0 840
michael@0 841 linfo.l_type =
michael@0 842 linfo.l_whence = SEEK_SET;
michael@0 843 linfo.l_start = 0;
michael@0 844 linfo.l_len = 0;
michael@0 845
michael@0 846 rv = fcntl(osfd, F_SETLK, &linfo);
michael@0 847 if (rv == 0)
michael@0 848 return PR_SUCCESS;
michael@0 849
michael@0 850 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
michael@0 851 return PR_FAILURE;
michael@0 852 }
michael@0 853
michael@0 854 PRStatus
michael@0 855 _MD_unlockfile (PRInt32 osfd)
michael@0 856 {
michael@0 857 PRInt32 rv;
michael@0 858 struct flock linfo;
michael@0 859
michael@0 860 linfo.l_type =
michael@0 861 linfo.l_whence = SEEK_SET;
michael@0 862 linfo.l_start = 0;
michael@0 863 linfo.l_len = 0;
michael@0 864
michael@0 865 rv = fcntl(osfd, F_UNLCK, &linfo);
michael@0 866
michael@0 867 if (rv == 0)
michael@0 868 return PR_SUCCESS;
michael@0 869
michael@0 870 _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
michael@0 871 return PR_FAILURE;
michael@0 872 }
michael@0 873

mercurial