📄 folder.c
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include <auth.h>#include "imap4d.h"static int copyData(int ffd, int tfd, MbLock *ml);static MbLock mLock ={ .fd = -1};static char curDir[MboxNameLen];voidresetCurDir(void){ curDir[0] = '\0';}intmyChdir(char *dir){ if(strcmp(dir, curDir) == 0) return 0; if(dir[0] != '/' || strlen(dir) > MboxNameLen) return -1; strcpy(curDir, dir); if(chdir(dir) < 0){ werrstr("mychdir failed: %r"); return -1; } return 0;}intcdCreate(char *dir, char *file, int mode, ulong perm){ if(myChdir(dir) < 0) return -1; return create(file, mode, perm);}Dir*cdDirstat(char *dir, char *file){ if(myChdir(dir) < 0) return nil; return dirstat(file);}intcdExists(char *dir, char *file){ Dir *d; d = cdDirstat(dir, file); if(d == nil) return 0; free(d); return 1;}intcdDirwstat(char *dir, char *file, Dir *d){ if(myChdir(dir) < 0) return -1; return dirwstat(file, d);}intcdOpen(char *dir, char *file, int mode){ if(myChdir(dir) < 0) return -1; return open(file, mode);}intcdRemove(char *dir, char *file){ if(myChdir(dir) < 0) return -1; return remove(file);}/* * open the one true mail lock file */MbLock*mbLock(void){ if(mLock.fd >= 0) bye("mail lock deadlock"); mLock.fd = openLocked(mboxDir, "L.mbox", OREAD); if(mLock.fd >= 0) return &mLock; return nil;}voidmbUnlock(MbLock *ml){ if(ml != &mLock) bye("bad mail unlock"); if(ml->fd < 0) bye("mail unlock when not locked"); close(ml->fd); ml->fd = -1;}voidmbLockRefresh(MbLock *ml){ char buf[1]; seek(ml->fd, 0, 0); read(ml->fd, buf, 1);}intmbLocked(void){ return mLock.fd >= 0;}char*impName(char *name){ char *s; int n; if(cistrcmp(name, "inbox") == 0) name = "mbox"; n = strlen(name) + STRLEN(".imp") + 1; s = binalloc(&parseBin, n, 0); if(s == nil) return nil; snprint(s, n, "%s.imp", name); return s;}/* * massage the mailbox name into something valid * eliminates all .', and ..',s, redundatant and trailing /'s. */char *mboxName(char *s){ char *ss; ss = mutf7str(s); if(ss == nil) return nil; cleanname(ss); return ss;}char *strmutf7(char *s){ char *m; int n; n = strlen(s) * MUtf7Max + 1; m = binalloc(&parseBin, n, 0); if(m == nil) return nil; if(encmutf7(m, n, s) < 0) return nil; return m;}char *mutf7str(char *s){ char *m; int n; /* * n = strlen(s) * UTFmax / (2.67) + 1 * UTFMax / 2.67 == 3 / (8/3) == 9 / 8 */ n = strlen(s); n = (n * 9 + 7) / 8 + 1; m = binalloc(&parseBin, n, 0); if(m == nil) return nil; if(decmutf7(m, n, s) < 0) return nil; return m;}voidsplitr(char *s, int c, char **left, char **right){ char *d; int n; n = strlen(s); d = binalloc(&parseBin, n + 1, 0); if(d == nil) parseErr("out of memory"); strcpy(d, s); s = strrchr(d, c); if(s != nil){ *left = d; *s++ = '\0'; *right = s; }else{ *right = d; *left = d + n; }}/* * create the mailbox and all intermediate components * a trailing / implies the new mailbox is a directory; * otherwise, it's a file. * * return with the file open for write, or directory open for read. */intcreateBox(char *mbox, int dir){ char *m; int fd; fd = -1; for(m = mbox; *m; m++){ if(*m == '/'){ *m = '\0'; if(access(mbox, AEXIST) < 0){ if(fd >= 0) close(fd); fd = cdCreate(mboxDir, mbox, OREAD, DMDIR|0775); if(fd < 0) return -1; } *m = '/'; } } if(dir) fd = cdCreate(mboxDir, mbox, OREAD, DMDIR|0775); else fd = cdCreate(mboxDir, mbox, OWRITE, 0664); return fd;}/* * move one mail folder to another * destination mailbox doesn't exist. * the source folder may be a directory or a mailbox, * and may be in the same directory as the destination, * or a completely different directory. */intmoveBox(char *from, char *to){ Dir *d; char *fd, *fe, *td, *te, *fimp; splitr(from, '/', &fd, &fe); splitr(to, '/', &td, &te); /* * in the same directory: try rename */ d = cdDirstat(mboxDir, from); if(d == nil) return 0; if(strcmp(fd, td) == 0){ nulldir(d); d->name = te; if(cdDirwstat(mboxDir, from, d) >= 0){ fimp = impName(from); d->name = impName(te); cdDirwstat(mboxDir, fimp, d); free(d); return 1; } } /* * directory copy is too hard for now */ if(d->mode & DMDIR) return 0; free(d); return copyBox(from, to, 1);}/* * copy the contents of one mailbox to another * either truncates or removes the source box if it succeeds. */intcopyBox(char *from, char *to, int doremove){ MbLock *ml; char *fimp, *timp; int ffd, tfd, ok; if(cistrcmp(from, "inbox") == 0) from = "mbox"; ml = mbLock(); if(ml == nil) return 0; ffd = openLocked(mboxDir, from, OREAD); if(ffd < 0){ mbUnlock(ml); return 0; } tfd = createBox(to, 0); if(tfd < 0){ mbUnlock(ml); close(ffd); return 0; } ok = copyData(ffd, tfd, ml); close(ffd); close(tfd); if(!ok){ mbUnlock(ml); return 0; } fimp = impName(from); timp = impName(to); if(fimp != nil && timp != nil){ ffd = cdOpen(mboxDir, fimp, OREAD); if(ffd >= 0){ tfd = cdCreate(mboxDir, timp, OWRITE, 0664); if(tfd >= 0){ copyData(ffd, tfd, ml); close(tfd); } close(ffd); } } cdRemove(mboxDir, fimp); if(doremove) cdRemove(mboxDir, from); else close(cdOpen(mboxDir, from, OWRITE|OTRUNC)); mbUnlock(ml); return 1;}/* * copies while holding the mail lock, * then tries to copy permissions and group ownership */static intcopyData(int ffd, int tfd, MbLock *ml){ Dir *fd, td; char buf[BufSize]; int n; for(;;){ n = read(ffd, buf, BufSize); if(n <= 0){ if(n < 0) return 0; break; } if(write(tfd, buf, n) != n) return 0; mbLockRefresh(ml); } fd = dirfstat(ffd); if(fd != nil){ nulldir(&td); td.mode = fd->mode; if(dirfwstat(tfd, &td) >= 0){ nulldir(&td); td.gid = fd->gid; dirfwstat(tfd, &td); } } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -