예제 #1
0
파일: preload.c 프로젝트: galigalikun/unco
static void before_open(const char *path, int oflag, struct backup_info *info)
{
	int srcfd = -1, dstfd = -1, success = 0;
	struct stat st;

	memset(info, 0, sizeof(*info));

	// bail out if not write
	if ((oflag & (O_WRONLY | O_RDWR)) == 0)
		return;
	// FIXME better blacklisting
	if (strncmp(path, "/dev/", 5) == 0)
		return;
	// not implemented
	if ((oflag & O_NOFOLLOW) != 0) {
		uncolog_set_error(&ufp, 0, "unco:unsupported operation: open with O_NOFOLLOW against file:%s", path);
		return;
	}

	// open source
	if ((srcfd = default_open(path, O_RDONLY)) == -1) {
		info->errnum = errno;
		goto Exit;
	}
	fstat(srcfd, &st); // TODO need to check error?

	// create backup and copy, update the times, and return
	if ((info->backup = uncolog_get_linkname(&ufp)) == NULL) {
		// errror reported by caller
		goto Exit;
	}
	if ((dstfd = default_open(info->backup, O_WRONLY | O_CREAT | O_EXCL)) == -1) {
		info->errnum = errno;
		goto Exit;
	}
	if (kcopyfd(srcfd, dstfd) != 0) {
		info->errnum = errno;
		goto Exit;
	}
	if (unco_utimes(dstfd, &st, default_futimes) != 0) {
		info->errnum = errno;
		goto Exit;
	}

	success = 1;
Exit:
	if (! success) {
		if (srcfd != -1)
			close(srcfd);
		free(info->backup);
		info->backup = NULL;
		if (dstfd != -1)
			close(dstfd);
	}
}
예제 #2
0
파일: default.c 프로젝트: digideskio/lirc
int my_open(const char* path)
{
	default_open(path);
	check_device(drv.device);
	set_rc_protocol(drv.device);
	return 0;
}
예제 #3
0
파일: preload.c 프로젝트: galigalikun/unco
extern void _setup_unco_preload()
{
	char *logfn, *env, *dir = NULL, *fnbuf = NULL;
	long long log_index;
	int dirlock_fd = -1;

	// load default handlers
	default_open = (int (*)(const char*, int, ...))dlsym(RTLD_NEXT, "open");
	default_mkdir = (int (*)(const char *, mode_t))dlsym(RTLD_NEXT, "mkdir");
	default_futimes = (int (*)(int, const struct timeval[2]))dlsym(RTLD_NEXT, "futimes");
	default_link = (int (*)(const char *, const char *))dlsym(RTLD_NEXT, "link");
	default_symlink = (int (*)(const char *, const char *))dlsym(RTLD_NEXT, "symlink");
	default_unlink = (int (*)(const char *))dlsym(RTLD_NEXT, "unlink");
	default_rmdir = (int (*)(const char *))dlsym(RTLD_NEXT, "rmdir");
	default_chown = (int (*)(const char *, uid_t, gid_t))dlsym(RTLD_NEXT, "chown");

	// open the log file
	if ((env = getenv("UNCO_LOG")) != NULL) {
		if (env[0] == '/') {
			logfn = env;
		} else {
			if ((dir = getcwd(NULL, 0)) == NULL) {
				perror("unco:could not obtain cwd");
				goto Error;
			}
			if ((fnbuf = ksprintf("%s/%s", dir, env)) == NULL) {
				perror("unco");
				goto Error;
			}
			logfn = fnbuf;
		}
		uncolog_open(&ufp, logfn, 'a', default_open, default_mkdir);
	} else {
		// no path given; create a new entry in the default dir
		if ((dir = unco_get_default_dir(default_mkdir)) == NULL)
			goto Error;
		// lock the directory
		if ((fnbuf = ksprintf("%s/lock", dir)) == NULL) {
			perror("unco");
			goto Error;
		}
		if ((dirlock_fd = default_open(fnbuf, O_WRONLY | O_CREAT | O_TRUNC | O_EXLOCK, 0600)) == -1) {
			kerr_printf("failed to open file:%s", fnbuf);
			goto Error;
		}
		free(fnbuf);
		fnbuf = NULL;
		// obtain logindex
		if ((log_index = unco_get_next_logindex(dir)) == -1)
			goto Error;
		if ((fnbuf = ksprintf("%s/%lld", dir, log_index)) == NULL) {
			perror("unco");
			goto Error;
		}
		logfn = fnbuf;
		// set UNCO_LOG, so that child processes would write to the same file
#if 1
		if (set_uncolog_osx(logfn) != 0)
			goto Error;
#else
		setenv("UNCO_LOG", logfn, 1);
#endif
		// open the log
		uncolog_open(&ufp, logfn, 'w', default_open, default_mkdir);
		// unlock the directory
		close(dirlock_fd);
		dirlock_fd = -1;
		// append meta
		if (uncolog_get_fd(&ufp) != -1) {
			// setup procedures for a new log
			log_meta();
			spawn_finalizer();
		}
	}

	free(dir);
	free(fnbuf);
	return;
Error:
	if (dirlock_fd != -1)
		close(dirlock_fd);
	free(dir);
	free(fnbuf);
	uncolog_init_fp(&ufp);
}