示例#1
0
static FILE *open_and_lock_cached_policy_file(const char *filename,
					      int *readwrite)
{
	int fd;
	int save_errno;

	*readwrite=1;
	fd=open(filename, O_RDWR | O_CREAT, 0644);

	if (fd >= 0 && ll_lock_ex(fd) >= 0)
	{
		FILE *fp=fdopen(fd, "r+");

		if (fp)
			return fp;
	}

	/*
	** Non-root will not be able to write to the cache.
	**
	** Do not pollute terminal output, but if this is run from the
	** script let's bark this somewhere where someone will hopefully
	** notice this.
	*/
	save_errno=errno;
	if (!isatty(2))
	{
		errno=save_errno;
		perror(filename);
	}
	if (fd >= 0)
		close(fd);

	*readwrite=0;
	fd=open(filename, O_RDONLY);

	if (fd >= 0 && ll_lockfd(fd, ll_readlock|ll_whence_start|ll_wait,
				 0, 0) >= 0)
	{
		FILE *fp=fdopen(fd, "r");

		if (fp)
			return fp;
	}

	if (fd >= 0)
		close(fd);
	return NULL;
}
示例#2
0
static int ll_mail_open_do(struct ll_mail *p, int ro)
{
	char *dotlock;
	char myidbuf[IDBUFSIZE];
	int save_errno;
	int fd;

	getid(myidbuf);

	if (p->dotlock) /* Already locked */
	{
		fd=open(p->file, ro ? O_RDONLY:O_RDWR);

		if (fd >= 0 &&
		    (ll_lockfd(fd, ro ? ll_readlock:ll_writelock, 0, 0) < 0 ||
		     fcntl(fd, F_SETFD, FD_CLOEXEC) < 0))
		{
			close(fd);
			fd= -1;
		}
		return fd;
	}

	if ((dotlock=malloc(strlen(p->file)+sizeof(".lock"))) == NULL)
		return -1;

	strcat(strcpy(dotlock, p->file), ".lock");

	if (try_mail_dotlock(dotlock, myidbuf) == 0)
	{
		fd=open(p->file, ro ? O_RDONLY:O_RDWR);

		if (fd >= 0 &&
		    (ll_lockfd(fd, ro ? ll_readlock:ll_writelock, 0, 0) ||
		     fcntl(fd, F_SETFD, FD_CLOEXEC) < 0))
		{
			close(fd);
			fd= -1;
		}

		p->dotlock=dotlock;
		return fd;
	}

	save_errno=errno;

	/*
	** Last fallback: for EEXIST, a read-only lock should suffice
	** In all other instances, we'll fallback to read/write or read-only
	** flock as last resort.
	*/

	if ((errno == EEXIST && ro) || errno == EPERM || errno == EACCES)
	{
		fd=open(p->file, ro ? O_RDONLY:O_RDWR);

		if (fd >= 0)
		{
			if (ll_lockfd(fd, ro ? ll_readlock:ll_writelock,
				      0, 0) == 0 &&
			    fcntl(fd, F_SETFD, FD_CLOEXEC) == 0)
			{
				free(dotlock);
				return fd;
			}
			close(fd);
		}
	}

	/*
	** If try_dotlock blew up for anything other than EEXIST, we don't
	** know what the deal is, so punt.
	*/

	if (save_errno != EEXIST)
	{
		free(dotlock);
		return (-1);
	}

	dotlock_exists(dotlock, myidbuf, 300);
	free(dotlock);
	return (-1);
}
示例#3
0
int ll_mail_lock(struct ll_mail *p)
{
	struct stat stat_buf;
	char idbuf[IDBUFSIZE];
	char idbuf2[IDBUFSIZE];

	char fn[NUMBUFSIZE*2 + 20];
	char *f;
	int fd;

	getid(idbuf);

	if (p->cclientfd >= 0)
		return 0;

	if (stat(p->file, &stat_buf) < 0)
		return -1;

	if (snprintf(fn, sizeof(fn), "/tmp/.%lx.%lx",
		     (unsigned long)stat_buf.st_dev,
		     (unsigned long)stat_buf.st_ino) < 0)
	{
		errno=ENOSPC;
		return (-1);
	}

	if ((f=strdup(fn)) == NULL)
		return (-1);

	/* We do things a bit differently.  First, try O_EXCL */

	if ((fd=open(f, O_RDWR|O_CREAT|O_EXCL, 0644)) >= 0)
	{
		struct stat stat_buf2;

		if (ll_lockfd(fd, ll_writelock, ll_whence_start, 0) < 0 ||
		    fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
		    writeid(idbuf, fd) < 0)
		{
			/* This shouldn't happen */

			close(fd);
			free(f);
			return (-1);
		}

		/* Rare race condition: */

		if (fstat(fd, &stat_buf) < 0 ||
		    lstat(f, &stat_buf2) < 0 ||
		    stat_buf.st_dev != stat_buf2.st_dev ||
		    stat_buf.st_ino != stat_buf2.st_ino)
		{
			errno=EAGAIN;
			close(fd);
			free(f);
			return (-1);
		}

		p->cclientfd=fd;
		p->cclientfile=f;
		return 0;
	}

	/*
	** An existing lockfile.  See if it's tagged with another
	** pid on this server, which no longer exists.
	*/

	if ((fd=open(f, O_RDONLY)) >= 0)
	{
		pid_t p=-1;

		if (readid(idbuf2, fd) == 0 &&
		    (p=getpidid(idbuf2, idbuf)) != 0 &&
		    kill(p, 0) < 0 && errno == ESRCH)
		{
			errno=EAGAIN;
			close(fd);
			unlink(f); /* Don't try again right away */
			free(f);
			return (-1);
		}

		/* If we can't lock, someone must have it open, game over. */

		if (p == getpid() /* It's us! */

		    || ll_lockfd(fd, ll_readlock, ll_whence_start, 0) < 0)
		{
			errno=EEXIST;
			close(fd);
			free(f);
			return (-1);
		}

		close(fd);
	}

	/* Stale 0-length lockfiles are blown away after 5 mins */

	if (lstat(f, &stat_buf) == 0 && stat_buf.st_size == 0 &&
	    stat_buf.st_mtime + 300 < time(NULL))
	{
		errno=EAGAIN;
		unlink(f);
		free(f);
		return (-1);
	}

	errno=EAGAIN;
	free(f);
	return (-1);
}