Example #1
0
int main(int argc, char *argv[])
{
	int fd;
	int ret;
	struct flock lock;
	char read_buf[32];

	// 打开或创建文件
	if ((fd = open("example_fc_lock", O_CREAT | O_TRUNC | O_RDWR, S_IRWXU)) == -1) {
		my_err("open", __LINE__);
	}
	if (write(fd, "test lock", 10) != 10) {
		my_err("write", __LINE__);
	}

	// 初始化lock结构 锁整个文件
	memset(&lock, 0, sizeof(struct flock));
	lock.l_whence = SEEK_SET;
	lock.l_start = 0;
	lock.l_len = 0;

	// 设置读锁
	lock.l_type = F_RDLCK;
	if (lock_test(fd, &lock) == 0) {
		// 测试可以设置锁
		lock.l_type = F_RDLCK;
		lock_set(fd, &lock);
	}

	// 读数据
	lseek(fd, 0, SEEK_SET);
	if ((ret = read(fd, read_buf, 10)) < 0) {
		my_err("read", __LINE__);
	}
	read_buf[ret] = '\0';
	printf("%s\n", read_buf);

	// 按任意键
	getchar();

	// 设置写锁
	lock.l_type = F_WRLCK;
	if (lock_test(fd, &lock) == 0) {
		lock.l_type = F_WRLCK;
		lock_set(fd, &lock);
	}

	// 释放锁
	lock.l_type = F_UNLCK;
	lock_set(fd, &lock);
	close(fd);

	return 0;
}
Example #2
0
int main(int argc, char *argv[])
{
	if(argc < 3)
	{
		printf("usage: ./main filename locktype\n");
		return -1;
	}

	int fd = open(argv[1], O_RDWR);
	if(fd < 0)
	{
		perror("file open fail");
		return -1;
	}

	int type = atoi(argv[2]);
	short locktype;
	if(type == 0)
	{
		locktype = F_RDLCK;    //should not set F_UNLCK first, it is always success, but a new process can not unlock another proceess's lock
	}                          //A rd or wr lock only can be unlock by the same process's unlock
	else
	{
		locktype = F_WRLCK;
	}
	
	int ret = lock_set(locktype, fd);
	if(ret < 0)
	{
		perror("lock file fail");
		return -1;
	}
	else
		printf("lockType %d success on file %s\n", atoi(argv[2]), argv[1]);

	sleep(10);
	
	ret = lock_set(F_UNLCK, fd);
	if(ret < 0)
	{
		perror("lock file fail");
		return -1;
	}
	else
		printf("lockType %d success on file %s\n", atoi(argv[2]), argv[1]);

	while(1);	
}
Example #3
0
int main(void){
	int fd;
	int ret;
	struct flock lock;
	char read_buf[32];

	if((fd = open("example_65", O_CREAT|O_TRUNC|O_RDWR, S_IRWXU)) == -1){
		my_err("open", __LINE__);
	}
	if(write(fd, "test lock", 10) != 10){
		my_err("write", __LINE__);
	}
	memset(&lock, 0, sizeof(struct flock));
	lock.l_start = SEEK_SET;
	lock.l_whence = 0;
	lock.l_len = 0;

	lock.l_type = F_RDLCK;
	if(lock_test(fd, &lock) == 0){
		lock.l_type = F_RDLCK;
		lock_set(fd, &lock);
	}

	lseek(fd, 0, SEEK_SET);
	bzero(read_buf, 10);
	if((ret = read(fd, read_buf, 10)) < 0){
		printf("%d\n", errno);
		my_err("read", __LINE__);
	}

	read_buf[ret] = '\0';
	printf("%s\n", read_buf);

	getchar();

	lock.l_type = F_WRLCK;
	if(lock_test(fd, &lock) == 0){
		lock.l_type = F_WRLCK;
		lock_set(fd, &lock);
	}

	lock.l_type = F_UNLCK;
	lock_set(fd, &lock);
	close(fd);
	return 0;
}
int main(void)
{
	int fd;
	fd = open("hello",O_RDWR | O_CREAT, 0666);
	if (fd < 0) {
		perror("open");
		exit(1);
	}
	
	lock_set(fd, F_WRLCK);
	getchar();
	
	lock_set(fd, F_UNLCK);
	getchar();
	
	close(fd);
	
	exit(0);
}
/*
 * When we apply priority inheritance, we must grab the owner's thread lock
 * while already holding the waiter's thread lock.  If both thread locks are
 * turnstile locks, this can lead to deadlock: while we hold L1 and try to
 * grab L2, some unrelated thread may be applying priority inheritance to
 * some other blocking chain, holding L2 and trying to grab L1.  The most
 * obvious solution -- do a lock_try() for the owner lock -- isn't quite
 * sufficient because it can cause livelock: each thread may hold one lock,
 * try to grab the other, fail, bail out, and try again, looping forever.
 * To prevent livelock we must define a winner, i.e. define an arbitrary
 * lock ordering on the turnstile locks.  For simplicity we declare that
 * virtual address order defines lock order, i.e. if L1 < L2, then the
 * correct lock ordering is L1, L2.  Thus the thread that holds L1 and
 * wants L2 should spin until L2 is available, but the thread that holds
 * L2 and can't get L1 on the first try must drop L2 and return failure.
 * Moreover, the losing thread must not reacquire L2 until the winning
 * thread has had a chance to grab it; to ensure this, the losing thread
 * must grab L1 after dropping L2, thus spinning until the winner is done.
 * Complicating matters further, note that the owner's thread lock pointer
 * can change (i.e. be pointed at a different lock) while we're trying to
 * grab it.  If that happens, we must unwind our state and try again.
 *
 * On success, returns 1 with both locks held.
 * On failure, returns 0 with neither lock held.
 */
static int
turnstile_interlock(lock_t *wlp, lock_t *volatile *olpp)
{
	ASSERT(LOCK_HELD(wlp));

	for (;;) {
		volatile lock_t *olp = *olpp;

		/*
		 * If the locks are identical, there's nothing to do.
		 */
		if (olp == wlp)
			return (1);
		if (lock_try((lock_t *)olp)) {
			/*
			 * If 'olp' is still the right lock, return success.
			 * Otherwise, drop 'olp' and try the dance again.
			 */
			if (olp == *olpp)
				return (1);
			lock_clear((lock_t *)olp);
		} else {
			hrtime_t spin_time = 0;
			/*
			 * If we're grabbing the locks out of order, we lose.
			 * Drop the waiter's lock, and then grab and release
			 * the owner's lock to ensure that we won't retry
			 * until the winner is done (as described above).
			 */
			if (olp >= (lock_t *)turnstile_table && olp < wlp) {
				lock_clear(wlp);
				lock_set((lock_t *)olp);
				lock_clear((lock_t *)olp);
				return (0);
			}
			/*
			 * We're grabbing the locks in the right order,
			 * so spin until the owner's lock either becomes
			 * available or spontaneously changes.
			 */
			spin_time =
			    LOCKSTAT_START_TIME(LS_TURNSTILE_INTERLOCK_SPIN);
			while (olp == *olpp && LOCK_HELD(olp)) {
				if (panicstr)
					return (1);
				SMT_PAUSE();
			}
			LOCKSTAT_RECORD_TIME(LS_TURNSTILE_INTERLOCK_SPIN,
			    olp, spin_time);
		}
	}
}
Example #6
0
int zrip_unlock_cdrom( int fd )
{
	ZInfo4(DBG_MISC, "Try to unlock the cdrom\n");
	if(!fd)
		return -1;

	lock_set( fd, F_UNLCK );
	if ( close(fd) < 0 ){
		return -1;
	}
	ZInfo4(DBG_MISC, "cdrom unlocked\n");
	return 0;
}
Example #7
0
int zrip_lock_cdrom( char *fileName )
{
	int  fd = 0;
	ZInfo4(DBG_MISC, "Try to lock the cdrom\n");
	if( ( fd = open( fileName, O_CREAT | O_TRUNC | O_RDWR, 0666 ) ) < 0 ){
		ZInfo4(DBG_MISC, "open lock file failed!\n");
		return 0;
	}

	lock_set( fd, F_WRLCK );
	ZInfo4(DBG_MISC, "cdrom locked\n");
	return fd;
}
Example #8
0
void sys_log(char * string)
{
	int fd;
	char str[SIZE];
	time_t timep;
	struct tm *timenow;
	char log[SIZE];
	struct flock lock;

	memset(&lock, 0, sizeof(struct flock));
	lock.l_start = SEEK_SET;
	lock.l_whence = 0;
	lock.l_len = 0;

	lock.l_type = F_WRLCK;
	if (lock_test(fd, &lock) == 0)
	{
		lock.l_type = F_WRLCK;
		lock_set(fd, &lock);
	}
	strcpy(log, string);

	time (&timep);
	timenow = localtime(&timep);
	strcpy(str, asctime(timenow));
	fd = open("/home/qiong/shujia/Net/sys_log.txt", O_WRONLY | O_CREAT | O_APPEND, 0600);
	write(fd, "\n\n时间:", strlen("\n\n时间:"));
	write(fd, str, strlen(str)-1);
	write(fd, "\nip:", strlen("\nip:"));
	write(fd, ip_name, strlen(ip_name));
	write(fd, "\n操作:", strlen("\n操作:"));
	write(fd, log, strlen(log));

	lock.l_type = F_UNLCK;
	lock_set(fd, &lock);

	close(fd);
}
Example #9
0
int product(void)
{
    int fd;
    unsigned int sign_type,sign_start,sign_count,size;
    static unsigned int counter = 0;

    if((fd = open(fifo_file, O_CREAT|O_RDWR|O_APPEND, 0644)) < 0){
        printf("Open fifo file error\n");
        exit(1);
    }
    sign_type = SIGN_TYPE;
    switch(sign_type)
    {
        case ALPHABET:
            sign_start = ALPHABET_START;
            sign_count = COUNT_OF_ALPHABET;
        break;
        case DIGIT:
            sign_start = DIGIT_START;
            sign_count = COUNT_OF_DIGIT;
        break;
        default:
        return -1;
    }
    sprintf(buff, "%c", (sign_start + counter));
    counter = (counter + 1) % sign_count;
    lock_set(fd,F_WRLCK);
    if((size = write(fd,buff,strlen(buff))) < 0)
    {
        printf("Producter:write error\n");
        return -1;
    }
    lock_set(fd,F_UNLCK);
    close(fd);
    return 0;
}
Example #10
0
File: stub.c Project: tamentis/mdp
int
main(int ac, char **av)
{
	(void)(ac);

	lock_path = strdup(av[1]);

	if (action_is("lock_exists")) {
		printf("%d\n", lock_exists());
	} else if (action_is("lock_set")) {
		lock_set();
	} else if (action_is("lock_unset")) {
		lock_unset();
	}

	return EXIT_SUCCESS;
}
Example #11
0
void transfer_rename(const char *to)
{
    size_t to_len;

    pthread_mutex_lock(&m_transfer);

    if (!t_state.active)
    {
        pthread_mutex_unlock(&m_transfer);
        return;
    }

    DEBUG("transfer_rename to %s", to);

    to_len = strlen(to);

    worker_block();

    lock_remove(t_state.job->path, LOCK_TRANSFER);
    free(t_state.job->path);
    t_state.job->path = strdup(to);
    lock_set(t_state.job->path, LOCK_TRANSFER);

    free(t_state.read_path);
    free(t_state.write_path);
    if (t_state.job->op == JOB_PUSH)
    {
        t_state.read_path = cache_path2(to, to_len);
        t_state.write_path = remote_path2(to, to_len);
    }
    else
    {
        t_state.read_path = remote_path2(to, to_len);
        t_state.write_path = cache_path2(to, to_len);
    }

    pthread_mutex_unlock(&m_transfer);
    worker_unblock();
}
Example #12
0
CosConcurrencyControl::LockSet_ptr
CC_Test::create_lock_set (void)
{
  // Create the lock set and return an obj ref corresponding to the
  // key.
  CosConcurrencyControl::LockSet_ptr lock_set(0);
  try
    {
      lock_set =
        this->naming_service_->get_lock_set_factory ()->create ();

      if (CORBA::is_nil (lock_set))
        ACE_ERROR_RETURN ((LM_ERROR,
                           "null lock set objref returned by factory\n"),
                          0);
    }
  catch (const CORBA::Exception& ex)
    {
      ex._tao_print_exception ("CC_Client::create_lock_set");
      return 0;
    }
  return lock_set;
}
Example #13
0
File: main.c Project: pbleser/mdp
int
main(int ac, char **av)
{
	char *t;
	int opt, mode = MODE_PAGER;
	extern int optind;
	extern char *optarg;

	if (ac < 2)
		usage();

	setlocale(LC_ALL, "");

	/* Populate $HOME */
	t = getenv("HOME");
	if (t == NULL || *t == '\0')
		errx(0, "Unknown variable '$HOME'.");
	mbstowcs(home, t, MAXPATHLEN);

	/* Populate $EDITOR */
	t = getenv("EDITOR");
	if (t != NULL)
		mbstowcs(editor, t, MAXPATHLEN);

	while ((opt = getopt(ac, av, "hVdeg:qrc:")) != -1) {
		switch (opt) {
		case 'd':
			cfg_debug = 1;
			break;
		case 'V':
			mode = MODE_VERSION;
			break;
		case 'q':
			mode = MODE_QUERY;
			break;
		case 'e':
			mode = MODE_EDIT;
			break;
		case 'g':
			mode = MODE_GENERATE;
			password_length = strtoumax(optarg, NULL, 10);
			break;
		case 'r':
			mode = MODE_RAW;
			break;
		case 'c':
			swprintf(cfg_config_path, MAXPATHLEN, L"%s", optarg);
			break;
		default:
			usage();
		}
	}

	debug("read config");

	config_set_defaults();
	config_check_paths();
	config_read();

	ac -= optind;
	av += optind;

	keywords_load_from_argv(av);

	/* Decide if we use the internal pager or just dump to screen. */
	switch (mode) {
		case MODE_VERSION:
			printf("mdp-%s\n", MDP_VERSION);
			break;

		case MODE_RAW:
			debug("mode: MODE_RAW");
			if (ac == 0)
				usage();

			gpg_check();
			load_results();
			filter_results();
			print_results();
			break;

		case MODE_PAGER:
			debug("mode: MODE_PAGER");
			if (ac == 0)
				usage();

			gpg_check();
			load_results();
			filter_results();
			pager(START_WITHOUT_PROMPT);
			break;

		case MODE_QUERY:
			debug("mode: MODE_QUERY");
			gpg_check();
			load_results();
			pager(START_WITH_PROMPT);
			break;

		case MODE_EDIT:
			debug("mode: MODE_EDIT");
			if (ac != 0)
				usage();

			gpg_check();
			lock_set();
			load_results();
			edit_results();
			break;

		case MODE_GENERATE:
			debug("mode: MODE_GENERATE");
			if (ac != 0)
				usage();

			print_passwords(password_length, cfg_password_count);
			break;

		default:
			errx(1, "unknown mode");
			break;
	}

	debug("normal shutdown");

	return 0;
}
int
turnstile_block(turnstile_t *ts, int qnum, void *sobj, sobj_ops_t *sobj_ops,
    kmutex_t *mp, lwp_timer_t *lwptp)
{
	kthread_t *owner;
	kthread_t *t = curthread;
	proc_t *p = ttoproc(t);
	klwp_t *lwp = ttolwp(t);
	turnstile_chain_t *tc = &TURNSTILE_CHAIN(sobj);
	int error = 0;
	int loser = 0;

	ASSERT(DISP_LOCK_HELD(&tc->tc_lock));
	ASSERT(mp == NULL || IS_UPI(mp));
	ASSERT((SOBJ_TYPE(sobj_ops) == SOBJ_USER_PI) ^ (mp == NULL));

	thread_lock_high(t);

	if (ts == NULL) {
		/*
		 * This is the first thread to block on this sobj.
		 * Take its attached turnstile and add it to the hash chain.
		 */
		ts = t->t_ts;
		ts->ts_sobj = sobj;
		ts->ts_next = tc->tc_first;
		tc->tc_first = ts;
		ASSERT(ts->ts_waiters == 0);
	} else {
		/*
		 * Another thread has already donated its turnstile
		 * to block on this sobj, so ours isn't needed.
		 * Stash it on the active turnstile's freelist.
		 */
		turnstile_t *myts = t->t_ts;
		myts->ts_free = ts->ts_free;
		ts->ts_free = myts;
		t->t_ts = ts;
		ASSERT(ts->ts_sobj == sobj);
		ASSERT(ts->ts_waiters > 0);
	}

	/*
	 * Put the thread to sleep.
	 */
	ASSERT(t != CPU->cpu_idle_thread);
	ASSERT(CPU_ON_INTR(CPU) == 0);
	ASSERT(t->t_wchan0 == NULL && t->t_wchan == NULL);
	ASSERT(t->t_state == TS_ONPROC);

	if (SOBJ_TYPE(sobj_ops) == SOBJ_USER_PI) {
		curthread->t_flag |= T_WAKEABLE;
	}
	CL_SLEEP(t);		/* assign kernel priority */
	THREAD_SLEEP(t, &tc->tc_lock);
	t->t_wchan = sobj;
	t->t_sobj_ops = sobj_ops;
	DTRACE_SCHED(sleep);

	if (lwp != NULL) {
		lwp->lwp_ru.nvcsw++;
		(void) new_mstate(t, LMS_SLEEP);
		if (SOBJ_TYPE(sobj_ops) == SOBJ_USER_PI) {
			lwp->lwp_asleep = 1;
			lwp->lwp_sysabort = 0;
			/*
			 * make wchan0 non-zero to conform to the rule that
			 * threads blocking for user-level objects have a
			 * non-zero wchan0: this prevents spurious wake-ups
			 * by, for example, /proc.
			 */
			t->t_wchan0 = (caddr_t)1;
		}
	}
	ts->ts_waiters++;
	sleepq_insert(&ts->ts_sleepq[qnum], t);

	if (SOBJ_TYPE(sobj_ops) == SOBJ_MUTEX &&
	    SOBJ_OWNER(sobj_ops, sobj) == NULL)
		panic("turnstile_block(%p): unowned mutex", (void *)ts);

	/*
	 * Follow the blocking chain to its end, willing our priority to
	 * everyone who's in our way.
	 */
	while (t->t_sobj_ops != NULL &&
	    (owner = SOBJ_OWNER(t->t_sobj_ops, t->t_wchan)) != NULL) {
		if (owner == curthread) {
			if (SOBJ_TYPE(sobj_ops) != SOBJ_USER_PI) {
				panic("Deadlock: cycle in blocking chain");
			}
			/*
			 * If the cycle we've encountered ends in mp,
			 * then we know it isn't a 'real' cycle because
			 * we're going to drop mp before we go to sleep.
			 * Moreover, since we've come full circle we know
			 * that we must have willed priority to everyone
			 * in our way.  Therefore, we can break out now.
			 */
			if (t->t_wchan == (void *)mp)
				break;

			if (loser)
				lock_clear(&turnstile_loser_lock);
			/*
			 * For SOBJ_USER_PI, a cycle is an application
			 * deadlock which needs to be communicated
			 * back to the application.
			 */
			thread_unlock_nopreempt(t);
			mutex_exit(mp);
			setrun(curthread);
			swtch(); /* necessary to transition state */
			curthread->t_flag &= ~T_WAKEABLE;
			if (lwptp->lwpt_id != 0)
				(void) lwp_timer_dequeue(lwptp);
			setallwatch();
			lwp->lwp_asleep = 0;
			lwp->lwp_sysabort = 0;
			return (EDEADLK);
		}
		if (!turnstile_interlock(t->t_lockp, &owner->t_lockp)) {
			/*
			 * If we failed to grab the owner's thread lock,
			 * turnstile_interlock() will have dropped t's
			 * thread lock, so at this point we don't even know
			 * that 't' exists anymore.  The simplest solution
			 * is to restart the entire priority inheritance dance
			 * from the beginning of the blocking chain, since
			 * we *do* know that 'curthread' still exists.
			 * Application of priority inheritance is idempotent,
			 * so it's OK that we're doing it more than once.
			 * Note also that since we've dropped our thread lock,
			 * we may already have been woken up; if so, our
			 * t_sobj_ops will be NULL, the loop will terminate,
			 * and the call to swtch() will be a no-op.  Phew.
			 *
			 * There is one further complication: if two (or more)
			 * threads keep trying to grab the turnstile locks out
			 * of order and keep losing the race to another thread,
			 * these "dueling losers" can livelock the system.
			 * Therefore, once we get into this rare situation,
			 * we serialize all the losers.
			 */
			if (loser == 0) {
				loser = 1;
				lock_set(&turnstile_loser_lock);
			}
			t = curthread;
			thread_lock_high(t);
			continue;
		}

		/*
		 * We now have the owner's thread lock.  If we are traversing
		 * from non-SOBJ_USER_PI ops to SOBJ_USER_PI ops, then we know
		 * that we have caught the thread while in the TS_SLEEP state,
		 * but holding mp.  We know that this situation is transient
		 * (mp will be dropped before the holder actually sleeps on
		 * the SOBJ_USER_PI sobj), so we will spin waiting for mp to
		 * be dropped.  Then, as in the turnstile_interlock() failure
		 * case, we will restart the priority inheritance dance.
		 */
		if (SOBJ_TYPE(t->t_sobj_ops) != SOBJ_USER_PI &&
		    owner->t_sobj_ops != NULL &&
		    SOBJ_TYPE(owner->t_sobj_ops) == SOBJ_USER_PI) {
			kmutex_t *upi_lock = (kmutex_t *)t->t_wchan;

			ASSERT(IS_UPI(upi_lock));
			ASSERT(SOBJ_TYPE(t->t_sobj_ops) == SOBJ_MUTEX);

			if (t->t_lockp != owner->t_lockp)
				thread_unlock_high(owner);
			thread_unlock_high(t);
			if (loser)
				lock_clear(&turnstile_loser_lock);

			while (mutex_owner(upi_lock) == owner) {
				SMT_PAUSE();
				continue;
			}

			if (loser)
				lock_set(&turnstile_loser_lock);
			t = curthread;
			thread_lock_high(t);
			continue;
		}

		turnstile_pi_inherit(t->t_ts, owner, DISP_PRIO(t));
		if (t->t_lockp != owner->t_lockp)
			thread_unlock_high(t);
		t = owner;
	}

	if (loser)
		lock_clear(&turnstile_loser_lock);

	/*
	 * Note: 't' and 'curthread' were synonymous before the loop above,
	 * but now they may be different.  ('t' is now the last thread in
	 * the blocking chain.)
	 */
	if (SOBJ_TYPE(sobj_ops) == SOBJ_USER_PI) {
		ushort_t s = curthread->t_oldspl;
		int timedwait = 0;
		uint_t imm_timeout = 0;
		clock_t tim = -1;

		thread_unlock_high(t);
		if (lwptp->lwpt_id != 0) {
			/*
			 * We enqueued a timeout.  If it has already fired,
			 * lwptp->lwpt_imm_timeout has been set with cas,
			 * so fetch it with cas.
			 */
			timedwait = 1;
			imm_timeout =
			    atomic_cas_uint(&lwptp->lwpt_imm_timeout, 0, 0);
		}
		mutex_exit(mp);
		splx(s);

		if (ISSIG(curthread, JUSTLOOKING) ||
		    MUSTRETURN(p, curthread) || imm_timeout)
			setrun(curthread);
		swtch();
		curthread->t_flag &= ~T_WAKEABLE;
		if (timedwait)
			tim = lwp_timer_dequeue(lwptp);
		setallwatch();
		if (ISSIG(curthread, FORREAL) || lwp->lwp_sysabort ||
		    MUSTRETURN(p, curthread))
			error = EINTR;
		else if (imm_timeout || (timedwait && tim == -1))
			error = ETIME;
		lwp->lwp_sysabort = 0;
		lwp->lwp_asleep = 0;
	} else {
		thread_unlock_nopreempt(t);
		swtch();
	}

	return (error);
}
Example #15
0
int transfer(const char *from, const char *to)
{
#define CLOSE(fd) { if (close(fd)) PERROR("error closing fd"); }
    int fdread, fdwrite;
    ssize_t readbytes;
    char buf[TRANSFER_SIZE];
    int w_flags;

    pthread_mutex_lock(&m_transfer);

    if (from && to)
    {
        lock_set(t_state.job->path, LOCK_TRANSFER);
        VERBOSE("beginning transfer: '%s' -> '%s'", from, to);
        t_state.read_path = strdup(from);
        t_state.write_path = strdup(to);

        w_flags = O_WRONLY | O_CREAT | O_TRUNC;
    }
    else if (!t_state.active)
    {
        pthread_mutex_unlock(&m_transfer);
        return TRANSFER_FINISH;
    }
    else
    {
        VERBOSE("resuming transfer: '%s' -> '%s' at %ld",
                t_state.read_path, t_state.write_path, t_state.offset);

        w_flags = O_WRONLY | O_APPEND;
    }


    if (!t_state.read_path || !t_state.write_path)
    {
        ERROR("t_state.read_path or t_state.write_path is NULL");
        lock_remove(t_state.job->path, LOCK_TRANSFER);
        goto failure;
    }

    /* open files */
    if ((fdread = open(t_state.read_path, O_RDONLY)) == -1
            || lseek(fdread, t_state.offset, SEEK_SET) == -1) {
        PERROR(t_state.read_path);
        goto failure;
    }

    if ((fdwrite = open(t_state.write_path, w_flags, 0666)) == -1
            || lseek(fdwrite, t_state.offset, SEEK_SET) == -1) {
        PERROR(t_state.write_path);
        goto failure;
    }

    while (ONLINE && !worker_blocked())
    {
        readbytes = read(fdread, buf, sizeof buf);
        if (readbytes && (readbytes < 0 || write(fdwrite, buf, readbytes) < readbytes || fsync(fdwrite)))
        {

            if (readbytes < 0)
                ERROR("failed to read from file");
            else
                ERROR("failed or incomplete write");

            goto failure;
        }

        /* copy completed, set mode and ownership */
        if (readbytes < sizeof buf)
        {
            CLOSE(fdread);
            CLOSE(fdwrite);

            copy_attrs(t_state.read_path, t_state.write_path);

            VERBOSE("transfer finished: '%s' -> '%s'", t_state.read_path, t_state.write_path);

            lock_remove(t_state.job->path, LOCK_TRANSFER);
            pthread_mutex_unlock(&m_transfer);
            transfer_reset_state();

            return TRANSFER_FINISH;
        }
    }

    t_state.offset = lseek(fdread, 0, SEEK_CUR);

    CLOSE(fdread);
    CLOSE(fdwrite);

    pthread_mutex_unlock(&m_transfer);
    return TRANSFER_OK;

failure:
    pthread_mutex_unlock(&m_transfer);
    transfer_abort();
    return TRANSFER_FAIL;
#undef CLOSE
}