1
0

file.cpp 7.6 KB

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