1
0

smbsharedfile.c 6.6 KB

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