smbsharedfile.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "headers.h"
  2. typedef struct SmbSharedFileEntry SmbSharedFileEntry;
  3. struct SmbSharedFileEntry {
  4. SmbSharedFile;
  5. Ref;
  6. SmbSharedFileEntry *next;
  7. };
  8. static struct {
  9. QLock;
  10. SmbSharedFileEntry *list;
  11. } sharedfiletable;
  12. typedef struct SmbLockListEntry SmbLockListEntry;
  13. struct SmbLockListEntry {
  14. SmbLock;
  15. SmbLockListEntry *next;
  16. };
  17. struct SmbLockList {
  18. SmbLockListEntry *head;
  19. };
  20. static int
  21. lockconflict(SmbLock *l1, SmbLock *l2)
  22. {
  23. return l1->base < l2->limit && l2->base < l1->limit;
  24. }
  25. static int
  26. lockorder(SmbLock *l1, SmbLock *l2)
  27. {
  28. if (l1->base < l2->base)
  29. return -1;
  30. if (l1->base > l2->base)
  31. return 1;
  32. if (l1->limit > l2->limit)
  33. return -1;
  34. if (l1->limit < l2->limit)
  35. return 1;
  36. return 0;
  37. }
  38. static void
  39. locklistfree(SmbLockList **llp)
  40. {
  41. SmbLockList *ll = *llp;
  42. if (ll) {
  43. while (ll->head) {
  44. SmbLockListEntry *next = ll->head->next;
  45. free(ll->head);
  46. ll->head = next;
  47. }
  48. free(ll);
  49. *llp = nil;
  50. }
  51. }
  52. int
  53. smbsharedfilelock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit)
  54. {
  55. SmbLockListEntry smblock;
  56. SmbLockListEntry *l, *nl, **lp;
  57. smblock.s = s;
  58. smblock.pid = pid;
  59. smblock.base = base;
  60. smblock.limit = limit;
  61. if (sf->locklist) {
  62. for (l = sf->locklist->head; l; l = l->next)
  63. if (lockconflict(l, &smblock)) {
  64. smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) failed because conflicts with [%lld, %lld)\n",
  65. base, limit, l->base, l->limit);
  66. return 0;
  67. }
  68. }
  69. if (sf->locklist == nil)
  70. sf->locklist = smbemallocz(sizeof(SmbLockList), 1);
  71. for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next)
  72. if (lockorder(&smblock, l) <= 0)
  73. break;
  74. smblogprintif(smbglobals.log.locks, "smbsharedfilelock: lock [%lld, %lld) succeeded\n", base, limit);
  75. nl = smbemalloc(sizeof(*nl));
  76. *nl = smblock;
  77. nl->next = *lp;
  78. *lp = nl;
  79. //{
  80. // smblogprintif(smbglobals.log.locks,"smbsharedfilelock: list\n");
  81. // for (l = sf->locklist->head; l; l = l->next)
  82. // smblogprintif(smbglobals.log.locks, "smbsharedfilelock: [%lld, %lld)\n", l->base, l->limit);
  83. //}
  84. return 1;
  85. }
  86. int
  87. smbsharedfileunlock(SmbSharedFile *sf, SmbSession *s, ushort pid, vlong base, vlong limit)
  88. {
  89. SmbLockListEntry smblock;
  90. SmbLockListEntry *l, **lp;
  91. smblock.s = s;
  92. smblock.pid = pid;
  93. smblock.base = base;
  94. smblock.limit = limit;
  95. if (sf->locklist == nil)
  96. goto failed;
  97. for (lp = &sf->locklist->head; (l = *lp) != nil; lp = &l->next) {
  98. if (l->s != s || l->pid != pid)
  99. continue;
  100. switch (lockorder(&smblock, l)) {
  101. case 0:
  102. *lp = l->next;
  103. free(l);
  104. smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) succeeded\n", base, limit);
  105. return 1;
  106. case -1:
  107. goto failed;
  108. }
  109. }
  110. failed:
  111. smblogprintif(smbglobals.log.locks, "smbsharedfilelock: unlock [%lld, %lld) failed\n", base, limit);
  112. return 0;
  113. }
  114. static int
  115. p9denied(int p9mode, int share)
  116. {
  117. //smblogprint(-1, "p9denied(%d, %d)\n", p9mode, share);
  118. if (share == SMB_OPEN_MODE_SHARE_EXCLUSIVE)
  119. return 1;
  120. switch (p9mode & 3) {
  121. case OREAD:
  122. case OEXEC:
  123. if (share == SMB_OPEN_MODE_SHARE_DENY_READOREXEC)
  124. return 1;
  125. break;
  126. case OWRITE:
  127. if (share == SMB_OPEN_MODE_SHARE_DENY_WRITE)
  128. return 1;
  129. break;
  130. case ORDWR:
  131. if (share != SMB_OPEN_MODE_SHARE_DENY_NONE)
  132. return 1;
  133. break;
  134. }
  135. return 0;
  136. }
  137. static void
  138. sharesplit(int share, int *denyread, int *denywrite)
  139. {
  140. switch (share) {
  141. case SMB_OPEN_MODE_SHARE_EXCLUSIVE:
  142. *denyread = 1;
  143. *denywrite = 1;
  144. break;
  145. case SMB_OPEN_MODE_SHARE_DENY_READOREXEC:
  146. *denyread = 1;
  147. *denywrite = 0;
  148. break;
  149. case SMB_OPEN_MODE_SHARE_DENY_WRITE:
  150. *denywrite = 0;
  151. *denywrite = 1;
  152. break;
  153. default:
  154. *denyread = 0;
  155. *denywrite = 0;
  156. }
  157. }
  158. static int
  159. sharemake(int denyread, int denywrite)
  160. {
  161. if (denyread)
  162. if (denywrite)
  163. return SMB_OPEN_MODE_SHARE_EXCLUSIVE;
  164. else
  165. return SMB_OPEN_MODE_SHARE_DENY_READOREXEC;
  166. else if (denywrite)
  167. return SMB_OPEN_MODE_SHARE_DENY_WRITE;
  168. else
  169. return SMB_OPEN_MODE_SHARE_DENY_NONE;
  170. }
  171. static ushort
  172. sharesubtract(int share1, int share2)
  173. {
  174. int dr1, dw1;
  175. int dr2, dw2;
  176. sharesplit(share1, &dr1, &dw1);
  177. sharesplit(share2, &dr2, &dw2);
  178. if (dw2)
  179. dw1 = 0;
  180. if (dr2)
  181. dr1 = 0;
  182. return sharemake(dr1, dw1);
  183. }
  184. static int
  185. shareadd(int share1, int share2)
  186. {
  187. int dr1, dw1;
  188. int dr2, dw2;
  189. sharesplit(share1, &dr1, &dw1);
  190. sharesplit(share2, &dr2, &dw2);
  191. if (dw2)
  192. dw1 = 1;
  193. if (dr2)
  194. dr1 = 1;
  195. return sharemake(dr1, dw1);
  196. }
  197. SmbSharedFile *
  198. smbsharedfileget(Dir *d, int p9mode, int *sharep)
  199. {
  200. SmbSharedFileEntry *sfe;
  201. qlock(&sharedfiletable);
  202. for (sfe = sharedfiletable.list; sfe; sfe = sfe->next) {
  203. if (sfe->type == d->type && sfe->dev == d->dev && sfe->path == d->qid.path) {
  204. if (p9denied(p9mode, sfe->share)) {
  205. qunlock(&sharedfiletable);
  206. return nil;
  207. }
  208. *sharep = sharesubtract(*sharep, sfe->share);
  209. sfe->share = shareadd(sfe->share, *sharep);
  210. sfe->ref++;
  211. goto done;
  212. }
  213. }
  214. sfe = smbemallocz(sizeof(SmbSharedFileEntry), 1);
  215. sfe->type = d->type;
  216. sfe->dev = d->dev;
  217. sfe->path = d->qid.path;
  218. // sfe->name = smbestrdup(name);
  219. sfe->ref = 1;
  220. sfe->share = *sharep;
  221. sfe->next = sharedfiletable.list;
  222. sharedfiletable.list = sfe;
  223. done:
  224. smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileget: ref %d share %d\n",
  225. sfe->ref, sfe->share);
  226. qunlock(&sharedfiletable);
  227. return sfe;
  228. }
  229. void
  230. smbsharedfileput(SmbFile *f, SmbSharedFile *sf, int share)
  231. {
  232. SmbSharedFileEntry *sfe, **sfep;
  233. qlock(&sharedfiletable);
  234. for (sfep = &sharedfiletable.list; (sfe = *sfep) != nil; sfep = &sfe->next) {
  235. if (sfe == sf) {
  236. sfe->ref--;
  237. if (sfe->ref == 0) {
  238. *sfep = sfe->next;
  239. if (sfe->deleteonclose && f)
  240. smbremovefile(f->t, nil, f->name);
  241. smblogprintif(smbglobals.log.sharedfiles, "smbsharedfileput: removed\n");
  242. locklistfree(&sfe->locklist);
  243. free(sfe);
  244. }
  245. else {
  246. sfe->share = sharesubtract(sfe->share, share);
  247. smblogprintif(smbglobals.log.sharedfiles,
  248. "smbsharedfileput: ref %d share %d\n", sfe->ref, sfe->share);
  249. }
  250. break;
  251. }
  252. }
  253. qunlock(&sharedfiletable);
  254. }