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.

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