static int /* ERRNO if error, 0 if successful. */ sam_inval_dev_call( void *arg, /* Pointer to arguments. */ int size, cred_t *credp) { sam_fsinval_arg_t args; dev_t rdev; if (secpolicy_fs_config(credp, NULL)) { return (EINVAL); } if (size != sizeof (args) || copyin(arg, (caddr_t)&args, sizeof (args))) { return (EFAULT); } rdev = expldev(args.rdev); bflush(rdev); binval(rdev); return (0); }
/*ARGSUSED2*/ int dh_k4_clnt_loadinfo(caddr_t usrdata, caddr_t *kdata, model_t model) { size_t nlen; int error = 0; char *userbufptr; dh_k4_clntdata_t *data; char netname[MAXNETNAMELEN+1]; struct netbuf *syncaddr; struct knetconfig *knconf; /* map opaque data to des specific strucutre */ data = kmem_alloc(sizeof (*data), KM_SLEEP); #ifdef _SYSCALL32_IMPL if (model != DATAMODEL_NATIVE) { struct des_clnt_data32 data32; if (copyin(usrdata, &data32, sizeof (data32)) == -1) { error = EFAULT; } else { data->syncaddr.maxlen = data32.syncaddr.maxlen; data->syncaddr.len = data32.syncaddr.len; data->syncaddr.buf = (caddr_t)(uintptr_t)data32.syncaddr.buf; data->knconf = (struct knetconfig *)(uintptr_t)data32.knconf; data->netname = (caddr_t)(uintptr_t)data32.netname; data->netnamelen = data32.netnamelen; } } else #endif /* _SYSCALL32_IMPL */ if (copyin(usrdata, data, sizeof (*data))) error = EFAULT; if (error == 0) { syncaddr = &data->syncaddr; if (syncaddr->len < MINAUTHLEN || syncaddr->len > MAXAUTHLEN) error = EINVAL; else { userbufptr = syncaddr->buf; syncaddr->buf = kmem_alloc(syncaddr->len, KM_SLEEP); syncaddr->maxlen = syncaddr->len; if (copyin(userbufptr, syncaddr->buf, syncaddr->len)) { kmem_free(syncaddr->buf, syncaddr->len); syncaddr->buf = NULL; error = EFAULT; } else { (void) copyinstr(data->netname, netname, sizeof (netname), &nlen); if (nlen != 0) { data->netname = kmem_alloc(nlen, KM_SLEEP); bcopy(netname, data->netname, nlen); data->netnamelen = (int)nlen; } } } } if (!error) { /* * Allocate space for a knetconfig structure and * its strings and copy in from user-land. */ knconf = kmem_alloc(sizeof (*knconf), KM_SLEEP); #ifdef _SYSCALL32_IMPL if (model != DATAMODEL_NATIVE) { struct knetconfig32 knconf32; if (copyin(data->knconf, &knconf32, sizeof (knconf32)) == -1) { kmem_free(knconf, sizeof (*knconf)); kmem_free(syncaddr->buf, syncaddr->len); syncaddr->buf = NULL; kmem_free(data->netname, nlen); error = EFAULT; } else { knconf->knc_semantics = knconf32.knc_semantics; knconf->knc_protofmly = (caddr_t)(uintptr_t)knconf32.knc_protofmly; knconf->knc_proto = (caddr_t)(uintptr_t)knconf32.knc_proto; knconf->knc_rdev = expldev(knconf32.knc_rdev); } } else #endif /* _SYSCALL32_IMPL */ if (copyin(data->knconf, knconf, sizeof (*knconf))) { kmem_free(knconf, sizeof (*knconf)); kmem_free(syncaddr->buf, syncaddr->len); syncaddr->buf = NULL; kmem_free(data->netname, nlen); error = EFAULT; } } if (!error) { size_t nmoved_tmp; char *p, *pf; pf = kmem_alloc(KNC_STRSIZE, KM_SLEEP); p = kmem_alloc(KNC_STRSIZE, KM_SLEEP); error = copyinstr(knconf->knc_protofmly, pf, KNC_STRSIZE, &nmoved_tmp); if (error) { kmem_free(pf, KNC_STRSIZE); kmem_free(p, KNC_STRSIZE); kmem_free(knconf, sizeof (*knconf)); kmem_free(syncaddr->buf, syncaddr->len); kmem_free(data->netname, nlen); } if (!error) { error = copyinstr(knconf->knc_proto, p, KNC_STRSIZE, &nmoved_tmp); if (error) { kmem_free(pf, KNC_STRSIZE); kmem_free(p, KNC_STRSIZE); kmem_free(knconf, sizeof (*knconf)); kmem_free(syncaddr->buf, syncaddr->len); kmem_free(data->netname, nlen); } } if (!error) { knconf->knc_protofmly = pf; knconf->knc_proto = p; } } if (error) { *kdata = NULL; kmem_free(data, sizeof (*data)); return (error); } data->knconf = knconf; *kdata = (caddr_t)data; return (0); }
static int /* ERRNO if error, 0 if ok */ syscall_mount_response( sam_mount_t *mp, /* pointer to mount entry. */ sam_fsmount_arg_t *mount) /* pointer to daemon mount response */ { sam_handle_t *fhandle; sam_node_t *ip; /* pointer to rm inode */ vnode_t *vp; int error = 0; sam_fs_fifo_ctl_t *fifo_ctl; dev_t rdev; fhandle = (sam_handle_t *)&mount->handle; fifo_ctl = (sam_fs_fifo_ctl_t *)fhandle->fifo_cmd.ptr; if ((ip = syscall_valid_ino(mp, fhandle)) == NULL) { return (ECANCELED); } vp = SAM_ITOV(ip); mutex_enter(&ip->daemon_mutex); /* * Is inode still waiting for the mount? */ if (ip->daemon_busy && ip->seqno == fhandle->seqno) { if (fifo_ctl && (fifo_ctl->fifo.magic == FS_FIFO_MAGIC)) { fifo_ctl->ret_err = mount->ret_err; rdev = expldev(mount->rdev); if ((mount->ret_err == 0) && rdev) { offset_t size; sam_resource_t *resource; offset_t section_size = 0; RW_LOCK_OS(&ip->inode_rwl, RW_WRITER); /* * Get the rm_info record. Preserve the file * size, since it includes the size of all VSNs. * Use size from rm_info record when reading * existing optical disk file (rm_info not * valid). */ size = ip->di.rm.size; resource = (sam_resource_t *)mount->resource.p32; if (curproc->p_model != DATAMODEL_ILP32) { resource = (sam_resource_t *) mount->resource.p64; } if (copyin((char *)&resource->archive.rm_info, (char *)&ip->di.rm, sizeof (sam_arch_rminfo_t))) { error = EFAULT; } else { /* * If the bof was written, or the * rm_info was not valid, get all the * resource record. */ if ((ip->di.rm.ui.flags & RM_BOF_WRITTEN) || !(ip->di.rm.ui.flags & RM_VALID)) { sam_archive_t *ap; ap = &fifo_ctl->fifo.param.fs_load.resource.archive; copyin( (char *)&resource->archive, (char *)ap, sizeof (sam_archive_t)); ap->rm_info.valid = 1; } /* * Preserve size of file for volume * overflow. Do not change size when * reading existing optical disk file. */ if ((ip->di.rm.ui.flags & RM_BOF_WRITTEN) || (ip->di.rm.ui.flags & RM_VALID)) { section_size = ip->di.rm.size; ip->di.rm.size = size; } /* Removable info valid */ ip->di.rm.ui.flags |= RM_VALID; /* * Set "space" from mount arg for writes * and tape. Set from section size of * the file when reading from optical * disk. */ ip->space = mount->space; if ((ip->di.rm.media & DT_CLASS_MASK) == DT_OPTICAL) { char access; copyin( (char *)&resource->access, (char *)&access, sizeof (char)); if (access == FREAD) { ip->space = section_size; } } ip->rdev = rdev; ip->mt_handle = (void *)mount->mt_handle.p32; if (curproc->p_model != DATAMODEL_ILP32) { ip->mt_handle = (void *)mount->mt_handle.p64; } ip->io_count = 0; TRACE(T_SAM_IOCTL_MNT, vp, ip->di.id.ino, (sam_tr_t)size, ip->rdev); if (!(ip->di.rm.ui.flags & RM_STRANGER) && (ip->di.rm.info.rm.mau == 0)) { error = EINVAL; fifo_ctl->ret_err = EINVAL; } if (!(ip->di.rm.ui.flags & RM_BOF_WRITTEN)) { if ((ip->di.rm.media & DT_CLASS_MASK) == DT_OPTICAL) { ip->stage_off = ip->di.rm.info.rm.position * ip->di.rm.info.rm.mau + ip->di.rm.info.rm.file_offset * 512; } } } ip->size = ip->di.rm.size; RW_UNLOCK_OS(&ip->inode_rwl, RW_WRITER); } else { if (mount->ret_err == 0) { /* No error with rdev == 0 */ fifo_ctl->ret_err = ENODEV; } TRACE(T_SAM_IOCTL_EMNT, vp, ip->di.id.ino, 1, mount->ret_err); } } else { if (mount->ret_err == 0) error = ECANCELED; TRACE(T_SAM_IOCTL_EMNT, vp, ip->di.id.ino, 2, mount->ret_err); } /* Signal 1 thread waiting on mount. */ ip->daemon_busy = 0; cv_signal(&ip->daemon_cv); } else { if (mount->ret_err == 0) error = ECANCELED; TRACE(T_SAM_IOCTL_EMNT, vp, ip->di.id.ino, 3, mount->ret_err); } mutex_exit(&ip->daemon_mutex); VN_RELE(vp); return (error); }