file.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /*
  42. * file.c: system specific functions for reading/writing files
  43. *
  44. * See file.h for formal definitions of what these functions do
  45. *
  46. * Rob McCool
  47. */
  48. #include "base/file.h"
  49. #ifdef BSD_RLIMIT
  50. #include <sys/time.h>
  51. #include <sys/resource.h>
  52. #else
  53. #include <stdlib.h>
  54. #include <signal.h>
  55. #endif
  56. #ifdef XP_WIN32
  57. #include <time.h> /* time */
  58. #include <sys/stat.h> /* stat */
  59. #include <errno.h>
  60. #include <direct.h>
  61. #include <base/nterr.h>
  62. /* Removed for ns security integration
  63. #include <xp_error.h>
  64. */
  65. #endif
  66. #include <prerror.h>
  67. #include "private/pprio.h"
  68. #include "prlock.h"
  69. extern "C" char *nscperror_lookup(int err);
  70. /* --- globals -------------------------------------------------------------*/
  71. /* PRFileDesc * SYS_ERROR_FD = NULL; */
  72. const int errbuf_size = 256;
  73. const unsigned int LOCKFILERANGE=0x7FFFFFFF;
  74. PRLock *_atomic_write_lock = NULL;
  75. /* --------------------------------- stat --------------------------------- */
  76. /* XXXMB - Can't convert to PR_GetFileInfo because we directly exported
  77. * the stat interface... Damn.
  78. */
  79. NSAPI_PUBLIC int system_stat(char *path, struct stat *finfo)
  80. {
  81. #ifdef XP_WIN32
  82. int chop, l;
  83. /* The NT stat is very peculiar about directory names. */
  84. /* XXX aruna - there is a bug here, maybe in the C runtime.
  85. * Stating the same path in a separate program succeeds. From
  86. * jblack's profiling, this needs to be replaced by the Win32
  87. * calls anyway.*/
  88. l = strlen(path);
  89. if((path[l - 1] == '/') &&
  90. (!(isalpha(path[0]) && (!strcmp(&path[1], ":/")))))
  91. {
  92. chop = 1;
  93. path[--l] = '\0';
  94. }
  95. else chop = 0;
  96. #endif /* XP_WIN32 */
  97. #ifdef XP_UNIX
  98. if(stat(path, finfo) == -1)
  99. return -1;
  100. #else /* XP_WIN32 */
  101. if(_stat(path, (struct _stat *)finfo) == -1) {
  102. /* XXXMB - this sucks;
  103. * try to convert to an error code we'll expect...
  104. */
  105. switch(errno) {
  106. case ENOENT: PR_SetError(PR_FILE_NOT_FOUND_ERROR, errno); break;
  107. default: PR_SetError(PR_UNKNOWN_ERROR, errno); break;
  108. }
  109. return -1;
  110. }
  111. /* NT sets the time fields to -1 if it thinks that the file
  112. * is a device ( like com1.html, lpt1.html etc) In this case
  113. * simply set last modified time to the current time....
  114. */
  115. if (finfo->st_mtime == -1) {
  116. finfo->st_mtime = time(NULL);
  117. }
  118. if (finfo->st_atime == -1) {
  119. finfo->st_atime = 0;
  120. }
  121. if (finfo->st_ctime == -1) {
  122. finfo->st_ctime = 0;
  123. }
  124. if(chop)
  125. path[l++] = '/';
  126. #endif /* XP_WIN32 */
  127. if(S_ISREG(finfo->st_mode) && (path[strlen(path) - 1] == '/')) {
  128. /* File with trailing slash */
  129. errno = ENOENT;
  130. return -1;
  131. }
  132. return 0;
  133. }
  134. NSAPI_PUBLIC int system_fread(SYS_FILE fd, char *buf, int sz)
  135. {
  136. /* XXXMB - this is the *one* function which does return a length
  137. * instead of the IO_ERROR/IO_OKAY.
  138. */
  139. return PR_Read(fd, buf, sz);
  140. }
  141. NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, char *buf, int sz) {
  142. int n,o,w;
  143. for(n=sz,o=0; n; n-=w,o+=w) {
  144. if((w = PR_Write(fd, &buf[o], n)) < 0)
  145. return IO_ERROR;
  146. }
  147. return IO_OKAY;
  148. }
  149. /* ---------------------------- Standard UNIX ----------------------------- */
  150. #ifdef XP_UNIX
  151. #include <sys/file.h> /* flock */
  152. NSAPI_PUBLIC int system_fwrite_atomic(SYS_FILE fd, char *buf, int sz)
  153. {
  154. int ret;
  155. #if 0
  156. if(flock(fd,LOCK_EX) == -1)
  157. return IO_ERROR;
  158. #endif
  159. ret = system_fwrite(fd,buf,sz);
  160. #if 0
  161. if(flock(fd,LOCK_UN) == -1)
  162. return IO_ERROR; /* ??? */
  163. #endif
  164. return ret;
  165. }
  166. /* -------------------------- system_nocoredumps -------------------------- */
  167. NSAPI_PUBLIC int system_nocoredumps(void)
  168. {
  169. #ifdef BSD_RLIMIT
  170. struct rlimit rl;
  171. rl.rlim_cur = 0;
  172. rl.rlim_max = 0;
  173. return setrlimit(RLIMIT_CORE, &rl);
  174. #else
  175. #if defined(SNI)
  176. /* C++ compiler seems to find more that one overloaded instance of exit() ?! */
  177. #define EXITFUNC ::exit
  178. #else
  179. #define EXITFUNC exit
  180. #endif
  181. signal(SIGQUIT, EXITFUNC);
  182. signal(SIGILL, EXITFUNC);
  183. signal(SIGTRAP, EXITFUNC);
  184. signal(SIGABRT, EXITFUNC);
  185. signal(SIGIOT, EXITFUNC);
  186. signal(SIGEMT, EXITFUNC);
  187. signal(SIGFPE, EXITFUNC);
  188. signal(SIGBUS, EXITFUNC);
  189. signal(SIGSEGV, EXITFUNC);
  190. signal(SIGSYS, EXITFUNC);
  191. return 0;
  192. #endif
  193. }
  194. #endif /* XP_UNIX */
  195. /* --------------------------- file_setinherit ---------------------------- */
  196. NSAPI_PUBLIC int file_setinherit(SYS_FILE fd, int value)
  197. {
  198. #if defined(XP_WIN32)
  199. int ret;
  200. // ret = SetHandleInformation((HANDLE)PR_FileDesc2NativeHandle(fd), 0, value?HANDLE_FLAG_INHERIT:0);
  201. // This function did nothing before since the mask was set to 0.
  202. ret = SetHandleInformation((HANDLE)PR_FileDesc2NativeHandle(fd), HANDLE_FLAG_INHERIT, value?HANDLE_FLAG_INHERIT:0);
  203. return ret==0?-1:0;
  204. #elif defined(XP_UNIX)
  205. int flags = 0;
  206. PRInt32 nativeFD;
  207. PRFileDesc *bottom = fd;
  208. while (bottom->lower != NULL) {
  209. bottom = bottom->lower;
  210. }
  211. nativeFD = PR_FileDesc2NativeHandle(bottom);
  212. #if 0
  213. fprintf(stderr, "\nInfo(file_setinherit): Native file descriptor is %d\n", nativeFD);
  214. #endif
  215. flags = fcntl(nativeFD, F_GETFD, 0);
  216. if(flags == -1)
  217. return -1;
  218. if(value)
  219. flags &= (~FD_CLOEXEC);
  220. else
  221. flags |= FD_CLOEXEC;
  222. fcntl(nativeFD, F_SETFD, flags);
  223. return 0;
  224. /* Comment out for ns security/ nspr integration (HACK for NOW)
  225. int flags = fcntl(PR_FileDesc2NativeHandle(fd), F_GETFD, 0);
  226. if(flags == -1)
  227. return -1;
  228. if(value)
  229. flags &= (~FD_CLOEXEC);
  230. else
  231. flags |= FD_CLOEXEC;
  232. fcntl(PR_FileDesc2NativeHandle(fd), F_SETFD, flags);
  233. return 0;
  234. */
  235. #endif
  236. }
  237. NSAPI_PUBLIC SYS_FILE system_fopenRO(char *p)
  238. {
  239. SYS_FILE f = PR_Open(p, PR_RDONLY, 0);
  240. if (!f)
  241. return SYS_ERROR_FD;
  242. return f;
  243. }
  244. NSAPI_PUBLIC SYS_FILE system_fopenWA(char *p)
  245. {
  246. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_APPEND, 0644);
  247. if (!f)
  248. return SYS_ERROR_FD;
  249. return f;
  250. }
  251. NSAPI_PUBLIC SYS_FILE system_fopenRW(char *p)
  252. {
  253. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE, 0644);
  254. if (!f)
  255. return SYS_ERROR_FD;
  256. return f;
  257. }
  258. NSAPI_PUBLIC SYS_FILE system_fopenWT(char *p)
  259. {
  260. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_TRUNCATE, 0644);
  261. if (!f)
  262. return SYS_ERROR_FD;
  263. return f;
  264. }
  265. NSAPI_PUBLIC int system_fclose(SYS_FILE fd)
  266. {
  267. return (PR_Close(fd));
  268. }
  269. #ifdef FILE_WIN32
  270. int CgiBuffering;
  271. NSAPI_PUBLIC SYS_FILE system_fopen(char *path, int access, int flags)
  272. {
  273. char p2[MAX_PATH];
  274. SYS_FILE ret;
  275. HANDLE fd;
  276. if (strlen(path) >= MAX_PATH) {
  277. return SYS_ERROR_FD;
  278. }
  279. file_unix2local(path, p2);
  280. fd = CreateFile(p2, access, FILE_SHARE_READ | FILE_SHARE_WRITE,
  281. NULL, flags, 0, NULL);
  282. ret = PR_ImportFile((int32)fd);
  283. if(ret == INVALID_HANDLE_VALUE)
  284. return SYS_ERROR_FD;
  285. return ret;
  286. }
  287. NSAPI_PUBLIC int system_pread(SYS_FILE fd, char *buf, int BytesToRead) {
  288. unsigned long BytesRead = 0;
  289. int result = 0;
  290. BOOLEAN TimeoutSet = FALSE;
  291. /* XXXMB - nspr20 should be able to do this; but right now it doesn't
  292. * return proper error info.
  293. * fix it later...
  294. */
  295. if(ReadFile((HANDLE)PR_FileDesc2NativeHandle(fd), (LPVOID)buf, BytesToRead, &BytesRead, NULL) == FALSE) {
  296. if (GetLastError() == ERROR_BROKEN_PIPE) {
  297. return IO_EOF;
  298. } else {
  299. return IO_ERROR;
  300. }
  301. }
  302. return (BytesRead ? BytesRead : IO_EOF);
  303. }
  304. NSAPI_PUBLIC int system_pwrite(SYS_FILE fd, char *buf, int BytesToWrite)
  305. {
  306. unsigned long BytesWritten;
  307. if (WriteFile((HANDLE)PR_FileDesc2NativeHandle(fd), (LPVOID)buf,
  308. BytesToWrite, &BytesWritten, NULL) == FALSE) {
  309. return IO_ERROR;
  310. }
  311. return BytesWritten;
  312. }
  313. NSAPI_PUBLIC int system_fwrite_atomic(SYS_FILE fd, char *buf, int sz)
  314. {
  315. int ret;
  316. #if 0
  317. if(system_flock(fd) == IO_ERROR)
  318. return IO_ERROR;
  319. #endif
  320. /* XXXMB - this is technically thread unsafe, but it catches any
  321. * callers of fwrite_atomic when we're single threaded and just coming
  322. * to life.
  323. */
  324. if (!_atomic_write_lock) {
  325. _atomic_write_lock = PR_NewLock();
  326. }
  327. PR_Lock(_atomic_write_lock);
  328. ret = system_fwrite(fd,buf,sz);
  329. PR_Unlock(_atomic_write_lock);
  330. #if 0
  331. if(system_ulock(fd) == IO_ERROR)
  332. return IO_ERROR;
  333. #endif
  334. return ret;
  335. }
  336. NSAPI_PUBLIC void file_unix2local(char *path, char *p2)
  337. {
  338. /* Try to handle UNIX-style paths */
  339. if((!strchr(path, FILE_PATHSEP))) {
  340. int x;
  341. for(x = 0; path[x]; x++)
  342. p2[x] = (path[x] == '/' ? '\\' : path[x]);
  343. p2[x] = '\0';
  344. }
  345. else
  346. strcpy(p2, path);
  347. }
  348. NSAPI_PUBLIC int system_nocoredumps(void)
  349. {
  350. return 0;
  351. }
  352. /* --------------------------- system_winerr ------------------------------ */
  353. #include <winsock.h>
  354. #include <errno.h>
  355. #include "util.h"
  356. NSAPI_PUBLIC char *system_winsockerr(void)
  357. {
  358. int errn = WSAGetLastError();
  359. return FindError(errn);
  360. }
  361. NSAPI_PUBLIC char *system_winerr(void)
  362. {
  363. int errn = GetLastError();
  364. if (errn == 0)
  365. errn = WSAGetLastError();
  366. return FindError(errn);
  367. }
  368. /* ------------------------- Dir related stuff ---------------------------- */
  369. NSAPI_PUBLIC SYS_DIR dir_open(char *pathp)
  370. {
  371. dir_s *ret = (dir_s *) MALLOC(sizeof(dir_s));
  372. char path[MAX_PATH];
  373. int l;
  374. if (strlen(pathp) >= MAX_PATH) {
  375. return NULL;
  376. }
  377. l = util_sprintf(path, "%s", pathp) - 1;
  378. path[strlen(pathp)] = '\0';
  379. if(path[strlen(path) - 1] != FILE_PATHSEP)
  380. strcpy (path + strlen(path), "\\*.*");
  381. else
  382. util_sprintf(path, "%s*.*", path);
  383. ret->de.d_name = NULL;
  384. if( (ret->dp = FindFirstFile(path, &ret->fdata)) != INVALID_HANDLE_VALUE)
  385. return ret;
  386. FREE(ret);
  387. return NULL;
  388. }
  389. NSAPI_PUBLIC SYS_DIRENT *dir_read(SYS_DIR ds)
  390. {
  391. if(FindNextFile(ds->dp, &ds->fdata) == FALSE)
  392. return NULL;
  393. if(ds->de.d_name)
  394. FREE(ds->de.d_name);
  395. ds->de.d_name = STRDUP(ds->fdata.cFileName);
  396. return &ds->de;
  397. }
  398. NSAPI_PUBLIC void dir_close(SYS_DIR ds)
  399. {
  400. FindClose(ds->dp);
  401. if(ds->de.d_name)
  402. FREE(ds->de.d_name);
  403. FREE(ds);
  404. }
  405. #endif /* FILE_WIN32 */
  406. NSAPI_PUBLIC int file_notfound(void)
  407. {
  408. #ifdef FILE_WIN32
  409. int errn = PR_GetError();
  410. return (errn == PR_FILE_NOT_FOUND_ERROR);
  411. #else
  412. return (errno == ENOENT);
  413. #endif
  414. }
  415. NSAPI_PUBLIC int dir_create_all(char *dir)
  416. {
  417. struct stat fi;
  418. char *t;
  419. #ifdef XP_WIN32
  420. t = dir + 3;
  421. #else /* XP_UNIX */
  422. t = dir + 1;
  423. #endif
  424. while(1) {
  425. t = strchr(t, FILE_PATHSEP);
  426. if(t) *t = '\0';
  427. if(stat(dir, &fi) == -1) {
  428. if(dir_create(dir) == -1)
  429. return -1;
  430. }
  431. if(t) *t++ = FILE_PATHSEP;
  432. else break;
  433. }
  434. return 0;
  435. }
  436. #ifdef XP_UNIX
  437. #if !defined(SNI) && !defined(LINUX)
  438. extern char *sys_errlist[];
  439. #endif /* SNI */
  440. #endif
  441. #define ERRMSG_SIZE 35
  442. #ifdef THREAD_ANY
  443. static int errmsg_key = -1;
  444. #include "systhr.h"
  445. /* Removed for ns security integration
  446. #include "xp_error.h"
  447. */
  448. #else /* THREAD_ANY */
  449. static char errmsg[ERRMSG_SIZE];
  450. #endif /* THREAD_ANY */
  451. #include "util.h"
  452. void system_errmsg_init(void)
  453. {
  454. if (errmsg_key == -1) {
  455. #if defined(THREAD_ANY)
  456. errmsg_key = systhread_newkey();
  457. #endif
  458. #ifdef XP_WIN32
  459. HashNtErrors();
  460. #endif
  461. if (!_atomic_write_lock)
  462. _atomic_write_lock = PR_NewLock();
  463. }
  464. }
  465. NSAPI_PUBLIC int system_errmsg_fn(char **buff, size_t maxlen)
  466. {
  467. char static_error[128];
  468. char *lmsg = 0; /* Local message pointer */
  469. size_t msglen = 0;
  470. int sys_error = 0;
  471. PRErrorCode nscp_error;
  472. #ifdef XP_WIN32
  473. LPTSTR sysmsg = 0;
  474. #endif
  475. /* Grab the OS error message */
  476. #ifdef XP_WIN32
  477. sys_error = GetLastError();
  478. #else
  479. sys_error = errno;
  480. #endif
  481. nscp_error = PR_GetError();
  482. /* If there is a NSPR error, but it is "unknown", try to get the OSError
  483. * and use that instead.
  484. */
  485. if (nscp_error == PR_UNKNOWN_ERROR)
  486. errno = PR_GetOSError();
  487. if (nscp_error != 0 && nscp_error != PR_UNKNOWN_ERROR){
  488. char *nscp_error_msg;
  489. nscp_error_msg = nscperror_lookup(nscp_error);
  490. if(nscp_error_msg){
  491. PR_SetError(0, 0);
  492. lmsg = nscp_error_msg;
  493. } else {
  494. util_snprintf(static_error, sizeof(static_error), "unknown error %d", nscp_error);
  495. lmsg = static_error;
  496. }
  497. } else {
  498. #if defined(XP_WIN32)
  499. msglen = FormatMessage(
  500. FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  501. NULL,
  502. GetLastError(),
  503. LOCALE_SYSTEM_DEFAULT,
  504. (LPTSTR)&sysmsg,
  505. 0,
  506. 0);
  507. if (msglen > 0)
  508. lmsg = sysmsg;
  509. else
  510. lmsg = system_winerr();
  511. SetLastError(0);
  512. #else
  513. /* replaced
  514. #if defined(SNI) || defined(LINUX)
  515. / C++ platform has no definition for sys_errlist /
  516. lmsg = strerror(errno);
  517. #else
  518. lmsg = sys_errlist[errno];
  519. #endif
  520. with lmsg =strerror(errno);*/
  521. lmsg=strerror(errno);
  522. errno = 0;
  523. #endif
  524. }
  525. /* At this point lmsg points to something. */
  526. msglen = strlen(lmsg);
  527. if (*buff == NULL)
  528. *buff = STRDUP(lmsg);
  529. else if (maxlen > msglen)
  530. memcpy(*buff, lmsg, msglen+1);
  531. else
  532. msglen = 0;
  533. #ifdef XP_WIN32
  534. /* NT's FormatMessage() dynamically allocated the msg; free it */
  535. if (sysmsg)
  536. LocalFree(sysmsg);
  537. #endif
  538. return msglen;
  539. }
  540. NSAPI_PUBLIC char *
  541. system_errmsg(void)
  542. {
  543. char *buff = 0;
  544. if (errmsg_key == -1)
  545. return "unknown early startup error";
  546. // rmaxwell - This is extremely lame.
  547. // Allocate a buffer in thread local storage to
  548. // hold the last error message.
  549. // The whole error message facility is broken and should be
  550. // updated to get error strings out of the code.
  551. if(!(buff = (char *) systhread_getdata(errmsg_key))) {
  552. buff = (char *) PERM_MALLOC(errbuf_size);
  553. systhread_setdata(errmsg_key, (void *)buff);
  554. }
  555. system_errmsg_fn(&buff, errbuf_size);
  556. if (buff == 0)
  557. buff = "Could not retrieve system error message";
  558. return buff;
  559. }
  560. NSAPI_PUBLIC int
  561. system_rename(char *oldpath, char *newpath)
  562. {
  563. return rename(oldpath, newpath);
  564. }
  565. NSAPI_PUBLIC int
  566. system_unlink(char *path)
  567. {
  568. return PR_Delete(path)==PR_FAILURE?-1:0;
  569. }
  570. NSAPI_PUBLIC int system_lseek(SYS_FILE fd, int off, int wh)
  571. {
  572. switch (wh) {
  573. case 0:
  574. return PR_Seek(fd, off, PR_SEEK_SET);
  575. break;
  576. case 1:
  577. return PR_Seek(fd, off, PR_SEEK_CUR);
  578. break;
  579. case 2:
  580. return PR_Seek(fd, off, PR_SEEK_END);
  581. break;
  582. default:
  583. return -1;
  584. }
  585. }
  586. NSAPI_PUBLIC int
  587. system_tlock(SYS_FILE fd)
  588. {
  589. return PR_TLockFile(fd);
  590. }
  591. NSAPI_PUBLIC int
  592. system_flock(SYS_FILE fd)
  593. {
  594. return PR_LockFile(fd);
  595. }
  596. NSAPI_PUBLIC int
  597. system_ulock(SYS_FILE fd)
  598. {
  599. return PR_UnlockFile(fd);
  600. }