file.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /*
  13. * file.c: system specific functions for reading/writing files
  14. *
  15. * See file.h for formal definitions of what these functions do
  16. *
  17. * Rob McCool
  18. */
  19. #include "base/file.h"
  20. #ifdef BSD_RLIMIT
  21. #include <sys/time.h>
  22. #include <sys/resource.h>
  23. #else
  24. #include <stdlib.h>
  25. #include <signal.h>
  26. #endif
  27. #include <prerror.h>
  28. #include "private/pprio.h"
  29. #include "prlock.h"
  30. extern "C" char *nscperror_lookup(int err);
  31. /* --- globals -------------------------------------------------------------*/
  32. /* PRFileDesc * SYS_ERROR_FD = NULL; */
  33. const int errbuf_size = 256;
  34. const unsigned int LOCKFILERANGE=0x7FFFFFFF;
  35. PRLock *_atomic_write_lock = NULL;
  36. /* --------------------------------- stat --------------------------------- */
  37. /* XXXMB - Can't convert to PR_GetFileInfo because we directly exported
  38. * the stat interface... Damn.
  39. */
  40. NSAPI_PUBLIC int system_stat(char *path, struct stat *finfo)
  41. {
  42. if(stat(path, finfo) == -1)
  43. return -1;
  44. if(S_ISREG(finfo->st_mode) && (path[strlen(path) - 1] == '/')) {
  45. /* File with trailing slash */
  46. errno = ENOENT;
  47. return -1;
  48. }
  49. return 0;
  50. }
  51. NSAPI_PUBLIC int system_fread(SYS_FILE fd, char *buf, int sz)
  52. {
  53. /* XXXMB - this is the *one* function which does return a length
  54. * instead of the IO_ERROR/IO_OKAY.
  55. */
  56. return PR_Read(fd, buf, sz);
  57. }
  58. NSAPI_PUBLIC int system_fwrite(SYS_FILE fd, char *buf, int sz) {
  59. int n,o,w;
  60. for(n=sz,o=0; n; n-=w,o+=w) {
  61. if((w = PR_Write(fd, &buf[o], n)) < 0)
  62. return IO_ERROR;
  63. }
  64. return IO_OKAY;
  65. }
  66. /* ---------------------------- Standard UNIX ----------------------------- */
  67. #include <sys/file.h> /* flock */
  68. NSAPI_PUBLIC int system_fwrite_atomic(SYS_FILE fd, char *buf, int sz)
  69. {
  70. int ret;
  71. #if 0
  72. if(flock(fd,LOCK_EX) == -1)
  73. return IO_ERROR;
  74. #endif
  75. ret = system_fwrite(fd,buf,sz);
  76. #if 0
  77. if(flock(fd,LOCK_UN) == -1)
  78. return IO_ERROR; /* ??? */
  79. #endif
  80. return ret;
  81. }
  82. /* -------------------------- system_nocoredumps -------------------------- */
  83. NSAPI_PUBLIC int system_nocoredumps(void)
  84. {
  85. #ifdef BSD_RLIMIT
  86. struct rlimit rl;
  87. rl.rlim_cur = 0;
  88. rl.rlim_max = 0;
  89. return setrlimit(RLIMIT_CORE, &rl);
  90. #else
  91. #define EXITFUNC exit
  92. signal(SIGQUIT, EXITFUNC);
  93. signal(SIGILL, EXITFUNC);
  94. signal(SIGTRAP, EXITFUNC);
  95. signal(SIGABRT, EXITFUNC);
  96. signal(SIGIOT, EXITFUNC);
  97. signal(SIGEMT, EXITFUNC);
  98. signal(SIGFPE, EXITFUNC);
  99. signal(SIGBUS, EXITFUNC);
  100. signal(SIGSEGV, EXITFUNC);
  101. signal(SIGSYS, EXITFUNC);
  102. return 0;
  103. #endif
  104. }
  105. /* --------------------------- file_setinherit ---------------------------- */
  106. NSAPI_PUBLIC int file_setinherit(SYS_FILE fd, int value)
  107. {
  108. int flags = 0;
  109. PRInt32 nativeFD;
  110. PRFileDesc *bottom = fd;
  111. while (bottom->lower != NULL) {
  112. bottom = bottom->lower;
  113. }
  114. nativeFD = PR_FileDesc2NativeHandle(bottom);
  115. #if 0
  116. fprintf(stderr, "\nInfo(file_setinherit): Native file descriptor is %d\n", nativeFD);
  117. #endif
  118. flags = fcntl(nativeFD, F_GETFD, 0);
  119. if(flags == -1)
  120. return -1;
  121. if(value)
  122. flags &= (~FD_CLOEXEC);
  123. else
  124. flags |= FD_CLOEXEC;
  125. fcntl(nativeFD, F_SETFD, flags);
  126. return 0;
  127. /* Comment out for ns security/ nspr integration (HACK for NOW)
  128. int flags = fcntl(PR_FileDesc2NativeHandle(fd), F_GETFD, 0);
  129. if(flags == -1)
  130. return -1;
  131. if(value)
  132. flags &= (~FD_CLOEXEC);
  133. else
  134. flags |= FD_CLOEXEC;
  135. fcntl(PR_FileDesc2NativeHandle(fd), F_SETFD, flags);
  136. return 0;
  137. */
  138. }
  139. NSAPI_PUBLIC SYS_FILE system_fopenRO(char *p)
  140. {
  141. SYS_FILE f = PR_Open(p, PR_RDONLY, 0);
  142. if (!f)
  143. return SYS_ERROR_FD;
  144. return f;
  145. }
  146. NSAPI_PUBLIC SYS_FILE system_fopenWA(char *p)
  147. {
  148. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_APPEND, 0644);
  149. if (!f)
  150. return SYS_ERROR_FD;
  151. return f;
  152. }
  153. NSAPI_PUBLIC SYS_FILE system_fopenRW(char *p)
  154. {
  155. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE, 0644);
  156. if (!f)
  157. return SYS_ERROR_FD;
  158. return f;
  159. }
  160. NSAPI_PUBLIC SYS_FILE system_fopenWT(char *p)
  161. {
  162. SYS_FILE f = PR_Open(p, PR_RDWR|PR_CREATE_FILE|PR_TRUNCATE, 0644);
  163. if (!f)
  164. return SYS_ERROR_FD;
  165. return f;
  166. }
  167. NSAPI_PUBLIC int system_fclose(SYS_FILE fd)
  168. {
  169. return (PR_Close(fd));
  170. }
  171. NSAPI_PUBLIC int file_notfound(void)
  172. {
  173. return (errno == ENOENT);
  174. }
  175. #if !defined(LINUX)
  176. extern char *sys_errlist[];
  177. #endif
  178. #define ERRMSG_SIZE 35
  179. #ifdef THREAD_ANY
  180. static int errmsg_key = -1;
  181. #include "systhr.h"
  182. /* Removed for ns security integration
  183. #include "xp_error.h"
  184. */
  185. #else /* THREAD_ANY */
  186. static char errmsg[ERRMSG_SIZE];
  187. #endif /* THREAD_ANY */
  188. #include "util.h"
  189. void system_errmsg_init(void)
  190. {
  191. if (errmsg_key == -1) {
  192. #if defined(THREAD_ANY)
  193. errmsg_key = systhread_newkey();
  194. #endif
  195. if (!_atomic_write_lock)
  196. _atomic_write_lock = PR_NewLock();
  197. }
  198. }
  199. NSAPI_PUBLIC int system_errmsg_fn(char **buff, size_t maxlen)
  200. {
  201. char static_error[128];
  202. char *lmsg = 0; /* Local message pointer */
  203. size_t msglen = 0;
  204. PRErrorCode nscp_error;
  205. nscp_error = PR_GetError();
  206. /* If there is a NSPR error, but it is "unknown", try to get the OSError
  207. * and use that instead.
  208. */
  209. if (nscp_error == PR_UNKNOWN_ERROR)
  210. errno = PR_GetOSError();
  211. if (nscp_error != 0 && nscp_error != PR_UNKNOWN_ERROR){
  212. char *nscp_error_msg;
  213. nscp_error_msg = nscperror_lookup(nscp_error);
  214. if(nscp_error_msg){
  215. PR_SetError(0, 0);
  216. lmsg = nscp_error_msg;
  217. } else {
  218. util_snprintf(static_error, sizeof(static_error), "unknown error %d", nscp_error);
  219. lmsg = static_error;
  220. }
  221. } else {
  222. lmsg=strerror(errno);
  223. errno = 0;
  224. }
  225. /* At this point lmsg points to something. */
  226. msglen = strlen(lmsg);
  227. if (*buff == NULL)
  228. *buff = STRDUP(lmsg);
  229. else if (maxlen > msglen)
  230. memcpy(*buff, lmsg, msglen+1);
  231. else
  232. msglen = 0;
  233. return msglen;
  234. }
  235. NSAPI_PUBLIC const char *
  236. system_errmsg(void)
  237. {
  238. char *buff = 0;
  239. if (errmsg_key == -1)
  240. return "unknown early startup error";
  241. // rmaxwell - This is extremely lame.
  242. // Allocate a buffer in thread local storage to
  243. // hold the last error message.
  244. // The whole error message facility is broken and should be
  245. // updated to get error strings out of the code.
  246. if(!(buff = (char *) systhread_getdata(errmsg_key))) {
  247. buff = (char *) PERM_MALLOC(errbuf_size);
  248. systhread_setdata(errmsg_key, (void *)buff);
  249. }
  250. system_errmsg_fn(&buff, errbuf_size);
  251. if (buff == 0)
  252. return "Could not retrieve system error message";
  253. return buff;
  254. }
  255. NSAPI_PUBLIC int
  256. system_rename(char *oldpath, char *newpath)
  257. {
  258. return rename(oldpath, newpath);
  259. }
  260. NSAPI_PUBLIC int
  261. system_unlink(char *path)
  262. {
  263. return PR_Delete(path)==PR_FAILURE?-1:0;
  264. }
  265. NSAPI_PUBLIC int system_lseek(SYS_FILE fd, int off, int wh)
  266. {
  267. switch (wh) {
  268. case 0:
  269. return PR_Seek(fd, off, PR_SEEK_SET);
  270. break;
  271. case 1:
  272. return PR_Seek(fd, off, PR_SEEK_CUR);
  273. break;
  274. case 2:
  275. return PR_Seek(fd, off, PR_SEEK_END);
  276. break;
  277. default:
  278. return -1;
  279. }
  280. }
  281. NSAPI_PUBLIC int
  282. system_tlock(SYS_FILE fd)
  283. {
  284. return PR_TLockFile(fd);
  285. }
  286. NSAPI_PUBLIC int
  287. system_flock(SYS_FILE fd)
  288. {
  289. return PR_LockFile(fd);
  290. }
  291. NSAPI_PUBLIC int
  292. system_ulock(SYS_FILE fd)
  293. {
  294. return PR_UnlockFile(fd);
  295. }