PageRenderTime 3635ms CodeModel.GetById 28ms RepoModel.GetById 3ms app.codeStats 1ms

/src/fileio.c

https://bitbucket.org/rizon/ircd/
C | 299 lines | 224 code | 45 blank | 30 comment | 53 complexity | 59e2b6a28b0ca7742e8565c84012e3fd MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /*
  2. * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
  3. * fileio.c: Provides a file input-output interface to ircd.
  4. *
  5. * Copyright (C) 2002 by the past and present ircd coders, and others.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  20. * USA
  21. *
  22. * $Id: fileio.c 147 2005-12-26 02:52:10Z jon $
  23. */
  24. #include "stdinc.h"
  25. #include "fileio.h"
  26. #include "irc_string.h"
  27. #include "memory.h"
  28. #include "s_log.h"
  29. /* The following are to get the fd manipulation routines. eww. */
  30. #include "fdlist.h"
  31. /*
  32. * Wrappers around open() / close() for fileio, since a whole bunch of
  33. * code that should be using the fbopen() / fbclose() code isn't.
  34. * Grr. -- adrian
  35. */
  36. int
  37. file_open(fde_t * F, const char *filename, int mode, int fmode)
  38. {
  39. int fd;
  40. #ifdef _WIN32
  41. DWORD dwDesiredAccess = 0;
  42. switch (mode & ~(O_CREAT | O_TRUNC | O_APPEND))
  43. {
  44. case O_RDONLY:
  45. dwDesiredAccess = GENERIC_READ;
  46. break;
  47. case O_WRONLY:
  48. dwDesiredAccess = GENERIC_WRITE;
  49. break;
  50. case O_RDWR:
  51. dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
  52. }
  53. fd = (int) CreateFile(filename,
  54. dwDesiredAccess,
  55. FILE_SHARE_READ | ((dwDesiredAccess & GENERIC_WRITE) ? 0 :
  56. FILE_SHARE_WRITE), NULL,
  57. ((mode & O_CREAT) ==
  58. 0) ? OPEN_EXISTING : ((mode & O_TRUNC) ? CREATE_ALWAYS :
  59. OPEN_ALWAYS), FILE_ATTRIBUTE_NORMAL, NULL);
  60. if(fd == (int) INVALID_HANDLE_VALUE)
  61. {
  62. errno = GetLastError();
  63. return -1;
  64. }
  65. if((mode & O_APPEND))
  66. SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);
  67. #else
  68. if(number_fd == hard_fdlimit)
  69. {
  70. errno = ENFILE;
  71. return -1;
  72. }
  73. if((fd = open(filename, mode, fmode)) < 0)
  74. return -1;
  75. #endif
  76. fd_open(F, fd, 0, filename);
  77. return 0;
  78. }
  79. void
  80. file_close(fde_t * F)
  81. {
  82. fd_close(F);
  83. }
  84. FBFILE *
  85. fbopen(const char *filename, const char *mode)
  86. {
  87. FBFILE *fb = MyMalloc(sizeof(FBFILE));
  88. int openmode = 0;
  89. int pmode = 0;
  90. while(*mode)
  91. switch (*mode++)
  92. {
  93. case 'r':
  94. openmode = O_RDONLY;
  95. break;
  96. case 'w':
  97. openmode = O_WRONLY | O_CREAT | O_TRUNC;
  98. pmode = 0644;
  99. break;
  100. case 'a':
  101. openmode = O_WRONLY | O_CREAT | O_APPEND;
  102. pmode = 0644;
  103. break;
  104. case '+':
  105. openmode &= ~(O_RDONLY | O_WRONLY);
  106. openmode |= O_RDWR;
  107. }
  108. if(file_open(&fb->F, filename, openmode, pmode) < 0)
  109. {
  110. MyFree(fb);
  111. return NULL;
  112. }
  113. fb->ptr = fb->endp = fb->buf;
  114. fb->flags = 0;
  115. fb->pbptr = NULL;
  116. return fb;
  117. }
  118. int
  119. fbrewind(FBFILE * fb)
  120. {
  121. fb->ptr = fb->endp = fb->buf;
  122. fb->flags = 0;
  123. fb->pbptr = NULL;
  124. #ifdef _WIN32
  125. SetFilePointer((HANDLE) fb->F.fd, 0, NULL, FILE_BEGIN);
  126. #else
  127. lseek(fb->F.fd, 0, SEEK_SET);
  128. #endif
  129. return 0;
  130. }
  131. void
  132. fbclose(FBFILE * fb)
  133. {
  134. if(fb == NULL)
  135. return;
  136. file_close(&fb->F);
  137. MyFree(fb);
  138. }
  139. static int
  140. fbfill(FBFILE * fb)
  141. {
  142. int n;
  143. if(fb->flags)
  144. return -1;
  145. #ifdef _WIN32
  146. if(!ReadFile((HANDLE) fb->F.fd, fb->buf, BUFSIZ, (LPDWORD) & n, NULL))
  147. n = -1;
  148. #else
  149. n = read(fb->F.fd, fb->buf, BUFSIZ);
  150. #endif
  151. if(n > 0)
  152. {
  153. fb->ptr = fb->buf;
  154. fb->endp = fb->buf + n;
  155. }
  156. else if(n < 0)
  157. fb->flags |= FB_FAIL;
  158. else
  159. fb->flags |= FB_EOF;
  160. return n;
  161. }
  162. int
  163. fbgetc(FBFILE * fb)
  164. {
  165. if(fb->pbptr != NULL)
  166. if((fb->pbptr == (fb->pbuf + BUFSIZ)) || !*fb->pbptr)
  167. fb->pbptr = NULL;
  168. if(fb->ptr < fb->endp || fbfill(fb) > 0)
  169. return *fb->ptr++;
  170. return EOF;
  171. }
  172. void
  173. fbungetc(char c, FBFILE * fb)
  174. {
  175. if(fb->pbptr == NULL)
  176. fb->pbptr = fb->pbuf + BUFSIZ;
  177. if(fb->pbptr != fb->pbuf)
  178. *--fb->pbptr = c;
  179. }
  180. char *
  181. fbgets(char *buf, size_t len, FBFILE * fb)
  182. {
  183. char *p = buf;
  184. assert(0 < len);
  185. if(fb->pbptr != NULL)
  186. {
  187. strlcpy(buf, fb->pbptr, len);
  188. fb->pbptr = NULL;
  189. return buf;
  190. }
  191. if(fb->ptr == fb->endp && fbfill(fb) < 1)
  192. return NULL;
  193. --len;
  194. while(len--)
  195. {
  196. *p = *fb->ptr++;
  197. if('\n' == *p)
  198. {
  199. ++p;
  200. break;
  201. }
  202. /* deal with CR's */
  203. else if('\r' == *p)
  204. {
  205. if(fb->ptr < fb->endp || fbfill(fb) > 0)
  206. {
  207. if('\n' == *fb->ptr)
  208. ++fb->ptr;
  209. }
  210. *p++ = '\n';
  211. break;
  212. }
  213. ++p;
  214. if(fb->ptr == fb->endp && fbfill(fb) < 1)
  215. break;
  216. }
  217. *p = '\0';
  218. return buf;
  219. }
  220. int
  221. fbputs(const char *str, FBFILE * fb, size_t nbytes)
  222. {
  223. int n = -1;
  224. if(0 == fb->flags)
  225. {
  226. assert(strlen(str) == nbytes);
  227. #ifdef _WIN32
  228. if(!WriteFile((HANDLE) fb->F.fd, str, nbytes, (LPDWORD) & n, NULL))
  229. n = -1;
  230. #else
  231. n = write(fb->F.fd, str, nbytes);
  232. #endif
  233. if(n == -1)
  234. fb->flags |= FB_FAIL;
  235. }
  236. return n;
  237. }
  238. int
  239. save_spare_fd(const char *spare_purpose)
  240. {
  241. int spare_fd = open(PATH_DEVNULL, O_RDONLY, 0);
  242. if(spare_fd < 0)
  243. {
  244. ilog(L_NOTICE, "Failed to reserve low fd for %s - open failed", spare_purpose);
  245. return -1;
  246. }
  247. else if(spare_fd > 255)
  248. {
  249. ilog(L_NOTICE, "Failed to reserve low fd for %s - too high", spare_purpose);
  250. close(spare_fd);
  251. return -1;
  252. }
  253. return spare_fd;
  254. }