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.

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