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.

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