Пример #1
0
extern int
close(int fd)
{
	int		r;
	int		oerrno;
	struct stat	st;
	char		buf[PATH_MAX];

	if (fd >= 0 && fd < elementsof(exe) && exe[fd])
	{
		r = exe[fd]->test;
		exe[fd]->test = 0;
		if (r > 0 && !fstat(fd, &st) && st.st_ino == exe[fd]->ino)
		{
			if (r = sysclose(fd))
				return r;
			oerrno = errno;
			if (!stat(exe[fd]->path, &st) && st.st_ino == exe[fd]->ino)
			{
				snprintf(buf, sizeof(buf), "%s.exe", exe[fd]->path);
				sysrename(exe[fd]->path, buf);
			}
			errno = oerrno;
			return 0;
		}
	}
	return sysclose(fd);
}
Пример #2
0
extern int
chmod(const char* path, mode_t mode)
{
	int	r;
	int	oerrno;
	char	buf[PATH_MAX];

	if ((r = syschmod(path, mode)) && errno == ENOENT && execrate(path, buf, sizeof(buf), 0))
	{
		errno = oerrno;
		return syschmod(buf, mode);
	}
	if (!(r = syschmod(path, mode)) &&
	    (mode & (S_IXUSR|S_IXGRP|S_IXOTH)) &&
	    !suffix(path) &&
	    (strlen(path) + 4) < sizeof(buf))
	{
		oerrno = errno;
		if (!magic(path, NiL))
		{
			snprintf(buf, sizeof(buf), "%s.exe", path);
			sysrename(path, buf);
		}
		errno = oerrno;
	}
	return r;
}
Пример #3
0
/*
 * Perform the actual rename.  For ease of use under vms5.0, check to see if we
 * have delete-privilege for the file.  If not, try to set it.  Returns 0 iff
 * no error occurred; otherwise the corresponding RMS status code.
 */
static
doit(char *newspec, char *oldspec, GETPROT *prot_)
{
	unsigned status;
	int	modified = FALSE;
#define	DELETE_MASK	 ((XAB$M_NODEL << XAB$V_SYS)\
			| (XAB$M_NODEL << XAB$V_OWN)\
			| (XAB$M_NODEL << XAB$V_GRP)\
			| (XAB$M_NODEL << XAB$V_WLD))

#define	UNMASK(name,mask) if ((status = chprot(name, mask, 0)) == RMS$_NORMAL)\
				status = 0

	if (!cmpprot(prot_, "d")) {
		UNMASK(oldspec, prot_->p_mask & ~DELETE_MASK);
		if (status != 0)
			return (status);
		modified = TRUE;
	}
	if (!(status = sysrename(newspec, oldspec))) {
		if (modified)
			UNMASK(newspec, prot_->p_mask);
	}
	return (status);
}
Пример #4
0
extern int
rename(const char* fp, const char* tp)
{
	int	r;
	int	oerrno;
	char	fb[PATH_MAX];
	char	tb[PATH_MAX];

	oerrno = errno;
	if ((r = sysrename(fp, tp)) && errno == ENOENT && execrate(fp, fb, sizeof(fb), 1))
	{
		if (execrate(tp, tb, sizeof(tb), 1))
			tp = tb;
		errno = oerrno;
		r = sysrename(fb, tp);
	}
	return r;
}
Пример #5
0
static void
_writembox(Mailbox *mb, Mlock *lk)
{
	Dir *d;
	Message *m;
	String *tmp;
	int mode, errs;
	Biobuf *b;

	tmp = s_copy(mb->path);
	s_append(tmp, ".tmp");

	/*
	 * preserve old files permissions, if possible
	 */
	d = dirstat(mb->path);
	if(d != nil){
		mode = d->mode&0777;
		free(d);
	} else
		mode = MBOXMODE;

	sysremove(s_to_c(tmp));
	b = sysopen(s_to_c(tmp), "alc", mode);
	if(b == 0){
		fprint(2, "can't write temporary mailbox %s: %r\n", s_to_c(tmp));
		return;
	}

	logmsg("writing new mbox", nil);
	errs = 0;
	for(m = mb->root->part; m != nil; m = m->next){
		if(lk != nil)
			syslockrefresh(lk);
		if(m->deleted)
			continue;
		logmsg("writing", m);
		if(Bwrite(b, m->start, m->end - m->start) < 0)
			errs = 1;
		if(Bwrite(b, "\n", 1) < 0)
			errs = 1;
	}
	logmsg("wrote new mbox", nil);

	if(sysclose(b) < 0)
		errs = 1;

	if(errs){
		fprint(2, "error writing temporary mail file\n");
		s_free(tmp);
		return;
	}

	sysremove(mb->path);
	if(sysrename(s_to_c(tmp), mb->path) < 0)
		fprint(2, "%s: can't rename %s to %s: %r\n", argv0,
			s_to_c(tmp), mb->path);
	s_free(tmp);
	if(mb->d != nil)
		free(mb->d);
	mb->d = dirstat(mb->path);
}
Пример #6
0
//
//  read in the mailbox and parse into messages.
//
static char*
_readmbox(Mailbox *mb, int doplumb, Mlock *lk)
{
	int fd, n;
	String *tmp;
	Dir *d;
	static char err[128];
	Message *m, **l;
	Inbuf *inb;
	char *x;

	l = &mb->root->part;

	/*
	 *  open the mailbox.  If it doesn't exist, try the temporary one.
	 */
	n = 0;
retry:
	fd = open(mb->path, OREAD);
	if(fd < 0){
		rerrstr(err, sizeof(err));
		if(strstr(err, "exclusive lock") != 0 && n++ < 20){
			sleep(500);	/* wait for lock to go away */
			goto retry;
		}
		if(strstr(err, "exist") != 0){
			tmp = s_copy(mb->path);
			s_append(tmp, ".tmp");
			if(sysrename(s_to_c(tmp), mb->path) == 0){
				s_free(tmp);
				goto retry;
			}
			s_free(tmp);
		}
		return err;
	}

	/*
	 *  a new qid.path means reread the mailbox, while
	 *  a new qid.vers means read any new messages
	 */
	d = dirfstat(fd);
	if(d == nil){
		close(fd);
		errstr(err, sizeof(err));
		return err;
	}
	if(mb->d != nil){
		if(d->qid.path == mb->d->qid.path && d->qid.vers == mb->d->qid.vers){
			close(fd);
			free(d);
			return nil;
		}
		if(d->qid.path == mb->d->qid.path){
			while(*l != nil)
				l = &(*l)->next;
			seek(fd, mb->d->length, 0);
		}
		free(mb->d);
	}
	mb->d = d;
	mb->vers++;
	henter(PATH(0, Qtop), mb->name,
		(Qid){PATH(mb->id, Qmbox), mb->vers, QTDIR}, nil, mb);

	inb = emalloc(sizeof(Inbuf));
	inb->rptr = inb->wptr = inb->data;
	inb->fd = fd;

	//  read new messages
	snprint(err, sizeof err, "reading '%s'", mb->path);
	logmsg(err, nil);
	for(;;){
		if(lk != nil)
			syslockrefresh(lk);
		m = newmessage(mb->root);
		m->mallocd = 1;
		m->inmbox = 1;
		if(readmessage(m, inb) < 0){
			delmessage(mb, m);
			mb->root->subname--;
			break;
		}

		// merge mailbox versions
		while(*l != nil){
			if(memcmp((*l)->digest, m->digest, SHA1dlen) == 0){
				// matches mail we already read, discard
				logmsg("duplicate", *l);
				delmessage(mb, m);
				mb->root->subname--;
				m = nil;
				l = &(*l)->next;
				break;
			} else {
				// old mail no longer in box, mark deleted
				logmsg("disappeared", *l);
				if(doplumb)
					mailplumb(mb, *l, 1);
				(*l)->inmbox = 0;
				(*l)->deleted = 1;
				l = &(*l)->next;
			}
		}
		if(m == nil)
			continue;

		x = strchr(m->start, '\n');
		if(x == nil)
			m->header = m->end;
		else
			m->header = x + 1;
		m->mheader = m->mhend = m->header;
		parseunix(m);
		parse(m, 0, mb, 0);
		logmsg("new", m);

		/* chain in */
		*l = m;
		l = &m->next;
		if(doplumb)
			mailplumb(mb, m, 0);

	}
	logmsg("mbox read", nil);

	// whatever is left has been removed from the mbox, mark deleted
	while(*l != nil){
		if(doplumb)
			mailplumb(mb, *l, 1);
		(*l)->inmbox = 0;
		(*l)->deleted = 1;
		l = &(*l)->next;
	}

	close(fd);
	free(inb);
	return nil;
}
Пример #7
0
extern int
unlink(const char* path)
{
	int		r;
	int		drive;
	int		mask;
	int		suffix;
	int		stop;
	int		oerrno;
	unsigned long	base;
	char		buf[PATH_MAX];
	char		tmp[MAX_PATH];

#define DELETED_DIR_1	7
#define DELETED_DIR_2	16

	static char	deleted[] = "%c:\\temp\\.deleted\\%08x.%03x";

	static int	count = 0;

#if __CYGWIN__

	DWORD		fattr = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE;
	DWORD		share = FILE_SHARE_DELETE;
	HANDLE		hp;
	struct stat	st;
	char		nat[MAX_PATH];

	oerrno = errno;
	if (lstat(path, &st) || !S_ISREG(st.st_mode))
		goto try_unlink;
	cygwin_conv_to_full_win32_path(path, nat);
	if (!strncasecmp(nat + 1, ":\\temp\\", 7))
		goto try_unlink;
	drive = nat[0];
	path = (const char*)nat;
	for (;;)
	{
		hp = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
		if (hp != INVALID_HANDLE_VALUE)
		{
			CloseHandle(hp);
			errno = oerrno;
			return 0;
		}
		if (GetLastError() != ERROR_FILE_NOT_FOUND)
			break;
		if (path == (const char*)buf || !execrate(path, buf, sizeof(buf), 1))
		{
			errno = ENOENT;
			return -1;
		}
		path = (const char*)buf;
	}
#else
	if (sysaccess(path, 0))
#if _win32_botch_access
	{
		if (errno != ENOENT || !execrate(path, buf, sizeof(buf), 1) || sysaccess(buf, 0))
			return -1;
		path = (const char*)buf;
	}
#else
		return -1;
#endif
	drive = 'C':
#endif

	/*
	 * rename to a `deleted' path just in case the file is open
	 * otherwise directory readers may choke on phantom entries
	 */

	base = ((getuid() & 0xffff) << 16) | (time(NiL) & 0xffff);
	suffix = (getpid() & 0xfff) + count++;
	snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
	if (!sysrename(path, tmp))
	{
		path = (const char*)tmp;
		goto try_delete;
	}
	if (errno != ENOTDIR && errno != ENOENT)
		goto try_unlink;
	tmp[DELETED_DIR_2] = 0;
	if (sysaccess(tmp, 0))
	{
		mask = umask(0);
		tmp[DELETED_DIR_1] = 0;
		if (sysaccess(tmp, 0) && mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO))
		{
			umask(mask);
			goto try_unlink;
		}
		tmp[DELETED_DIR_1] = '\\';
		r = mkdir(tmp, S_IRWXU|S_IRWXG|S_IRWXO);
		umask(mask);
		if (r)
			goto try_unlink;
		errno = 0;
	}
	tmp[DELETED_DIR_2] = '\\';
	if (!errno && !sysrename(path, tmp))
	{
		path = (const char*)tmp;
		goto try_delete;
	}
#if !__CYGWIN__
	if (errno == ENOENT)
	{
#if !_win32_botch_access
		if (execrate(path, buf, sizeof(buf), 1) && !sysrename(buf, tmp))
			path = (const char*)tmp;
#endif
		goto try_unlink;
	}
#endif
	stop = suffix;
	do
	{
		snprintf(tmp, sizeof(tmp), deleted, drive, base, suffix);
		if (!sysrename(path, tmp))
		{
			path = (const char*)tmp;
			goto try_delete;
		}
		if (++suffix > 0xfff)
			suffix = 0;
	} while (suffix != stop);
 try_delete:
#if __CYGWIN__
	hp = CreateFile(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL);
	if (hp != INVALID_HANDLE_VALUE)
	{
		CloseHandle(hp);
		errno = oerrno;
		return 0;
	}
#endif
 try_unlink:
	errno = oerrno;
	return sysunlink(path);
}