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