/libanxt/file.c

https://github.com/jgraef/aNXT · C · 313 lines · 169 code · 19 blank · 125 comment · 37 complexity · 403083aa241b4baa9cc8d2ef786a597e MD5 · raw file

  1. /*
  2. libanxt/file.c
  3. aNXT - a NXt Toolkit
  4. Libraries and tools for LEGO Mindstorms NXT robots
  5. Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Lesser General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include <sys/types.h>
  18. #include <string.h>
  19. #include <stdarg.h>
  20. #include <anxt/nxt.h>
  21. #include <anxt/file.h>
  22. #include "private.h"
  23. /**
  24. * Opens a file for writing in fragmented mode
  25. * @param nxt NXT handle
  26. * @param file Filename
  27. * @param size How big the file should be
  28. * @return File handle
  29. * @note Use nxt_file_open
  30. */
  31. int nxt_file_open_write(nxt_t *nxt,const char *file,size_t size) {
  32. nxt_pack_start(nxt,0x81);
  33. nxt_pack_str(nxt,file,20);
  34. nxt_pack_dword(nxt,size);
  35. test(nxt_con_send(nxt));
  36. test(nxt_con_recv(nxt,4));
  37. test(nxt_unpack_start(nxt,0x81));
  38. if (nxt_unpack_error(nxt)==0) return nxt_unpack_byte(nxt);
  39. else return NXT_FAIL;
  40. }
  41. /**
  42. * Opens a file for writing in linear mode
  43. * @param nxt NXT handle
  44. * @param file Filename
  45. * @param size How big the file should be
  46. * @return File handle
  47. * @note Use nxt_file_open
  48. */
  49. int nxt_file_open_write_linear(nxt_t *nxt,const char *file,size_t size) {
  50. nxt_pack_start(nxt,0x89);
  51. nxt_pack_str(nxt,file,20);
  52. nxt_pack_dword(nxt,size);
  53. test(nxt_con_send(nxt));
  54. test(nxt_con_recv(nxt,4));
  55. test(nxt_unpack_start(nxt,0x89));
  56. if (nxt_unpack_error(nxt)==0) return nxt_unpack_byte(nxt);
  57. else return NXT_FAIL;
  58. }
  59. /**
  60. * Opens a file for appending data
  61. * @param nxt NXT handle
  62. * @param file Filename
  63. * @return File handle
  64. * @note Use nxt_file_open
  65. */
  66. int nxt_file_open_append(nxt_t *nxt,const char *file,size_t *avail) {
  67. nxt_pack_start(nxt,0x8C);
  68. nxt_pack_str(nxt,file,20);
  69. test(nxt_con_send(nxt));
  70. test(nxt_con_recv(nxt,4));
  71. test(nxt_unpack_start(nxt,0x8C));
  72. if (nxt_unpack_error(nxt)==0) {
  73. int handle = nxt_unpack_byte(nxt);
  74. if (avail!=NULL) *avail = nxt_unpack_dword(nxt);
  75. return handle;
  76. }
  77. else return NXT_FAIL;
  78. }
  79. /**
  80. * Opens a file on NXT for reading
  81. * @param nxt NXT handle
  82. * @param file Filename
  83. * @param filesize Reference for filesize
  84. * @return File handle
  85. * @note Use nxt_file_open
  86. */
  87. int nxt_file_open_read(nxt_t *nxt,const char *file,size_t *filesize) {
  88. nxt_pack_start(nxt,0x80);
  89. nxt_pack_str(nxt,file,20);
  90. test(nxt_con_send(nxt));
  91. test(nxt_con_recv(nxt,8));
  92. test(nxt_unpack_start(nxt,0x80));
  93. if (nxt_unpack_error(nxt)==0) {
  94. int handle = (int)nxt_unpack_byte(nxt);
  95. if (filesize!=NULL) *filesize = nxt_unpack_dword(nxt);
  96. return handle;
  97. }
  98. else return NXT_FAIL;
  99. }
  100. /**
  101. * Opens a file on NXT for writing
  102. * @param nxt NXT handle
  103. * @param file Filename
  104. * @param oflag Open flags
  105. * @param [size] How big the file should be
  106. * @return File handle
  107. * @note For fragmented and linear mode 'size' is the requested file size
  108. * @note For appending mode 'size' is a refernce for the available file size
  109. * @note For reading mode 'size' is a reference for the file size
  110. */
  111. int nxt_file_open(nxt_t *nxt,const char *file,int oflag,...) {
  112. va_list args;
  113. int handle = -1;
  114. va_start(args,oflag);
  115. if (FLAG_ISSET(oflag,NXT_OREAD)) handle = nxt_file_open_read(nxt,file,va_arg(args,size_t*));
  116. else if (FLAG_ISSET(oflag,NXT_OAPPND)) handle = nxt_file_open_append(nxt,file,va_arg(args,size_t*));
  117. else {
  118. if (FLAG_ISSET(oflag,NXT_OWOVER) && (handle = nxt_file_find_first(nxt,file,NULL,NULL))>=0) {
  119. nxt_file_close(nxt,handle);
  120. nxt_file_remove(nxt,file);
  121. handle = -1;
  122. }
  123. if (FLAG_ISSET(oflag,NXT_OWLINE)) handle = nxt_file_open_write_linear(nxt,file,va_arg(args,size_t));
  124. else if (FLAG_ISSET(oflag,NXT_OWFRAG)) handle = nxt_file_open_write(nxt,file,va_arg(args,size_t));
  125. }
  126. va_end(args);
  127. return handle;
  128. }
  129. /**
  130. * Reads data from file from NXT (Lowlevel)
  131. * @param nxt NXT handle
  132. * @param handle File handle
  133. * @param dest Buffer where to store data
  134. * @param count How many bytes to read (max: 59 bytes)
  135. * @return How many bytes read
  136. */
  137. static ssize_t nxt_file_read_low(nxt_t *nxt,int handle,void *dest,size_t count) {
  138. nxt_pack_start(nxt,0x82);
  139. nxt_pack_byte(nxt,handle);
  140. nxt_pack_word(nxt,count);
  141. test(nxt_con_send(nxt));
  142. test(nxt_con_recv(nxt,6+count));
  143. test(nxt_unpack_start(nxt,0x82));
  144. if (nxt_unpack_error(nxt)==0) {
  145. nxt_unpack_byte(nxt);
  146. count = nxt_unpack_word(nxt);
  147. memcpy(dest,nxt_unpack_mem(nxt,count),count);
  148. return count;
  149. }
  150. else return NXT_FAIL;
  151. }
  152. /**
  153. * Reads data from file from NXT
  154. * @param nxt NXT handle
  155. * @param handle File handle
  156. * @param dest Buffer to store red data in
  157. * @param count How many bytes to read
  158. * @return How many bytes red
  159. */
  160. ssize_t nxt_file_read(nxt_t *nxt,int handle,void *dest,size_t count) {
  161. int i;
  162. ssize_t partlen;
  163. int len = 0;
  164. for (i=0;i<count/50;i++) {
  165. partlen = nxt_file_read_low(nxt,handle,dest,50);
  166. if (partlen==-1) return NXT_FAIL;
  167. dest += partlen;
  168. len += partlen;
  169. }
  170. if ((partlen = nxt_file_read_low(nxt,handle,dest,count%50))==-1) return NXT_FAIL;
  171. len += partlen;
  172. return len;
  173. }
  174. /**
  175. * Writes data to file from NXT (Lowlevel)
  176. * @param nxt NXT handle
  177. * @param handle File handle
  178. * @param src Data to write in file
  179. * @param count How many bytes to write (max: 59 bytes)
  180. * @return How many bytes written
  181. */
  182. static ssize_t nxt_file_write_low(nxt_t *nxt,int handle,void *src,size_t count) {
  183. nxt_pack_start(nxt,0x83);
  184. nxt_pack_byte(nxt,handle);
  185. nxt_pack_mem(nxt,src,count);
  186. test(nxt_con_send(nxt));
  187. test(nxt_con_recv(nxt,6));
  188. test(nxt_unpack_start(nxt,0x83));
  189. if (nxt_unpack_error(nxt)==0) {
  190. nxt_unpack_byte(nxt);
  191. return nxt_unpack_word(nxt);
  192. }
  193. else return NXT_FAIL;
  194. }
  195. /**
  196. * Writes data to file from NXT
  197. * @param nxt NXT handle
  198. * @param handle File handle
  199. * @param src Data to write in file
  200. * @param count How many bytes to write
  201. * @return How many bytes written
  202. */
  203. ssize_t nxt_file_write(nxt_t *nxt,int handle,void *src,size_t count) {
  204. int i,partlen;
  205. int len = 0;
  206. for (i=0;i<count/50;i++) {
  207. partlen = nxt_file_write_low(nxt,handle,src,50);
  208. if (partlen==-1) return -1;
  209. src += partlen;
  210. len += partlen;
  211. }
  212. if ((partlen = nxt_file_write_low(nxt,handle,src,count%50))==-1) return NXT_FAIL;
  213. len += partlen;
  214. return len;
  215. }
  216. /**
  217. * Closes file from NXT
  218. * @param nxt NXT handle
  219. * @param handle File handle
  220. * @return Success?
  221. */
  222. int nxt_file_close(nxt_t *nxt,int handle) {
  223. nxt_pack_start(nxt,0x84);
  224. nxt_pack_byte(nxt,handle);
  225. test(nxt_con_send(nxt));
  226. test(nxt_con_recv(nxt,4));
  227. test(nxt_unpack_start(nxt,0x84));
  228. return nxt_unpack_error(nxt)==0?NXT_SUCC:NXT_FAIL;
  229. }
  230. /**
  231. * Removes file from NXT
  232. * @param nxt NXT handle
  233. * @param file Filename
  234. * @return Whether file could be removed
  235. */
  236. int nxt_file_remove(nxt_t *nxt,const char *file) {
  237. nxt_pack_start(nxt,0x85);
  238. nxt_pack_str(nxt,file,20);
  239. test(nxt_con_send(nxt));
  240. test(nxt_con_recv(nxt,23));
  241. test(nxt_unpack_start(nxt,0x85));
  242. return nxt_unpack_error(nxt)==0?NXT_SUCC:NXT_FAIL;
  243. }
  244. /**
  245. * Finds a file
  246. * @param nxt NXT handle
  247. * @param wildcard Wildcard to search for
  248. * @param filename Reference to store filename of found file as string
  249. * @param filesize Reference to store filesize of found file
  250. * @return File handle of found file
  251. * @note The pointer 'filename' can and should be passed to free()
  252. * @note If the file is not needed it should be passed to nxt_file_close()
  253. */
  254. int nxt_file_find_first(nxt_t *nxt,const char *wildcard,char **filename,size_t *filesize) {
  255. nxt_pack_start(nxt,0x86);
  256. nxt_pack_str(nxt,wildcard,20);
  257. test(nxt_con_send(nxt));
  258. test(nxt_con_recv(nxt,28));
  259. test(nxt_unpack_start(nxt,0x86));
  260. if (nxt_unpack_error(nxt)==0) {
  261. int handle = nxt_unpack_byte(nxt);
  262. if (filename!=NULL) *filename = strdup(nxt_unpack_str(nxt,20));
  263. if (filesize!=NULL) *filesize = nxt_unpack_dword(nxt);
  264. return handle;
  265. }
  266. else return NXT_FAIL;
  267. }
  268. /**
  269. * Finds a file
  270. * @param nxt NXT handle
  271. * @param handle Filehandle of previous found file
  272. * @param filename Reference to store filename of found file as string
  273. * @param filesize Reference to store filesize of found file
  274. * @return File handle of found file
  275. * @note The pointer 'filename' can and should be passed to free()
  276. * @note If the file is not needed it should be passed to nxt_file_close()
  277. */
  278. int nxt_file_find_next(nxt_t *nxt,int handle,char **filename,size_t *filesize) {
  279. nxt_pack_start(nxt,0x87);
  280. nxt_pack_byte(nxt,handle);
  281. test(nxt_con_send(nxt));
  282. test(nxt_con_recv(nxt,28));
  283. test(nxt_unpack_start(nxt,0x87));
  284. if (nxt_unpack_error(nxt)==0) {
  285. int handle = nxt_unpack_byte(nxt);
  286. if (filename!=NULL) *filename = strdup(nxt_unpack_str(nxt,20));
  287. if (filesize!=NULL) *filesize = nxt_unpack_dword(nxt);
  288. return handle;
  289. }
  290. else return NXT_FAIL;
  291. }