/*===========================================================================* * fs_utime * *===========================================================================*/ PUBLIC int fs_utime() { struct puffs_node *pn; struct vattr va; PUFFS_MAKECRED(pcr, &global_kcred); if (is_readonly_fs) return(EROFS); if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); if( (pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) return(EINVAL); puffs_vattr_null(&va); va.va_atime.tv_nsec = va.va_mtime.tv_nsec = va.va_ctime.tv_nsec = 0; va.va_atime.tv_sec = fs_m_in.REQ_ACTIME; va.va_mtime.tv_sec = fs_m_in.REQ_MODTIME; va.va_ctime.tv_sec = clock_time(); if (global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr) != 0) return(EINVAL); return(OK); }
/*===========================================================================* * fs_ftrunc * *===========================================================================*/ PUBLIC int fs_ftrunc(void) { int r; struct puffs_node *pn; off_t start, end; PUFFS_MAKECRED(pcr, &global_kcred); if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) return(EINVAL); start = fs_m_in.REQ_TRC_START_LO; end = fs_m_in.REQ_TRC_END_LO; if (end == 0) { struct vattr va; if (pn->pn_va.va_size == start) return(OK); if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); puffs_vattr_null(&va); va.va_size = start; r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr); if (r) return(EINVAL); } else { /* XXX zerofill the given region. Can we make a hole? */ off_t bytes_left = end - start; char* rw_buf; if (global_pu->pu_ops.puffs_node_write == NULL) return(EINVAL); /* XXX split into chunks? */ rw_buf = malloc(bytes_left); if (!rw_buf) panic("fs_ftrunc: failed to allocated memory\n"); memset(rw_buf, 0, bytes_left); r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf, start, (size_t *) &bytes_left, pcr, 0); free(rw_buf); if (r) return(EINVAL); } update_times(pn, CTIME | MTIME, 0); return(r); }
int psbuf_get_vattr(struct puffs_framebuf *pb, struct vattr *vap) { uint32_t flags; uint32_t val; uint32_t tmpval; puffs_vattr_null(vap); FAILRV(psbuf_get_4(pb, &flags)); if (flags & SSH_FILEXFER_ATTR_SIZE) { FAILRV(psbuf_get_8(pb, &vap->va_size)); vap->va_bytes = vap->va_size; } if (flags & SSH_FILEXFER_ATTR_UIDGID) { FAILRV(psbuf_get_4(pb, &vap->va_uid)); FAILRV(psbuf_get_4(pb, &vap->va_gid)); } if (flags & SSH_FILEXFER_ATTR_PERMISSIONS) { FAILRV(psbuf_get_4(pb, &tmpval)); vap->va_mode = tmpval; vap->va_type = puffs_mode2vt(vap->va_mode); } if (flags & SSH_FILEXFER_ATTR_ACCESSTIME) { /* * XXX: this is utterly wrong if we want to speak * protocol version 3, but it seems like the * "internet standard" for doing this */ FAILRV(psbuf_get_4(pb, &val)); vap->va_atime.tv_sec = val; FAILRV(psbuf_get_4(pb, &val)); vap->va_mtime.tv_sec = val; /* make ctime the same as mtime */ vap->va_ctime.tv_sec = val; vap->va_atime.tv_nsec = 0; vap->va_ctime.tv_nsec = 0; vap->va_mtime.tv_nsec = 0; } return 0; }
/* * Well, you're probably wondering why this isn't optimized. * The reason is simple: my available time is not optimized for * size ... so please be patient ;) */ struct puffs_node * puffs_pn_new(struct puffs_usermount *pu, void *privdata) { struct puffs_node *pn; pn = calloc(1, sizeof(struct puffs_node)); if (pn == NULL) return NULL; pn->pn_data = privdata; pn->pn_mnt = pu; puffs_vattr_null(&pn->pn_va); LIST_INSERT_HEAD(&pu->pu_pnodelst, pn, pn_entries); pu->pu_flags |= PUFFS_FLAG_PNCOOKIE; return pn; }
struct psshfs_dir * direnter(struct puffs_node *parent, const char *entryname) { struct psshfs_node *psn_parent = parent->pn_data; struct psshfs_dir *pd; int i; /* create directory entry */ if (psn_parent->denttot == psn_parent->dentnext) allocdirs(psn_parent); i = psn_parent->dentnext; pd = &psn_parent->dir[i]; pd->entryname = estrdup(entryname); pd->valid = 1; pd->attrread = 0; puffs_vattr_null(&pd->va); psn_parent->dentnext++; return pd; }
/*===========================================================================* * fs_readwrite * *===========================================================================*/ PUBLIC int fs_readwrite(void) { int r = OK, rw_flag; cp_grant_id_t gid; off_t pos; size_t nrbytes, bytes_left, bytes_done; struct puffs_node *pn; struct vattr va; PUFFS_MAKECRED(pcr, &global_kcred); if ((pn = puffs_pn_nodewalk(global_pu, 0, &fs_m_in.REQ_INODE_NR)) == NULL) { lpuffs_debug("walk failed...\n"); return(EINVAL); } /* Get the values from the request message */ rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING); gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; pos = (off_t) fs_m_in.REQ_SEEK_POS_LO; nrbytes = bytes_left = (size_t) fs_m_in.REQ_NBYTES; if (nrbytes > RW_BUFSIZ) nrbytes = bytes_left = RW_BUFSIZ; memset(getdents_buf, '\0', RW_BUFSIZ); /* Avoid leaking any data */ if (rw_flag == READING) { if (global_pu->pu_ops.puffs_node_read == NULL) return(EINVAL); r = global_pu->pu_ops.puffs_node_read(global_pu, pn, (uint8_t *)rw_buf, pos, &bytes_left, pcr, 0); if (r) { lpuffs_debug("puffs_node_read failed\n"); return(EINVAL); } bytes_done = nrbytes - bytes_left; if (bytes_done) { r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0, (vir_bytes) rw_buf, bytes_done, D); update_times(pn, ATIME, 0); } } else if (rw_flag == WRITING) { /* At first try to change vattr */ if (global_pu->pu_ops.puffs_node_setattr == NULL) return(EINVAL); puffs_vattr_null(&va); if ( (pos + bytes_left) > pn->pn_va.va_size) va.va_size = bytes_left + pos; va.va_ctime.tv_sec = va.va_mtime.tv_sec = clock_time(); va.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec; r = global_pu->pu_ops.puffs_node_setattr(global_pu, pn, &va, pcr); if (r) return(EINVAL); r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0, (vir_bytes) rw_buf, nrbytes, D); if (r != OK) return(EINVAL); if (global_pu->pu_ops.puffs_node_write == NULL) return(EINVAL); r = global_pu->pu_ops.puffs_node_write(global_pu, pn, (uint8_t *)rw_buf, pos, &bytes_left, pcr, 0); bytes_done = nrbytes - bytes_left; } if (r != OK) return(EINVAL); fs_m_out.RES_SEEK_POS_LO = pos + bytes_done; fs_m_out.RES_NBYTES = bytes_done; return(r); }