You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

410 lines
7.6 KiB

  1. #define _FILE_OFFSET_BITS 64
  2. #include "fuse_attr.h"
  3. #include "fuse_dirent.h"
  4. #include "fuse_direntplus.h"
  5. #include "fuse_dirents.h"
  6. #include "fuse_entry.h"
  7. #include "linux_dirent64.h"
  8. #include "stat_utils.h"
  9. #include <dirent.h>
  10. #include <errno.h>
  11. #include <stddef.h>
  12. #include <stdint.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. /* 32KB - same as glibc getdents buffer size */
  17. #define DEFAULT_SIZE (1024 * 32)
  18. static
  19. uint64_t
  20. align_uint64_t(uint64_t v_)
  21. {
  22. return ((v_ + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1));
  23. }
  24. static
  25. uint64_t
  26. fuse_dirent_size(const uint64_t namelen_)
  27. {
  28. uint64_t rv;
  29. rv = offsetof(fuse_dirent_t,name);
  30. rv += namelen_;
  31. rv = align_uint64_t(rv);
  32. return rv;
  33. }
  34. static
  35. uint64_t
  36. fuse_direntplus_size(const uint64_t namelen_)
  37. {
  38. uint64_t rv;
  39. rv = offsetof(fuse_direntplus_t,dirent.name);
  40. rv += namelen_;
  41. rv = align_uint64_t(rv);
  42. return rv;
  43. }
  44. static
  45. int
  46. fuse_dirents_buf_resize(fuse_dirents_t *d_,
  47. uint64_t size_)
  48. {
  49. void *p;
  50. if((d_->data_len + size_) >= d_->buf_len)
  51. {
  52. p = realloc(d_->buf,(d_->buf_len * 2));
  53. if(p == NULL)
  54. return -errno;
  55. d_->buf = p;
  56. d_->buf_len *= 2;
  57. }
  58. return 0;
  59. }
  60. static
  61. void*
  62. fuse_dirents_dirent_alloc(fuse_dirents_t *d_,
  63. uint64_t namelen_)
  64. {
  65. int rv;
  66. uint64_t size;
  67. fuse_dirent_t *d;
  68. size = fuse_dirent_size(namelen_);
  69. rv = fuse_dirents_buf_resize(d_,size);
  70. if(rv)
  71. return NULL;
  72. d = (fuse_dirent_t*)&d_->buf[d_->data_len];
  73. d_->data_len += size;
  74. return d;
  75. }
  76. static
  77. void*
  78. fuse_dirents_direntplus_alloc(fuse_dirents_t *d_,
  79. uint64_t namelen_)
  80. {
  81. int rv;
  82. uint64_t size;
  83. fuse_dirent_t *d;
  84. size = fuse_direntplus_size(namelen_);
  85. rv = fuse_dirents_buf_resize(d_,size);
  86. if(rv)
  87. return NULL;
  88. d = (fuse_dirent_t*)&d_->buf[d_->data_len];
  89. d_->data_len += size;
  90. return d;
  91. }
  92. static
  93. void
  94. fuse_dirents_fill_attr(fuse_attr_t *attr_,
  95. const struct stat *st_)
  96. {
  97. attr_->ino = st_->st_ino;
  98. attr_->size = st_->st_size;
  99. attr_->blocks = st_->st_blocks;
  100. attr_->atime = st_->st_atime;
  101. attr_->mtime = st_->st_mtime;
  102. attr_->ctime = st_->st_ctime;
  103. attr_->atimensec = ST_ATIM_NSEC(st_);
  104. attr_->mtimensec = ST_MTIM_NSEC(st_);
  105. attr_->ctimensec = ST_CTIM_NSEC(st_);
  106. attr_->mode = st_->st_mode;
  107. attr_->nlink = st_->st_nlink;
  108. attr_->uid = st_->st_uid;
  109. attr_->gid = st_->st_gid;
  110. attr_->rdev = st_->st_rdev;
  111. attr_->blksize = st_->st_blksize;
  112. }
  113. fuse_dirent_t*
  114. fuse_dirent_next(fuse_dirent_t *cur_)
  115. {
  116. char *buf;
  117. buf = (char*)cur_;
  118. buf += fuse_dirent_size(cur_->namelen);
  119. return (fuse_dirent_t*)buf;
  120. }
  121. fuse_direntplus_t*
  122. fuse_direntplus_next(fuse_direntplus_t *cur_)
  123. {
  124. char *buf;
  125. buf = (char*)cur_;
  126. buf += fuse_direntplus_size(cur_->dirent.namelen);
  127. return (fuse_direntplus_t*)buf;
  128. }
  129. fuse_dirent_t*
  130. fuse_dirent_find(fuse_dirents_t *d_,
  131. const uint64_t ino_)
  132. {
  133. fuse_dirent_t *cur;
  134. fuse_dirent_t *end;
  135. if(d_->type != NORMAL)
  136. return NULL;
  137. cur = (fuse_dirent_t*)&d_->buf[0];
  138. end = (fuse_dirent_t*)&d_->buf[d_->data_len];
  139. while(cur < end)
  140. {
  141. if(cur->ino == ino_)
  142. return cur;
  143. cur = fuse_dirent_next(cur);
  144. }
  145. return NULL;
  146. }
  147. fuse_direntplus_t*
  148. fuse_direntplus_find(fuse_dirents_t *d_,
  149. const uint64_t ino_)
  150. {
  151. fuse_direntplus_t *cur;
  152. fuse_direntplus_t *end;
  153. if(d_->type != PLUS)
  154. return NULL;
  155. cur = (fuse_direntplus_t*)&d_->buf[0];
  156. end = (fuse_direntplus_t*)&d_->buf[d_->data_len];
  157. while(cur < end)
  158. {
  159. if(cur->dirent.ino == ino_)
  160. return cur;
  161. cur = fuse_direntplus_next(cur);
  162. }
  163. return NULL;
  164. }
  165. void*
  166. fuse_dirents_find(fuse_dirents_t *d_,
  167. const uint64_t ino_)
  168. {
  169. switch(d_->type)
  170. {
  171. default:
  172. case UNSET:
  173. return NULL;
  174. case NORMAL:
  175. return fuse_dirent_find(d_,ino_);
  176. case PLUS:
  177. return fuse_direntplus_find(d_,ino_);
  178. }
  179. }
  180. int
  181. fuse_dirents_convert_plus2normal(fuse_dirents_t *d_)
  182. {
  183. return -ENOSYS;
  184. }
  185. int
  186. fuse_dirents_add(fuse_dirents_t *d_,
  187. const struct dirent *dirent_,
  188. const uint64_t namelen_)
  189. {
  190. fuse_dirent_t *d;
  191. switch(d_->type)
  192. {
  193. case UNSET:
  194. d_->type = NORMAL;
  195. break;
  196. case NORMAL:
  197. break;
  198. case PLUS:
  199. return -EINVAL;
  200. }
  201. d = fuse_dirents_dirent_alloc(d_,namelen_);
  202. if(d == NULL)
  203. return -ENOMEM;
  204. d->off = kv_size(d_->offs);
  205. kv_push(uint32_t,d_->offs,d_->data_len);
  206. d->ino = dirent_->d_ino;
  207. d->namelen = namelen_;
  208. d->type = dirent_->d_type;
  209. memcpy(d->name,dirent_->d_name,namelen_);
  210. return 0;
  211. }
  212. int
  213. fuse_dirents_add_plus(fuse_dirents_t *d_,
  214. const struct dirent *dirent_,
  215. const uint64_t namelen_,
  216. const fuse_entry_t *entry_,
  217. const struct stat *st_)
  218. {
  219. fuse_direntplus_t *d;
  220. switch(d_->type)
  221. {
  222. case UNSET:
  223. d_->type = PLUS;
  224. break;
  225. case NORMAL:
  226. return -EINVAL;
  227. case PLUS:
  228. break;
  229. }
  230. d = fuse_dirents_direntplus_alloc(d_,namelen_);
  231. if(d == NULL)
  232. return -ENOMEM;
  233. d->dirent.off = kv_size(d_->offs);
  234. kv_push(uint32_t,d_->offs,d_->data_len);
  235. d->dirent.ino = dirent_->d_ino;
  236. d->dirent.namelen = namelen_;
  237. d->dirent.type = dirent_->d_type;
  238. memcpy(d->dirent.name,dirent_->d_name,namelen_);
  239. d->entry = *entry_;
  240. fuse_dirents_fill_attr(&d->attr,st_);
  241. return 0;
  242. }
  243. int
  244. fuse_dirents_add_linux(fuse_dirents_t *d_,
  245. const struct linux_dirent64 *dirent_,
  246. const uint64_t namelen_)
  247. {
  248. fuse_dirent_t *d;
  249. switch(d_->type)
  250. {
  251. case UNSET:
  252. d_->type = NORMAL;
  253. break;
  254. case NORMAL:
  255. break;
  256. case PLUS:
  257. return -EINVAL;
  258. }
  259. d = fuse_dirents_dirent_alloc(d_,namelen_);
  260. if(d == NULL)
  261. return -ENOMEM;
  262. d->off = kv_size(d_->offs);
  263. kv_push(uint32_t,d_->offs,d_->data_len);
  264. d->ino = dirent_->ino;
  265. d->namelen = namelen_;
  266. d->type = dirent_->type;
  267. memcpy(d->name,dirent_->name,namelen_);
  268. return 0;
  269. }
  270. int
  271. fuse_dirents_add_linux_plus(fuse_dirents_t *d_,
  272. const struct linux_dirent64 *dirent_,
  273. const uint64_t namelen_,
  274. const fuse_entry_t *entry_,
  275. const struct stat *st_)
  276. {
  277. fuse_direntplus_t *d;
  278. switch(d_->type)
  279. {
  280. case UNSET:
  281. d_->type = PLUS;
  282. break;
  283. case NORMAL:
  284. return -EINVAL;
  285. case PLUS:
  286. break;
  287. }
  288. d = fuse_dirents_direntplus_alloc(d_,namelen_);
  289. if(d == NULL)
  290. return -ENOMEM;
  291. d->dirent.off = kv_size(d_->offs);
  292. kv_push(uint32_t,d_->offs,d_->data_len);
  293. d->dirent.ino = dirent_->ino;
  294. d->dirent.namelen = namelen_;
  295. d->dirent.type = dirent_->type;
  296. memcpy(d->dirent.name,dirent_->name,namelen_);
  297. d->entry = *entry_;
  298. fuse_dirents_fill_attr(&d->attr,st_);
  299. return 0;
  300. }
  301. void
  302. fuse_dirents_reset(fuse_dirents_t *d_)
  303. {
  304. d_->data_len = 0;
  305. d_->type = UNSET;
  306. kv_size(d_->offs) = 1;
  307. }
  308. int
  309. fuse_dirents_init(fuse_dirents_t *d_)
  310. {
  311. void *buf;
  312. buf = calloc(DEFAULT_SIZE,1);
  313. if(buf == NULL)
  314. return -ENOMEM;
  315. d_->buf = buf;
  316. d_->buf_len = DEFAULT_SIZE;
  317. d_->data_len = 0;
  318. d_->type = UNSET;
  319. kv_init(d_->offs);
  320. kv_resize(uint32_t,d_->offs,64);
  321. kv_push(uint32_t,d_->offs,0);
  322. return 0;
  323. }
  324. void
  325. fuse_dirents_free(fuse_dirents_t *d_)
  326. {
  327. d_->buf_len = 0;
  328. d_->data_len = 0;
  329. d_->type = UNSET;
  330. kv_destroy(d_->offs);
  331. free(d_->buf);
  332. }