open.c 8.0 KB

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