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.

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