Back to index

lightning-sunbird  0.9+nobinonly
bfile.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; c-basic-offset: 8 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "primpl.h"
00039 
00040 /*
00041 ** Global lock variable used to bracket calls into rusty libraries that
00042 ** aren't thread safe (like libc, libX, etc).
00043 */
00044 static PRLock *_pr_rename_lock = NULL; 
00045 
00046 void
00047 _MD_InitIO (void)
00048 {
00049 }
00050 
00051 PRStatus
00052 _MD_open_dir (_MDDir *md,const char *name)
00053 {
00054 int err;
00055 
00056        md->d = opendir(name);
00057        if (!md->d) {
00058               err = _MD_ERRNO();
00059               _PR_MD_MAP_OPENDIR_ERROR(err);
00060               return PR_FAILURE;
00061        }
00062        return PR_SUCCESS;
00063 }
00064 
00065 char*
00066 _MD_read_dir (_MDDir *md, PRIntn flags)
00067 {
00068 struct dirent *de;
00069 int err;
00070 
00071        for (;;) {
00072               /*
00073                * XXX: readdir() is not MT-safe
00074                */
00075               _MD_ERRNO() = 0;
00076               de = readdir(md->d);
00077 
00078               if (!de) {
00079                      err = _MD_ERRNO();
00080                      _PR_MD_MAP_READDIR_ERROR(err);
00081                      return 0;
00082               }
00083 
00084               if ((flags & PR_SKIP_DOT) &&
00085                   (de->d_name[0] == '.') && (de->d_name[1] == 0))
00086                      continue;
00087 
00088               if ((flags & PR_SKIP_DOT_DOT) &&
00089                   (de->d_name[0] == '.') && (de->d_name[1] == '.') &&
00090                   (de->d_name[2] == 0))
00091                      continue;
00092 
00093               if ((flags & PR_SKIP_HIDDEN) && (de->d_name[1] == '.'))
00094                      continue;
00095 
00096               break;
00097        }
00098        return de->d_name;
00099 }
00100 
00101 
00102 PRInt32
00103 _MD_close_dir (_MDDir *md)
00104 {
00105 int rv = 0, err;
00106 
00107        if (md->d) {
00108               rv = closedir(md->d);
00109               if (rv == -1) {
00110                      err = _MD_ERRNO();
00111                      _PR_MD_MAP_CLOSEDIR_ERROR(err);
00112               }
00113        }
00114        return(rv);
00115 }
00116 
00117 void
00118 _MD_make_nonblock (PRFileDesc *fd)
00119 {
00120        int blocking = 1;
00121        setsockopt(fd->secret->md.osfd, SOL_SOCKET, SO_NONBLOCK, &blocking, sizeof(blocking));
00122 
00123 }
00124 
00125 PRStatus
00126 _MD_set_fd_inheritable (PRFileDesc *fd, PRBool inheritable)
00127 {
00128         int rv;
00129        
00130         rv = fcntl(fd->secret->md.osfd, F_SETFD, inheritable ? 0 : FD_CLOEXEC);
00131         if (-1 == rv) {
00132                 PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
00133                 return PR_FAILURE;
00134         }
00135         return PR_SUCCESS;
00136 }
00137 
00138 void
00139 _MD_init_fd_inheritable (PRFileDesc *fd, PRBool imported)
00140 {
00141        if (imported) {
00142               fd->secret->inheritable = _PR_TRI_UNKNOWN;
00143        } else {
00144               int flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
00145               if (flags == -1) {
00146                      PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO());
00147                      return;
00148               }
00149               fd->secret->inheritable = (flags & FD_CLOEXEC) ? 
00150                      _PR_TRI_TRUE : _PR_TRI_FALSE;
00151        }
00152 }
00153 
00154 void
00155 _MD_query_fd_inheritable (PRFileDesc *fd)
00156 {
00157        int flags;
00158        
00159        PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
00160        flags = fcntl(fd->secret->md.osfd, F_GETFD, 0);
00161        PR_ASSERT(-1 != flags);
00162        fd->secret->inheritable = (flags & FD_CLOEXEC) ?
00163               _PR_TRI_FALSE : _PR_TRI_TRUE;
00164 }
00165 
00166 PRInt32
00167 _MD_open (const char *name, PRIntn flags, PRIntn mode)
00168 {
00169        PRInt32 osflags;
00170        PRInt32 rv, err;
00171 
00172        if (flags & PR_RDWR) {
00173               osflags = O_RDWR;
00174        } else if (flags & PR_WRONLY) {
00175               osflags = O_WRONLY;
00176        } else {
00177               osflags = O_RDONLY;
00178        }
00179 
00180        if (flags & PR_EXCL)
00181               osflags |= O_EXCL;
00182        if (flags & PR_APPEND)
00183               osflags |= O_APPEND;
00184        if (flags & PR_TRUNCATE)
00185               osflags |= O_TRUNC;
00186        if (flags & PR_SYNC) {
00187 /* Ummmm.  BeOS doesn't appear to
00188    support sync in any way shape or
00189    form. */
00190               return PR_NOT_IMPLEMENTED_ERROR;
00191        }
00192 
00193        /*
00194        ** On creations we hold the 'create' lock in order to enforce
00195        ** the semantics of PR_Rename. (see the latter for more details)
00196        */
00197        if (flags & PR_CREATE_FILE)
00198        {
00199               osflags |= O_CREAT ;
00200               if (NULL !=_pr_rename_lock)
00201                   PR_Lock(_pr_rename_lock);
00202        }
00203 
00204         rv = open(name, osflags, mode);
00205 
00206         if (rv < 0) {
00207                 err = _MD_ERRNO();
00208                 _PR_MD_MAP_OPEN_ERROR(err);
00209         }                                                                      
00210 
00211     if ((flags & PR_CREATE_FILE) && (NULL !=_pr_rename_lock))
00212         PR_Unlock(_pr_rename_lock);
00213         return rv;
00214 }
00215 
00216 PRInt32
00217 _MD_close_file (PRInt32 osfd)
00218 {
00219 PRInt32 rv, err;
00220 
00221        rv = close(osfd);
00222        if (rv == -1) {
00223               err = _MD_ERRNO();
00224               _PR_MD_MAP_CLOSE_ERROR(err);
00225        }
00226        return(rv);
00227 }
00228 
00229 PRInt32
00230 _MD_read (PRFileDesc *fd, void *buf, PRInt32 amount)
00231 {
00232     PRInt32 rv, err;
00233     PRInt32 osfd = fd->secret->md.osfd;
00234 
00235     rv = read( osfd, buf, amount );
00236     if (rv < 0) {
00237        err = _MD_ERRNO();
00238        _PR_MD_MAP_READ_ERROR(err);
00239     }
00240     return(rv);
00241 }
00242 
00243 PRInt32
00244 _MD_write (PRFileDesc *fd, const void *buf, PRInt32 amount)
00245 {
00246     PRInt32 rv, err;
00247     PRInt32 osfd = fd->secret->md.osfd;
00248 
00249     rv = write( osfd, buf, amount );
00250 
00251     if( rv < 0 ) {
00252 
00253        err = _MD_ERRNO();
00254        _PR_MD_MAP_WRITE_ERROR(err);
00255     }
00256     return( rv );
00257 }
00258 
00259 #ifndef BONE_VERSION /* Writev moves to bnet.c with BONE */
00260 PRInt32
00261 _MD_writev (PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size,
00262            PRIntervalTime timeout)
00263 {
00264     return PR_NOT_IMPLEMENTED_ERROR;
00265 }
00266 #endif
00267 
00268 PRInt32
00269 _MD_lseek (PRFileDesc *fd, PRInt32 offset, int whence)
00270 {
00271 PRInt32 rv, err;
00272 
00273     rv = lseek (fd->secret->md.osfd, offset, whence);
00274     if (rv == -1) {
00275         err = _MD_ERRNO();
00276        _PR_MD_MAP_LSEEK_ERROR(err);
00277     }
00278     return( rv );
00279 }
00280 
00281 PRInt64
00282 _MD_lseek64 (PRFileDesc *fd, PRInt64 offset, int whence)
00283 {
00284 PRInt32 rv, err;
00285 
00286 /* According to the BeOS headers, lseek accepts a
00287  * variable of type off_t for the offset, and off_t
00288  * is defined to be a 64-bit value.  So no special
00289  * cracking needs to be done on "offset".
00290  */
00291 
00292     rv = lseek (fd->secret->md.osfd, offset, whence);
00293     if (rv == -1) {
00294         err = _MD_ERRNO();
00295        _PR_MD_MAP_LSEEK_ERROR(err);
00296     }
00297     return( rv );
00298 }
00299 
00300 PRInt32
00301 _MD_fsync (PRFileDesc *fd)
00302 {
00303 PRInt32 rv, err;
00304 
00305     rv = fsync(fd->secret->md.osfd);
00306     if (rv == -1) {
00307        err = _MD_ERRNO();
00308        _PR_MD_MAP_FSYNC_ERROR(err);
00309     }
00310     return(rv);
00311 }
00312 
00313 PRInt32
00314 _MD_delete (const char *name)
00315 {
00316 PRInt32 rv, err;
00317 
00318     rv = unlink(name);
00319     if (rv == -1)
00320     {
00321        err = _MD_ERRNO();
00322         _PR_MD_MAP_UNLINK_ERROR(err);
00323     }
00324     return (rv);
00325 }
00326 
00327 PRInt32
00328 _MD_getfileinfo (const char *fn, PRFileInfo *info)
00329 {
00330 struct stat sb;
00331 PRInt32 rv, err;
00332 PRInt64 s, s2us;
00333 
00334        rv = stat(fn, &sb);
00335        if (rv < 0) {
00336               err = _MD_ERRNO();
00337               _PR_MD_MAP_STAT_ERROR(err);
00338        } else if (info) {
00339               if (S_IFREG & sb.st_mode)
00340                      info->type = PR_FILE_FILE;
00341               else if (S_IFDIR & sb.st_mode)
00342                      info->type = PR_FILE_DIRECTORY;
00343               else
00344                      info->type = PR_FILE_OTHER;
00345 
00346               /* Must truncate file size for the 32 bit
00347                  version */
00348               info->size = (sb.st_size & 0xffffffff);
00349               LL_I2L(s, sb.st_mtime);
00350               LL_I2L(s2us, PR_USEC_PER_SEC);
00351               LL_MUL(s, s, s2us);
00352               info->modifyTime = s;
00353               LL_I2L(s, sb.st_ctime);
00354               LL_MUL(s, s, s2us);
00355               info->creationTime = s;
00356        }
00357        return rv;
00358 }
00359 
00360 PRInt32
00361 _MD_getfileinfo64 (const char *fn, PRFileInfo64 *info)
00362 {
00363 struct stat sb;
00364 PRInt32 rv, err;
00365 PRInt64 s, s2us;
00366 
00367        rv = stat(fn, &sb);
00368        if (rv < 0) {
00369               err = _MD_ERRNO();
00370               _PR_MD_MAP_STAT_ERROR(err);
00371        } else if (info) {
00372               if (S_IFREG & sb.st_mode)
00373                      info->type = PR_FILE_FILE;
00374               else if (S_IFDIR & sb.st_mode)
00375                      info->type = PR_FILE_DIRECTORY;
00376               else
00377                      info->type = PR_FILE_OTHER;
00378        
00379               /* For the 64 bit version we can use
00380                * the native st_size without modification
00381                */
00382               info->size = sb.st_size;
00383               LL_I2L(s, sb.st_mtime);
00384               LL_I2L(s2us, PR_USEC_PER_SEC);
00385               LL_MUL(s, s, s2us);
00386               info->modifyTime = s;
00387               LL_I2L(s, sb.st_ctime);
00388               LL_MUL(s, s, s2us);
00389               info->creationTime = s;
00390        }
00391        return rv;
00392 }
00393 
00394 PRInt32
00395 _MD_getopenfileinfo (const PRFileDesc *fd, PRFileInfo *info)
00396 {
00397         struct stat sb;
00398         PRInt64 s, s2us;
00399         PRInt32 rv, err;
00400 
00401         rv = fstat(fd->secret->md.osfd, &sb);
00402         if (rv < 0) {
00403                         err = _MD_ERRNO();
00404                         _PR_MD_MAP_FSTAT_ERROR(err);
00405         } else if (info) {
00406                 if (info) {
00407                         if (S_IFREG & sb.st_mode)
00408                                 info->type = PR_FILE_FILE ;
00409                         else if (S_IFDIR & sb.st_mode)
00410                                 info->type = PR_FILE_DIRECTORY;
00411                         else
00412                                 info->type = PR_FILE_OTHER;
00413                      /* Use lower 32 bits of file size */
00414                         info->size = ( sb.st_size & 0xffffffff);
00415                         LL_I2L(s, sb.st_mtime);
00416                         LL_I2L(s2us, PR_USEC_PER_SEC);
00417                         LL_MUL(s, s, s2us);
00418                         info->modifyTime = s;
00419                         LL_I2L(s, sb.st_ctime);
00420                         LL_MUL(s, s, s2us);
00421                         info->creationTime = s;
00422                 }
00423         }
00424         return rv;
00425 }
00426 
00427 PRInt32
00428 _MD_getopenfileinfo64 (const PRFileDesc *fd, PRFileInfo64 *info)
00429 {
00430         struct stat sb;
00431         PRInt64 s, s2us;
00432         PRInt32 rv, err;
00433 
00434         rv = fstat(fd->secret->md.osfd, &sb);
00435         if (rv < 0) {
00436                         err = _MD_ERRNO();
00437                         _PR_MD_MAP_FSTAT_ERROR(err);
00438         } else if (info) {
00439                 if (info) {
00440                         if (S_IFREG & sb.st_mode)
00441                                 info->type = PR_FILE_FILE ;
00442                         else if (S_IFDIR & sb.st_mode)
00443                                 info->type = PR_FILE_DIRECTORY;
00444                         else
00445                                 info->type = PR_FILE_OTHER;
00446                         info->size = sb.st_size;
00447                         LL_I2L(s, sb.st_mtime);
00448                         LL_I2L(s2us, PR_USEC_PER_SEC);
00449                         LL_MUL(s, s, s2us);
00450                         info->modifyTime = s;
00451                         LL_I2L(s, sb.st_ctime);
00452                         LL_MUL(s, s, s2us);
00453                         info->creationTime = s;
00454                 }
00455         }
00456         return rv;
00457 }
00458 
00459 PRInt32
00460 _MD_rename (const char *from, const char *to)
00461 {
00462     PRInt32 rv = -1, err;
00463 
00464     /*
00465     ** This is trying to enforce the semantics of WINDOZE' rename
00466     ** operation. That means one is not allowed to rename over top
00467     ** of an existing file. Holding a lock across these two function
00468     ** and the open function is known to be a bad idea, but ....
00469     */
00470     if (NULL != _pr_rename_lock)
00471         PR_Lock(_pr_rename_lock);
00472     if (0 == access(to, F_OK))
00473         PR_SetError(PR_FILE_EXISTS_ERROR, 0);
00474     else
00475     {
00476             rv = rename(from, to);
00477             if (rv < 0) {
00478                     err = _MD_ERRNO();
00479                     _PR_MD_MAP_RENAME_ERROR(err);
00480             }
00481     }
00482     if (NULL != _pr_rename_lock)
00483         PR_Unlock(_pr_rename_lock);
00484     return rv; 
00485 }
00486 
00487 PRInt32
00488 _MD_access (const char *name, PRIntn how)
00489 {
00490 PRInt32 rv, err;
00491 int checkFlags;
00492 struct stat buf;
00493 
00494        switch (how) {
00495               case PR_ACCESS_WRITE_OK:
00496                      checkFlags = S_IWUSR | S_IWGRP | S_IWOTH;
00497                      break;
00498               
00499               case PR_ACCESS_READ_OK:
00500                      checkFlags = S_IRUSR | S_IRGRP | S_IROTH;
00501                      break;
00502               
00503               case PR_ACCESS_EXISTS:
00504                      /* we don't need to examine st_mode. */
00505                      break;
00506               
00507               default:
00508                      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
00509                      return -1;
00510        }
00511 
00512        rv = stat(name, &buf);
00513        if (rv == 0 && how != PR_ACCESS_EXISTS && (!(buf.st_mode & checkFlags))) {
00514               PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR, 0);
00515               return -1;
00516        }
00517 
00518        if (rv < 0) {
00519               err = _MD_ERRNO();
00520               _PR_MD_MAP_STAT_ERROR(err);
00521        }
00522 
00523        return(rv);
00524 }
00525 
00526 PRInt32
00527 _MD_stat (const char *name, struct stat *buf)
00528 {
00529     return PR_NOT_IMPLEMENTED_ERROR;
00530 }
00531 
00532 PRInt32
00533 _MD_mkdir (const char *name, PRIntn mode)
00534 {
00535     status_t rv;
00536     int err;
00537 
00538     /*
00539     ** This lock is used to enforce rename semantics as described
00540     ** in PR_Rename. Look there for more fun details.
00541     */
00542     if (NULL !=_pr_rename_lock)
00543         PR_Lock(_pr_rename_lock);
00544 
00545     rv = mkdir(name, mode);
00546     if (rv < 0) {
00547        err = _MD_ERRNO();
00548        _PR_MD_MAP_MKDIR_ERROR(err);
00549     }
00550     if (NULL !=_pr_rename_lock)
00551         PR_Unlock(_pr_rename_lock);
00552     return rv; 
00553 }
00554 
00555 PRInt32
00556 _MD_rmdir (const char *name)
00557 {
00558 int rv, err;
00559 
00560         rv = rmdir(name);
00561         if (rv == -1) {
00562                         err = _MD_ERRNO();
00563                         _PR_MD_MAP_RMDIR_ERROR(err);
00564         }
00565         return rv;
00566 }
00567 
00568 PRInt32
00569 _MD_pr_poll(PRPollDesc *pds, PRIntn npds, PRIntervalTime timeout)
00570 {
00571        PRInt32 rv = 0;
00572        PRThread *me = _PR_MD_CURRENT_THREAD();
00573        /*
00574         * This code is almost a duplicate of w32poll.c's _PR_MD_PR_POLL().
00575         */
00576        fd_set rd, wt, ex;
00577        PRFileDesc *bottom;
00578        PRPollDesc *pd, *epd;
00579        PRInt32 maxfd = -1, ready, err;
00580        PRIntervalTime remaining, elapsed, start;
00581 
00582        struct timeval tv, *tvp = NULL;
00583 
00584        if (_PR_PENDING_INTERRUPT(me))
00585        {
00586               me->flags &= ~_PR_INTERRUPT;
00587               PR_SetError(PR_PENDING_INTERRUPT_ERROR, 0);
00588               return -1;
00589        }
00590 
00591        if (0 == npds) {
00592               PR_Sleep(timeout);
00593               return rv;
00594        }
00595 
00596        FD_ZERO(&rd);
00597        FD_ZERO(&wt);
00598        FD_ZERO(&ex);
00599 
00600        ready = 0;
00601        for (pd = pds, epd = pd + npds; pd < epd; pd++)
00602        {
00603               PRInt16 in_flags_read = 0, in_flags_write = 0;
00604               PRInt16 out_flags_read = 0, out_flags_write = 0; 
00605               
00606               if ((NULL != pd->fd) && (0 != pd->in_flags))
00607               {
00608                      if (pd->in_flags & PR_POLL_READ)
00609                      {
00610                             in_flags_read = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_WRITE, &out_flags_read);
00611                      }
00612                      if (pd->in_flags & PR_POLL_WRITE)
00613                      {
00614                             in_flags_write = (pd->fd->methods->poll)(pd->fd, pd->in_flags & ~PR_POLL_READ, &out_flags_write);
00615                      }
00616                      if ((0 != (in_flags_read & out_flags_read))
00617                          || (0 != (in_flags_write & out_flags_write)))
00618                      {
00619                             /* this one's ready right now */
00620                             if (0 == ready)
00621                             {
00622                                    /*
00623                                     * We will have to return without calling the
00624                                     * system poll/select function.  So zero the
00625                                     * out_flags fields of all the poll descriptors
00626                                     * before this one. 
00627                                     */
00628                                    PRPollDesc *prev;
00629                                    for (prev = pds; prev < pd; prev++)
00630                                    {
00631                                           prev->out_flags = 0;
00632                                    }
00633                             }
00634                             ready += 1;
00635                             pd->out_flags = out_flags_read | out_flags_write;
00636                      }
00637                      else
00638                      {
00639                             pd->out_flags = 0;  /* pre-condition */
00640                             
00641                             /* make sure this is an NSPR supported stack */
00642                             bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00643                             PR_ASSERT(NULL != bottom);  /* what to do about that? */
00644                             if ((NULL != bottom)
00645                                 && (_PR_FILEDESC_OPEN == bottom->secret->state))
00646                             {
00647                                    if (0 == ready)
00648                                    {
00649                                           PRInt32 osfd = bottom->secret->md.osfd; 
00650                                           if (osfd > maxfd) maxfd = osfd;
00651                                           if (in_flags_read & PR_POLL_READ)
00652                                           {
00653                                                  pd->out_flags |= _PR_POLL_READ_SYS_READ;
00654                                                  FD_SET(osfd, &rd);
00655                                           }
00656                                           if (in_flags_read & PR_POLL_WRITE)
00657                                           {
00658                                                  pd->out_flags |= _PR_POLL_READ_SYS_WRITE;
00659                                                  FD_SET(osfd, &wt);
00660                                           }
00661                                           if (in_flags_write & PR_POLL_READ)
00662                                           {
00663                                                  pd->out_flags |= _PR_POLL_WRITE_SYS_READ;
00664                                                  FD_SET(osfd, &rd);
00665                                           }
00666                                           if (in_flags_write & PR_POLL_WRITE)
00667                                           {
00668                                                  pd->out_flags |= _PR_POLL_WRITE_SYS_WRITE;
00669                                                  FD_SET(osfd, &wt);
00670                                           }
00671                                           if (pd->in_flags & PR_POLL_EXCEPT) FD_SET(osfd, &ex);
00672                                    }
00673                             }
00674                             else
00675                             {
00676                                    if (0 == ready)
00677                                    {
00678                                           PRPollDesc *prev;
00679                                           for (prev = pds; prev < pd; prev++)
00680                                           {
00681                                                  prev->out_flags = 0;
00682                                           }
00683                                    }
00684                                    ready += 1;  /* this will cause an abrupt return */
00685                                    pd->out_flags = PR_POLL_NVAL;  /* bogii */
00686                             }
00687                      }
00688               }
00689               else
00690               {
00691                      pd->out_flags = 0;
00692               }
00693        }
00694 
00695        if (0 != ready) return ready;  /* no need to block */
00696 
00697        remaining = timeout;
00698        start = PR_IntervalNow(); 
00699 
00700  retry:
00701        if (timeout != PR_INTERVAL_NO_TIMEOUT)
00702        {
00703               PRInt32 ticksPerSecond = PR_TicksPerSecond();
00704               tv.tv_sec = remaining / ticksPerSecond;
00705               tv.tv_usec = PR_IntervalToMicroseconds( remaining % ticksPerSecond );
00706               tvp = &tv;
00707        }
00708        
00709        ready = _MD_SELECT(maxfd + 1, &rd, &wt, &ex, tvp);
00710        
00711        if (ready == -1 && errno == EINTR)
00712        {
00713               if (timeout == PR_INTERVAL_NO_TIMEOUT) goto retry;
00714               else
00715               {
00716                      elapsed = (PRIntervalTime) (PR_IntervalNow() - start);
00717                      if (elapsed > timeout) ready = 0;  /* timed out */
00718                      else
00719                      {
00720                             remaining = timeout - elapsed;
00721                             goto retry; 
00722                      }
00723               }
00724        } 
00725 
00726        /*
00727        ** Now to unravel the select sets back into the client's poll
00728        ** descriptor list. Is this possibly an area for pissing away
00729        ** a few cycles or what?
00730        */
00731        if (ready > 0)
00732        {
00733               ready = 0;
00734               for (pd = pds, epd = pd + npds; pd < epd; pd++)
00735               {
00736                      PRInt16 out_flags = 0;
00737                      if ((NULL != pd->fd) && (0 != pd->in_flags))
00738                      {
00739                             PRInt32 osfd;
00740                             bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00741                             PR_ASSERT(NULL != bottom);
00742                             
00743                             osfd = bottom->secret->md.osfd; 
00744                             
00745                             if (FD_ISSET(osfd, &rd))
00746                             {
00747                                    if (pd->out_flags & _PR_POLL_READ_SYS_READ)
00748                                           out_flags |= PR_POLL_READ;
00749                                    if (pd->out_flags & _PR_POLL_WRITE_SYS_READ)
00750                                           out_flags |= PR_POLL_WRITE;
00751                             }
00752                             if (FD_ISSET(osfd, &wt))
00753                             {
00754                                    if (pd->out_flags & _PR_POLL_READ_SYS_WRITE)
00755                                           out_flags |= PR_POLL_READ;
00756                                    if (pd->out_flags & _PR_POLL_WRITE_SYS_WRITE)
00757                                           out_flags |= PR_POLL_WRITE;
00758                             }
00759                             if (FD_ISSET(osfd, &ex)) out_flags |= PR_POLL_EXCEPT;
00760 
00761 /* Workaround for nonblocking connects under net_server */
00762 #ifndef BONE_VERSION               
00763                             if (out_flags)
00764                             {
00765                                    /* check if it is a pending connect */
00766                                    int i = 0, j = 0;
00767                                    PR_Lock( _connectLock );
00768                                    for( i = 0; i < connectCount; i++ ) 
00769                                    {
00770                                           if(connectList[i].osfd == osfd)
00771                                           {
00772                                                  int connectError;
00773                                                  int connectResult;
00774                                    
00775                                                  connectResult = connect(connectList[i].osfd,
00776                                                                          &connectList[i].addr,
00777                                                                          connectList[i].addrlen);
00778                                                  connectError = errno;
00779                                    
00780                                                  if(connectResult < 0 ) 
00781                                                  {
00782                                                         if(connectError == EINTR || connectError == EWOULDBLOCK ||
00783                                                     connectError == EINPROGRESS || connectError == EALREADY)
00784                                                         {
00785                                                                break;
00786                                                         }
00787                                                  }
00788                                    
00789                                                  if(i == (connectCount - 1))
00790                                                  {
00791                                                         connectList[i].osfd = -1;
00792                                                  } else {
00793                                                         for(j = i; j < connectCount; j++ )
00794                                                         {
00795                                                                memcpy( &connectList[j], &connectList[j+1],
00796                                                                        sizeof(connectList[j]));
00797                                                         }
00798                                                  }
00799                                                  connectCount--;
00800                                    
00801                                                  bottom->secret->md.connectReturnValue = connectResult;
00802                                                  bottom->secret->md.connectReturnError = connectError;
00803                                                  bottom->secret->md.connectValueValid = PR_TRUE;
00804                                                  break;
00805                                           }
00806                                    }
00807                                    PR_Unlock( _connectLock );
00808                             }
00809 #endif
00810                      }
00811                      pd->out_flags = out_flags;
00812                      if (out_flags) ready++;
00813               }
00814               PR_ASSERT(ready > 0);
00815        }
00816        else if (ready < 0)
00817        { 
00818               err = _MD_ERRNO();
00819               if (err == EBADF)
00820               {
00821                      /* Find the bad fds */
00822                      ready = 0;
00823                      for (pd = pds, epd = pd + npds; pd < epd; pd++)
00824                      {
00825                             pd->out_flags = 0;
00826                             if ((NULL != pd->fd) && (0 != pd->in_flags))
00827                             {
00828                                    bottom = PR_GetIdentitiesLayer(pd->fd, PR_NSPR_IO_LAYER);
00829                                    if (fcntl(bottom->secret->md.osfd, F_GETFL, 0) == -1)
00830                                    {
00831                                           pd->out_flags = PR_POLL_NVAL;
00832                                           ready++;
00833                                    }
00834                             }
00835                      }
00836                      PR_ASSERT(ready > 0);
00837               }
00838               else _PR_MD_MAP_SELECT_ERROR(err);
00839        }
00840        
00841        return ready;
00842 }  /* _MD_pr_poll */
00843 
00844 /*
00845  * File locking.
00846  */
00847 
00848 PRStatus
00849 _MD_lockfile (PRInt32 osfd)
00850 {
00851     PRInt32 rv;
00852     struct flock linfo;
00853 
00854     linfo.l_type = 
00855     linfo.l_whence = SEEK_SET;
00856     linfo.l_start = 0;
00857     linfo.l_len = 0;
00858 
00859     rv = fcntl(osfd, F_SETLKW, &linfo);
00860     if (rv == 0)
00861        return PR_SUCCESS;
00862 
00863     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
00864     return PR_FAILURE;
00865 }
00866 
00867 PRStatus
00868 _MD_tlockfile (PRInt32 osfd)
00869 {
00870     PRInt32 rv;
00871     struct flock linfo;
00872 
00873     linfo.l_type = 
00874     linfo.l_whence = SEEK_SET;
00875     linfo.l_start = 0;
00876     linfo.l_len = 0;
00877 
00878     rv = fcntl(osfd, F_SETLK, &linfo);
00879     if (rv == 0)
00880        return PR_SUCCESS;
00881 
00882     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
00883     return PR_FAILURE;
00884 }
00885 
00886 PRStatus
00887 _MD_unlockfile (PRInt32 osfd)
00888 {
00889     PRInt32 rv;
00890     struct flock linfo;
00891 
00892     linfo.l_type = 
00893     linfo.l_whence = SEEK_SET;
00894     linfo.l_start = 0;
00895     linfo.l_len = 0;
00896 
00897     rv = fcntl(osfd, F_UNLCK, &linfo);
00898 
00899     if (rv == 0)
00900        return PR_SUCCESS;
00901 
00902     _PR_MD_MAP_FLOCK_ERROR(_MD_ERRNO());
00903     return PR_FAILURE;
00904 }
00905