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); }
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); }
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); }