Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_tlsv12/sys/src/cmd/ip/imap4d/folder.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <auth.h>
5
#include "imap4d.h"
6
 
7
static	int	copyData(int ffd, int tfd, MbLock *ml);
8
static	MbLock	mLock =
9
{
10
	.fd = -1
11
};
12
 
13
static char curDir[MboxNameLen];
14
 
15
void
16
resetCurDir(void)
17
{
18
	curDir[0] = '\0';
19
}
20
 
21
int
22
myChdir(char *dir)
23
{
24
	if(strcmp(dir, curDir) == 0)
25
		return 0;
26
	if(dir[0] != '/' || strlen(dir) > MboxNameLen)
27
		return -1;
28
	strcpy(curDir, dir);
29
	if(chdir(dir) < 0){
30
		werrstr("mychdir failed: %r");
31
		return -1;
32
	}
33
	return 0;
34
}
35
 
36
int
37
cdCreate(char *dir, char *file, int mode, ulong perm)
38
{
39
	if(myChdir(dir) < 0)
40
		return -1;
41
	return create(file, mode, perm);
42
}
43
 
44
Dir*
45
cdDirstat(char *dir, char *file)
46
{
47
	if(myChdir(dir) < 0)
48
		return nil;
49
	return dirstat(file);
50
}
51
 
52
int
53
cdExists(char *dir, char *file)
54
{
55
	Dir *d;
56
 
57
	d = cdDirstat(dir, file);
58
	if(d == nil)
59
		return 0;
60
	free(d);
61
	return 1;
62
}
63
 
64
int
65
cdDirwstat(char *dir, char *file, Dir *d)
66
{
67
	if(myChdir(dir) < 0)
68
		return -1;
69
	return dirwstat(file, d);
70
}
71
 
72
int
73
cdOpen(char *dir, char *file, int mode)
74
{
75
	if(myChdir(dir) < 0)
76
		return -1;
77
	return open(file, mode);
78
}
79
 
80
int
81
cdRemove(char *dir, char *file)
82
{
83
	if(myChdir(dir) < 0)
84
		return -1;
85
	return remove(file);
86
}
87
 
88
/*
89
 * open the one true mail lock file
90
 */
91
MbLock*
92
mbLock(void)
93
{
94
	int i;
95
 
96
	if(mLock.fd >= 0)
97
		bye("mail lock deadlock");
98
	for(i = 0; i < 5; i++){
99
		mLock.fd = openLocked(mboxDir, "L.mbox", OREAD);
100
		if(mLock.fd >= 0)
101
			return &mLock;
102
		sleep(1000);
103
	}
104
	return nil;
105
}
106
 
107
void
108
mbUnlock(MbLock *ml)
109
{
110
	if(ml != &mLock)
111
		bye("bad mail unlock");
112
	if(ml->fd < 0)
113
		bye("mail unlock when not locked");
114
	close(ml->fd);
115
	ml->fd = -1;
116
}
117
 
118
void
119
mbLockRefresh(MbLock *ml)
120
{
121
	char buf[1];
122
 
123
	seek(ml->fd, 0, 0);
124
	read(ml->fd, buf, 1);
125
}
126
 
127
int
128
mbLocked(void)
129
{
130
	return mLock.fd >= 0;
131
}
132
 
133
char*
134
impName(char *name)
135
{
136
	char *s;
137
	int n;
138
 
139
	if(cistrcmp(name, "inbox") == 0)
140
		if(access("msgs", AEXIST) == 0)
141
			name = "msgs";
142
		else
143
			name = "mbox";
144
	n = strlen(name) + STRLEN(".imp") + 1;
145
	s = binalloc(&parseBin, n, 0);
146
	if(s == nil)
147
		return nil;
148
	snprint(s, n, "%s.imp", name);
149
	return s;
150
}
151
 
152
/*
153
 * massage the mailbox name into something valid
154
 * eliminates all .', and ..',s, redundatant and trailing /'s.
155
 */
156
char *
157
mboxName(char *s)
158
{
159
	char *ss;
160
 
161
	ss = mutf7str(s);
162
	if(ss == nil)
163
		return nil;
164
	cleanname(ss);
165
	return ss;
166
}
167
 
168
char *
169
strmutf7(char *s)
170
{
171
	char *m;
172
	int n;
173
 
174
	n = strlen(s) * MUtf7Max + 1;
175
	m = binalloc(&parseBin, n, 0);
176
	if(m == nil)
177
		return nil;
178
	if(encmutf7(m, n, s) < 0)
179
		return nil;
180
	return m;
181
}
182
 
183
char *
184
mutf7str(char *s)
185
{
186
	char *m;
187
	int n;
188
 
189
	/*
190
	 * n = strlen(s) * UTFmax / (2.67) + 1
191
	 * UTFMax / 2.67 == 3 / (8/3) == 9 / 8
192
	 */
193
	n = strlen(s);
194
	n = (n * 9 + 7) / 8 + 1;
195
	m = binalloc(&parseBin, n, 0);
196
	if(m == nil)
197
		return nil;
198
	if(decmutf7(m, n, s) < 0)
199
		return nil;
200
	return m;
201
}
202
 
203
void
204
splitr(char *s, int c, char **left, char **right)
205
{
206
	char *d;
207
	int n;
208
 
209
	n = strlen(s);
210
	d = binalloc(&parseBin, n + 1, 0);
211
	if(d == nil)
212
		parseErr("out of memory");
213
	strcpy(d, s);
214
	s = strrchr(d, c);
215
	if(s != nil){
216
		*left = d;
217
		*s++ = '\0';
218
		*right = s;
219
	}else{
220
		*right = d;
221
		*left = d + n;
222
	}
223
}
224
 
225
/*
226
 * create the mailbox and all intermediate components
227
 * a trailing / implies the new mailbox is a directory;
228
 * otherwise, it's a file.
229
 *
230
 * return with the file open for write, or directory open for read.
231
 */
232
int
233
createBox(char *mbox, int dir)
234
{
235
	char *m;
236
	int fd;
237
 
238
	fd = -1;
239
	for(m = mbox; *m; m++){
240
		if(*m == '/'){
241
			*m = '\0';
242
			if(access(mbox, AEXIST) < 0){
243
				if(fd >= 0)
244
					close(fd);
245
				fd = cdCreate(mboxDir, mbox, OREAD, DMDIR|0775);
246
				if(fd < 0)
247
					return -1;
248
			}
249
			*m = '/';
250
		}
251
	}
252
	if(dir)
253
		fd = cdCreate(mboxDir, mbox, OREAD, DMDIR|0775);
254
	else
255
		fd = cdCreate(mboxDir, mbox, OWRITE, 0664);
256
	return fd;
257
}
258
 
259
/*
260
 * move one mail folder to another
261
 * destination mailbox doesn't exist.
262
 * the source folder may be a directory or a mailbox,
263
 * and may be in the same directory as the destination,
264
 * or a completely different directory.
265
 */
266
int
267
moveBox(char *from, char *to)
268
{
269
	Dir *d;
270
	char *fd, *fe, *td, *te, *fimp;
271
 
272
	splitr(from, '/', &fd, &fe);
273
	splitr(to, '/', &td, &te);
274
 
275
	/*
276
	 * in the same directory: try rename
277
	 */
278
	d = cdDirstat(mboxDir, from);
279
	if(d == nil)
280
		return 0;
281
	if(strcmp(fd, td) == 0){
282
		nulldir(d);
283
		d->name = te;
284
		if(cdDirwstat(mboxDir, from, d) >= 0){
285
			fimp = impName(from);
286
			d->name = impName(te);
287
			cdDirwstat(mboxDir, fimp, d);
288
			free(d);
289
			return 1;
290
		}
291
	}
292
 
293
	/*
294
	 * directory copy is too hard for now
295
	 */
296
	if(d->mode & DMDIR)
297
		return 0;
298
	free(d);
299
 
300
	return copyBox(from, to, 1);
301
}
302
 
303
/*
304
 * copy the contents of one mailbox to another
305
 * either truncates or removes the source box if it succeeds.
306
 */
307
int
308
copyBox(char *from, char *to, int doremove)
309
{
310
	MbLock *ml;
311
	char *fimp, *timp;
312
	int ffd, tfd, ok;
313
 
314
	if(cistrcmp(from, "inbox") == 0)
315
		if(access("msgs", AEXIST) == 0)
316
			from = "msgs";
317
		else
318
			from = "mbox";
319
 
320
	ml = mbLock();
321
	if(ml == nil)
322
		return 0;
323
	ffd = openLocked(mboxDir, from, OREAD);
324
	if(ffd < 0){
325
		mbUnlock(ml);
326
		return 0;
327
	}
328
	tfd = createBox(to, 0);
329
	if(tfd < 0){
330
		mbUnlock(ml);
331
		close(ffd);
332
		return 0;
333
	}
334
 
335
	ok = copyData(ffd, tfd, ml);
336
	close(ffd);
337
	close(tfd);
338
	if(!ok){
339
		mbUnlock(ml);
340
		return 0;
341
	}
342
 
343
	fimp = impName(from);
344
	timp = impName(to);
345
	if(fimp != nil && timp != nil){
346
		ffd = cdOpen(mboxDir, fimp, OREAD);
347
		if(ffd >= 0){
348
			tfd = cdCreate(mboxDir, timp, OWRITE, 0664);
349
			if(tfd >= 0){
350
				copyData(ffd, tfd, ml);
351
				close(tfd);
352
			}
353
			close(ffd);
354
		}
355
	}
356
	cdRemove(mboxDir, fimp);
357
	if(doremove)
358
		cdRemove(mboxDir, from);
359
	else
360
		close(cdOpen(mboxDir, from, OWRITE|OTRUNC));
361
	mbUnlock(ml);
362
	return 1;
363
}
364
 
365
/*
366
 * copies while holding the mail lock,
367
 * then tries to copy permissions and group ownership
368
 */
369
static int
370
copyData(int ffd, int tfd, MbLock *ml)
371
{
372
	Dir *fd, td;
373
	char buf[BufSize];
374
	int n;
375
 
376
	for(;;){
377
		n = read(ffd, buf, BufSize);
378
		if(n <= 0){
379
			if(n < 0)
380
				return 0;
381
			break;
382
		}
383
		if(write(tfd, buf, n) != n)
384
			return 0;
385
		mbLockRefresh(ml);
386
	}
387
	fd = dirfstat(ffd);
388
	if(fd != nil){
389
		nulldir(&td);
390
		td.mode = fd->mode;
391
		if(dirfwstat(tfd, &td) >= 0){
392
			nulldir(&td);
393
			td.gid = fd->gid;
394
			dirfwstat(tfd, &td);
395
		}
396
	}
397
	return 1;
398
}