open.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*!
  2. * \file lib/gis/open.c
  3. *
  4. * \brief GIS Library - Open file functions
  5. *
  6. * (C) 1999-2015 by the GRASS Development Team
  7. *
  8. * This program is free software under the GNU General Public
  9. * License (>=v2). Read the file COPYING that comes with GRASS
  10. * for details.
  11. *
  12. * \author USACERL and many others
  13. */
  14. #include <grass/config.h>
  15. #include <errno.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18. #include <fcntl.h>
  19. #include <grass/gis.h>
  20. #include <grass/glocale.h>
  21. #include "gis_local_proto.h"
  22. /*!
  23. \brief Lowest level open routine.
  24. Opens the file <i>name</i> in <i>element</i> ("cell", etc.) in mapset <i>mapset</i>
  25. according to the i/o <i>mode</i>.
  26. - mode = 0 (read) will look for <i>name</i> in <i>mapset</i> and
  27. open the file for read only the file must exist
  28. - mode = 1 (write) will create an empty file <i>name</i> in the
  29. current mapset and open the file for write only
  30. <i>mapset</i> ignored
  31. - mode = 2 (read and write) will open a file in the current mapset
  32. for reading and writing creating a new file if
  33. necessary <i>mapset</i> ignored
  34. \param element database element name
  35. \param name map file name
  36. \param mapset mapset containing map <i>name</i>
  37. \param mode r/w mode 0=read, 1=write, 2=read/write
  38. \return open file descriptor (int)
  39. \return -1 could not open
  40. */
  41. static int G__open(const char *element,
  42. const char *name, const char *mapset, int mode)
  43. {
  44. int fd;
  45. int is_tmp;
  46. char path[GPATH_MAX];
  47. char xname[GNAME_MAX], xmapset[GMAPSET_MAX];
  48. G__check_gisinit();
  49. is_tmp = (element && strncmp(element, ".tmp", 3) == 0);
  50. /* READ */
  51. if (mode == 0) {
  52. if (G_name_is_fully_qualified(name, xname, xmapset)) {
  53. if (*mapset && strcmp(xmapset, mapset) != 0) {
  54. G_warning(_("G__open(read): mapset <%s> doesn't match xmapset <%s>"),
  55. mapset, xmapset);
  56. return -1;
  57. }
  58. name = xname;
  59. mapset = xmapset;
  60. }
  61. if (!is_tmp) {
  62. mapset = G_find_file2(element, name, mapset);
  63. if (!mapset)
  64. return -1;
  65. G_file_name(path, element, name, mapset);
  66. }
  67. else {
  68. G_file_name_tmp(path, element, name, mapset);
  69. }
  70. if ((fd = open(path, 0)) < 0)
  71. G_warning(_("G__open(read): Unable to open '%s': %s"),
  72. path, strerror(errno));
  73. return fd;
  74. }
  75. /* WRITE */
  76. if (mode == 1 || mode == 2) {
  77. mapset = G_mapset();
  78. if (G_name_is_fully_qualified(name, xname, xmapset)) {
  79. if (strcmp(xmapset, mapset) != 0) {
  80. G_warning(_("G__open(write): xmapset <%s> != G_mapset() <%s>"),
  81. xmapset, mapset);
  82. return -1;
  83. }
  84. name = xname;
  85. }
  86. if (*name && G_legal_filename(name) == -1)
  87. return -1;
  88. if (!is_tmp)
  89. G_file_name(path, element, name, mapset);
  90. else
  91. G_file_name_tmp(path, element, name, mapset);
  92. if (mode == 1 || access(path, 0) != 0) {
  93. if (is_tmp)
  94. G_make_mapset_element_tmp(element);
  95. else
  96. G_make_mapset_element(element);
  97. close(open(path, O_WRONLY | O_CREAT | O_TRUNC, 0666));
  98. }
  99. if ((fd = open(path, mode)) < 0)
  100. G_warning(_("G__open(write): Unable to open '%s': %s"),
  101. path, strerror(errno));
  102. return fd;
  103. }
  104. return -1;
  105. }
  106. /*!
  107. \brief Open a new database file
  108. Creates <i>name</i> in the current mapset and opens it
  109. for write only.
  110. The database file <i>name</i> under the <i>element</i> in the
  111. current mapset is created and opened for writing (but not reading).
  112. The UNIX open() routine is used to open the file. If the file does
  113. not exist, -1 is returned. Otherwise the file is positioned at the
  114. end of the file and the file descriptor from the open() is returned.
  115. \param element database element name
  116. \param name map file name
  117. \return open file descriptor (int)
  118. \return -1 could not open
  119. */
  120. int G_open_new(const char *element, const char *name)
  121. {
  122. return G__open(element, name, G_mapset(), 1);
  123. }
  124. /*!
  125. \brief Open a database file for reading
  126. The database file <i>name</i> under the <i>element</i> in the
  127. specified <i>mapset</i> is opened for reading (but not for writing).
  128. The UNIX open() routine is used to open the file. If the file does
  129. not exist, -1 is returned. Otherwise the file descriptor from the
  130. open() is returned.
  131. \param element database element name
  132. \param name map file name
  133. \param mapset mapset containing map <i>name</i>
  134. \return open file descriptor (int)
  135. \return -1 could not open
  136. */
  137. int G_open_old(const char *element, const char *name, const char *mapset)
  138. {
  139. return G__open(element, name, mapset, 0);
  140. }
  141. /*!
  142. \brief Open a database file for update
  143. The database file <i>name</i> under the <i>element</i> in the
  144. current mapset is opened for reading and writing. The UNIX open()
  145. routine is used to open the file. If the file does not exist, -1 is
  146. returned. Otherwise the file is positioned at the end of the file
  147. and the file descriptor from the open() is returned.
  148. \param element database element name
  149. \param name map file name
  150. \return open file descriptor (int)
  151. \return -1 could not open
  152. */
  153. int G_open_update(const char *element, const char *name)
  154. {
  155. int fd;
  156. fd = G__open(element, name, G_mapset(), 2);
  157. if (fd >= 0)
  158. lseek(fd, 0L, SEEK_END);
  159. return fd;
  160. }
  161. /*!
  162. \brief Open a new database file
  163. The database file <i>name</i> under the <i>element</i> in the
  164. current mapset is created and opened for writing (but not reading).
  165. The UNIX fopen() routine, with "w" write mode, is used to open the
  166. file. If the file does not exist, the NULL pointer is
  167. returned. Otherwise the file is positioned at the end of the file
  168. and the file descriptor from the fopen() is returned.
  169. \param element database element name
  170. \param name map file name
  171. \return open file descriptor (FILE *)
  172. \return NULL on error
  173. */
  174. FILE *G_fopen_new(const char *element, const char *name)
  175. {
  176. int fd;
  177. fd = G__open(element, name, G_mapset(), 1);
  178. if (fd < 0) {
  179. G_debug(1, "G_fopen_new(): element = %s, name = %s : NULL",
  180. element, name);
  181. return (FILE *) 0;
  182. }
  183. G_debug(2, "\tfile open: new (mode = w)");
  184. return fdopen(fd, "w");
  185. }
  186. /*!
  187. \brief Open a database file for reading
  188. The database file <i>name</i> under the <i>element</i> in the
  189. specified <i>mapset</i> is opened for reading (but not for writing).
  190. The UNIX fopen() routine, with "r" read mode, is used to open the
  191. file. If the file does not exist, the NULL pointer is
  192. returned. Otherwise the file descriptor from the fopen() is
  193. returned.
  194. \param element database element name
  195. \param name map file name
  196. \param mapset mapset name containing map <i>name</i>
  197. \return open file descriptor (FILE *)
  198. \return NULL on error
  199. */
  200. FILE *G_fopen_old(const char *element, const char *name, const char *mapset)
  201. {
  202. int fd;
  203. fd = G__open(element, name, mapset, 0);
  204. if (fd < 0)
  205. return (FILE *) NULL;
  206. G_debug(2, "\tfile open: read (mode = r)");
  207. return fdopen(fd, "r");
  208. }
  209. /*!
  210. \brief Open a database file for update (append mode)
  211. The database file <i>name</i> under the <i>element</i> in the
  212. current mapset is opened for for writing. The UNIX fopen() routine,
  213. with "a" append mode, is used to open the file. If the file does not
  214. exist, the NULL pointer is returned. Otherwise the file descriptor
  215. from the fopen() is returned.
  216. \param element database element name
  217. \param name map file name
  218. \return open file descriptor (FILE *)
  219. \return NULL on error
  220. */
  221. FILE *G_fopen_append(const char *element, const char *name)
  222. {
  223. int fd;
  224. fd = G__open(element, name, G_mapset(), 2);
  225. if (fd < 0)
  226. return (FILE *) 0;
  227. lseek(fd, 0L, SEEK_END);
  228. G_debug(2, "\tfile open: append (mode = a)");
  229. return fdopen(fd, "a");
  230. }
  231. /*!
  232. \brief Open a database file for update (r+ mode)
  233. The database file <i>name</i> under the <i>element</i> in the
  234. current mapset is opened for for writing. The UNIX fopen() routine,
  235. with "r+" append mode, is used to open the file. If the file does not
  236. exist, the NULL pointer is returned. Otherwise the file descriptor
  237. from the fopen() is returned.
  238. \param element database element name
  239. \param name map file name
  240. \return open file descriptor (FILE *)
  241. \return NULL on error
  242. */
  243. FILE *G_fopen_modify(const char *element, const char *name)
  244. {
  245. int fd;
  246. fd = G__open(element, name, G_mapset(), 2);
  247. if (fd < 0)
  248. return (FILE *) 0;
  249. lseek(fd, 0L, SEEK_END);
  250. G_debug(2, "\tfile open: modify (mode = r+)");
  251. return fdopen(fd, "r+");
  252. }