file.cpp 17 KB

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