예제 #1
0
파일: list.cpp 프로젝트: optigon/aseprite
void jlist_insert_before(JList list, JLink sibling, void *data)
{
  if (jlist_empty(list))
    jlist_prepend(list, data);
  else if (sibling) {
    JLink new_link;

    new_link = new jlink(data);
    new_link->prev = sibling->prev;
    new_link->next = sibling;
    new_link->prev->next = new_link;
    new_link->next->prev = new_link;
    list->length++;
  }
  else
    jlist_append(list, data);
}
예제 #2
0
int capfs_ftruncate64(int fd, int64_t length)
{
	int i;
	ireq req;

	memset(&req, 0, sizeof(req));
	/* check for badness */
	if (fd < 0 || fd >= CAPFS_NR_OPEN 
		 || (pfds[fd] && pfds[fd]->fs == FS_RESV)) 
	{
		errno = EBADF;
		return(-1);
	}  

	/* check for UNIX */
	if (!pfds[fd] || pfds[fd]->fs==FS_UNIX) {
#ifndef LARGE_FILE_SUPPORT
		if ((off_t) length == length) {
			return ftruncate(fd, (off_t) length);
		}
		else {
			errno = EINVAL;
			return(-1);
		}
#else
		return ftruncate64(fd, length);
#endif
	}

	if (pfds[fd]->fs == FS_PDIR) {
		errno = EISDIR;
		return(-1);
	}
	if (capfs_mode == 0)
	{
		req.majik_nr             = IOD_MAJIK_NR;
		req.release_nr           = CAPFS_RELEASE_NR;
		req.type                 = IOD_FTRUNCATE;
		req.dsize                = 0;
		req.req.ftruncate.f_ino  = FINO;
		req.req.ftruncate.cap    = pfds[fd]->fd.cap;
		req.req.ftruncate.length = length;

		/* build job to send reqs and recv acks */
		if (build_simple_jobs(pfds[fd], &req) < 0) {
			LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: build_simple_jobs failed\n");
			return(-1);
		}

		/* call do_job */
		while (!jlist_empty(active_p)) {
			if (do_jobs(active_p, &socks, -1) < 0) {
				LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: do_jobs failed\n");
				return(-1);
			}
		}

		/* check acks from iods */
		for (i=0; i < PCNT; i++) {
			if (pfds[fd]->fd.iod[i].ack.status) {
				LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "capfs_ftruncate: non-zero status returned from iod %d\n", i);
				errno = pfds[fd]->fd.iod[i].ack.eno;
				return(-1);
			}
		}
	}
	return(0);
}
예제 #3
0
파일: capfs_read.c 프로젝트: mnv104/capfs
int capfs_read(int fd, char *buf, size_t count)
{
	int i;
	int64_t size = 0;
	fdesc_p pfd_p = pfds[fd];

	/* variables added for correct handling of EOF */
	char *contacted;
	int64_t exp_next_off, act_last_off, known_file_sz, calc_file_sz, start_off;

	if (fd < 0 || fd >= CAPFS_NR_OPEN 
	    || (pfds[fd] && pfds[fd]->fs == FS_RESV)) {
		errno = EBADF;
		return(-1);
	} 
	if (capfs_mode == 1) {
		LOG(stderr, CRITICAL_MSG, SUBSYS_LIB, "capfs_read is not yet implemented for capfs! Please use"
				"the VFS interface for accessing such files\n");
		errno = ENOSYS;
		return -1;
	}

	if (!pfd_p || pfd_p->fs == FS_UNIX) return(unix_read(fd, buf, count));
	if (pfd_p->fs == FS_PDIR) return(unix_read(fd, buf, count));

#ifdef STRICT_FDESC_CHECK
	if (do_fdesc_check(fd) < 0) {
		LOG(stderr, CRITICAL_MSG, SUBSYS_LIB,  "check failed at start of capfs_read()\n");
	}
#endif
	start_off = pfd_p->fd.off;
	exp_next_off = pfd_p->fd.off + count;
	known_file_sz = 0;
	contacted = malloc(PCOUNT * sizeof(char));

	for (i = 0; i < PCOUNT; i++) {
		contacted[i] = 0;
		pfd_p->fd.iod[i].ack.status = 0;
		pfd_p->fd.iod[i].ack.dsize  = 0;
	}	

	/* build jobs, including requests and acks */
	if (build_rw_jobs(pfd_p, buf, count, J_READ) < 0) {
		LOG(stderr, WARNING_MSG, SUBSYS_LIB,  "build_rw_jobs failed in capfs_read\n");
		return(-1);
	}

	/* determine what iods we will contact */
	for (i = 0; i < PCOUNT; i++) {
		/* this isn't so efficient, but i don't want to muck with jlist imp. */
		if (j_search(active_p, pfd_p->fd.iod[i].sock) != NULL) {
			contacted[i] = 1;
		}
	}
	
	/* send requests; receive data and acks */
	while (!jlist_empty(active_p)) {
		if (do_jobs(active_p, &socks, -1) < 0) {
			PERROR(SUBSYS_LIB,"do_jobs");
			free(contacted);
			return(-1);
		}
	}

	/* pass through responses, checking for errors, sizes */
	for (i = 0; i < PCOUNT; i++) {
		if (contacted[i]) {
			if (pfd_p->fd.iod[i].ack.status) {
				errno = pfd_p->fd.iod[i].ack.eno;
				free(contacted);
				return -1;
			}

			/* update known file size */
			calc_file_sz = fsize_to_file_size(pfd_p->fd.iod[i].ack.ack.rw.fsize, 
														 i, pfd_p); 
			size += pfd_p->fd.iod[i].ack.dsize;

			if (calc_file_sz > known_file_sz) {
				known_file_sz = calc_file_sz;
			}

		}
	}

	/* check for short read */
	if (exp_next_off <= known_file_sz) {
		/* we definitely did not hit EOF */
		if (size < count) {
			LOG(stderr, WARNING_MSG, SUBSYS_LIB,  " capfs_read: hit hole, read %Ld of %d (everything should be ok)\n",
				 size, count);
		}
		pfd_p->fd.off = exp_next_off;
		size = count; /* ensure correct return value (size might have hole) */
		errno = 0;
	}
	else {
		mack ack;
		mreq req;
		struct sockaddr saddr;
		struct capfs_options opt;
		
		opt.tcp = MGR_USE_TCP;
		opt.use_hcache = 0;

		/* we know we got a short read.  it MIGHT be EOF, or it might just
		 * be that we hit a hole that happened to extend to the end of our
		 * region to read.  we need to figure out which one happened.
		 */
		act_last_off = known_file_sz;

		/* the quick and dirty way to figure out what happened is to
		 * stat() the file.  a better solution would be to collect the
		 * remaining sizes from the iods we didn't already talk to.
		 */

		req.uid = getuid();
		req.gid = getgid();
		req.type = MGR_FSTAT;
		req.dsize = 0;
		req.req.fstat.meta = pfd_p->fd.meta;
		saddr = pfd_p->fd.meta.mgr;

		if (send_mreq_saddr(&opt, &saddr, &req, NULL, &ack, NULL) < 0 || ack.status != 0) {
			PERROR(SUBSYS_LIB,"capfs_read: send_mreq_saddr - ");
			/* error talking to mgr, but not really critical.
			 * assume we hit EOF, return what we know.
			 */
			pfd_p->fd.off = act_last_off;
			size = act_last_off - start_off;
		}
		else {
			/* got a response; determine if we hit EOF */
			if (ack.ack.fstat.meta.u_stat.st_size > known_file_sz) {
				/* the file is in fact bigger than we were told by the
				 * other iods
				 */
				known_file_sz = ack.ack.fstat.meta.u_stat.st_size;
			}
			if (exp_next_off <= known_file_sz) {
				/* didn't really hit EOF */
				if (size < count) {
					LOG(stderr, WARNING_MSG, SUBSYS_LIB,  " capfs_read: hit hole, read %Ld of %d (everything should be ok)\n",
				  		size, count);
				}
				pfd_p->fd.off = exp_next_off;
				size = count; /* ensure correct return value */
				errno = 0;
			}
			else {
				/* we really did hit EOF; return short read */
				if(known_file_sz > start_off)
				{
					pfd_p->fd.off = known_file_sz;
					size = known_file_sz - start_off;
					errno = 0;
				}
				else
				{
					/* apparently tried to read after seeking beyond EOF;
					 * keep current offset but do not return any data
					 */
					pfd_p->fd.off = start_off;
					size = 0;
					errno = 0;
				}
			}
		}
	}

	pfd_p->fd.meta.u_stat.atime = time(NULL);
	LOG(stderr, DEBUG_MSG, SUBSYS_LIB,  "capfs_read: completed %Ld bytes; new offset = %Ld\n", size,
		pfd_p->fd.off);

#ifdef STRICT_FDESC_CHECK
	if (do_fdesc_check(fd) < 0) {
		LOG(stderr, CRITICAL_MSG, SUBSYS_LIB,  "check failed at end of capfs_read()\n");
	}
#endif

	free(contacted);
	return(size);
}