util_file.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
  3. * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
  4. *
  5. * This program is free software; you can redistribute it and/or modify it under
  6. * the terms of the GNU General Public License as published by the Free
  7. * Software Foundation; either version 2 of the License, or (at your option)
  8. * any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along with
  16. * this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #include "includes.h"
  20. extern int DEBUGLEVEL;
  21. #if 0
  22. static int gotalarm;
  23. /***************************************************************
  24. Signal function to tell us we timed out.
  25. ****************************************************************/
  26. static void gotalarm_sig(void)
  27. {
  28. gotalarm = 1;
  29. }
  30. /***************************************************************
  31. Lock or unlock a fd for a known lock type. Abandon after waitsecs
  32. seconds.
  33. ****************************************************************/
  34. BOOL do_file_lock(int fd, int waitsecs, int type)
  35. {
  36. SMB_STRUCT_FLOCK lock;
  37. int ret;
  38. gotalarm = 0;
  39. CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
  40. lock.l_type = type;
  41. lock.l_whence = SEEK_SET;
  42. lock.l_start = 0;
  43. lock.l_len = 1;
  44. lock.l_pid = 0;
  45. alarm(waitsecs);
  46. ret = fcntl(fd, SMB_F_SETLKW, &lock);
  47. alarm(0);
  48. CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
  49. if (gotalarm) {
  50. DEBUG(0, ("do_file_lock: failed to %s file.\n",
  51. type == F_UNLCK ? "unlock" : "lock"));
  52. return False;
  53. }
  54. return (ret == 0);
  55. }
  56. /***************************************************************
  57. Lock an fd. Abandon after waitsecs seconds.
  58. ****************************************************************/
  59. BOOL file_lock(int fd, int type, int secs, int *plock_depth)
  60. {
  61. if (fd < 0)
  62. return False;
  63. (*plock_depth)++;
  64. if ((*plock_depth) == 0)
  65. {
  66. if (!do_file_lock(fd, secs, type)) {
  67. DEBUG(10,("file_lock: locking file failed, error = %s.\n",
  68. strerror(errno)));
  69. return False;
  70. }
  71. }
  72. return True;
  73. }
  74. /***************************************************************
  75. Unlock an fd. Abandon after waitsecs seconds.
  76. ****************************************************************/
  77. BOOL file_unlock(int fd, int *plock_depth)
  78. {
  79. BOOL ret=True;
  80. if(*plock_depth == 1)
  81. ret = do_file_lock(fd, 5, F_UNLCK);
  82. (*plock_depth)--;
  83. if(!ret)
  84. DEBUG(10,("file_unlock: unlocking file failed, error = %s.\n",
  85. strerror(errno)));
  86. return ret;
  87. }
  88. /***************************************************************
  89. locks a file for enumeration / modification.
  90. update to be set = True if modification is required.
  91. ****************************************************************/
  92. void *startfilepwent(char *pfile, char *s_readbuf, int bufsize,
  93. int *file_lock_depth, BOOL update)
  94. {
  95. FILE *fp = NULL;
  96. if (!*pfile)
  97. {
  98. DEBUG(0, ("startfilepwent: No file set\n"));
  99. return (NULL);
  100. }
  101. DEBUG(10, ("startfilepwent: opening file %s\n", pfile));
  102. fp = sys_fopen(pfile, update ? "r+b" : "rb");
  103. if (fp == NULL) {
  104. DEBUG(0, ("startfilepwent: unable to open file %s\n", pfile));
  105. return NULL;
  106. }
  107. /* Set a buffer to do more efficient reads */
  108. setvbuf(fp, s_readbuf, _IOFBF, bufsize);
  109. if (!file_lock(fileno(fp), (update ? F_WRLCK : F_RDLCK), 5, file_lock_depth))
  110. {
  111. DEBUG(0, ("startfilepwent: unable to lock file %s\n", pfile));
  112. fclose(fp);
  113. return NULL;
  114. }
  115. /* Make sure it is only rw by the owner */
  116. chmod(pfile, 0600);
  117. /* We have a lock on the file. */
  118. return (void *)fp;
  119. }
  120. /***************************************************************
  121. End enumeration of the file.
  122. ****************************************************************/
  123. void endfilepwent(void *vp, int *file_lock_depth)
  124. {
  125. FILE *fp = (FILE *)vp;
  126. file_unlock(fileno(fp), file_lock_depth);
  127. fclose(fp);
  128. DEBUG(7, ("endfilepwent: closed file.\n"));
  129. }
  130. /*************************************************************************
  131. Return the current position in the file list as an SMB_BIG_UINT.
  132. This must be treated as an opaque token.
  133. *************************************************************************/
  134. SMB_BIG_UINT getfilepwpos(void *vp)
  135. {
  136. return (SMB_BIG_UINT)sys_ftell((FILE *)vp);
  137. }
  138. /*************************************************************************
  139. Set the current position in the file list from an SMB_BIG_UINT.
  140. This must be treated as an opaque token.
  141. *************************************************************************/
  142. BOOL setfilepwpos(void *vp, SMB_BIG_UINT tok)
  143. {
  144. return !sys_fseek((FILE *)vp, (SMB_OFF_T)tok, SEEK_SET);
  145. }
  146. /*************************************************************************
  147. gets a line out of a file.
  148. line is of format "xxxx:xxxxxx:xxxxx:".
  149. lines with "#" at the front are ignored.
  150. *************************************************************************/
  151. int getfileline(void *vp, char *linebuf, int linebuf_size)
  152. {
  153. /* Static buffers we will return. */
  154. FILE *fp = (FILE *)vp;
  155. unsigned char c;
  156. unsigned char *p;
  157. size_t linebuf_len;
  158. if (fp == NULL)
  159. {
  160. DEBUG(0,("getfileline: Bad file pointer.\n"));
  161. return -1;
  162. }
  163. /*
  164. * Scan the file, a line at a time.
  165. */
  166. while (!feof(fp))
  167. {
  168. linebuf[0] = '\0';
  169. fgets(linebuf, linebuf_size, fp);
  170. if (ferror(fp))
  171. {
  172. return -1;
  173. }
  174. /*
  175. * Check if the string is terminated with a newline - if not
  176. * then we must keep reading and discard until we get one.
  177. */
  178. linebuf_len = strlen(linebuf);
  179. if (linebuf[linebuf_len - 1] != '\n')
  180. {
  181. c = '\0';
  182. while (!ferror(fp) && !feof(fp))
  183. {
  184. c = fgetc(fp);
  185. if (c == '\n')
  186. {
  187. break;
  188. }
  189. }
  190. }
  191. else
  192. {
  193. linebuf[linebuf_len - 1] = '\0';
  194. }
  195. #ifdef DEBUG_PASSWORD
  196. DEBUG(100, ("getfileline: got line |%s|\n", linebuf));
  197. #endif
  198. if ((linebuf[0] == 0) && feof(fp))
  199. {
  200. DEBUG(4, ("getfileline: end of file reached\n"));
  201. return 0;
  202. }
  203. if (linebuf[0] == '#' || linebuf[0] == '\0')
  204. {
  205. DEBUG(6, ("getfileline: skipping comment or blank line\n"));
  206. continue;
  207. }
  208. p = (unsigned char *) strchr(linebuf, ':');
  209. if (p == NULL)
  210. {
  211. DEBUG(0, ("getfileline: malformed line entry (no :)\n"));
  212. continue;
  213. }
  214. return linebuf_len;
  215. }
  216. return -1;
  217. }
  218. #endif /* 0 */
  219. /****************************************************************************
  220. read a line from a file with possible \ continuation chars.
  221. Blanks at the start or end of a line are stripped.
  222. The string will be allocated if s2 is NULL
  223. ****************************************************************************/
  224. char *fgets_slash(char *s2,int maxlen,FILE *f)
  225. {
  226. char *s=s2;
  227. int len = 0;
  228. int c;
  229. BOOL start_of_line = True;
  230. if (feof(f))
  231. return(NULL);
  232. if (!s2)
  233. {
  234. maxlen = MIN(maxlen,8);
  235. s = (char *)Realloc(s,maxlen);
  236. }
  237. if (!s || maxlen < 2) return(NULL);
  238. *s = 0;
  239. while (len < maxlen-1)
  240. {
  241. c = getc(f);
  242. switch (c)
  243. {
  244. case '\r':
  245. break;
  246. case '\n':
  247. while (len > 0 && s[len-1] == ' ')
  248. {
  249. s[--len] = 0;
  250. }
  251. if (len > 0 && s[len-1] == '\\')
  252. {
  253. s[--len] = 0;
  254. start_of_line = True;
  255. break;
  256. }
  257. return(s);
  258. case EOF:
  259. if (len <= 0 && !s2)
  260. free(s);
  261. return(len>0?s:NULL);
  262. case ' ':
  263. if (start_of_line)
  264. break;
  265. default:
  266. start_of_line = False;
  267. s[len++] = c;
  268. s[len] = 0;
  269. }
  270. if (!s2 && len > maxlen-3)
  271. {
  272. maxlen *= 2;
  273. s = (char *)Realloc(s,maxlen);
  274. if (!s) return(NULL);
  275. }
  276. }
  277. return(s);
  278. }