int sys_posix_openpt(struct thread *td, struct posix_openpt_args *uap) { int error, fd; struct file *fp; /* * POSIX states it's unspecified when other flags are passed. We * don't allow this. */ if (uap->flags & ~(O_RDWR|O_NOCTTY|O_CLOEXEC)) return (EINVAL); error = falloc(td, &fp, &fd, uap->flags); if (error) return (error); /* Allocate the actual pseudo-TTY. */ error = pts_alloc(FFLAGS(uap->flags & O_ACCMODE), td, fp); if (error != 0) { fdclose(td, fp, fd); fdrop(fp, td); return (error); } /* Pass it back to userspace. */ td->td_retval[0] = fd; fdrop(fp, td); return (0); }
char *test_IOBuf_streaming() { // test streaming from /dev/zero to /dev/null Connection *zero = fake_conn("/dev/zero", O_RDONLY); IOBuf *from = zero->iob; Connection *null = fake_conn("/dev/null", O_WRONLY); IOBuf *to = null->iob; int rc = IOBuf_stream(from, to, 500); mu_assert(rc == 500, "Didn't stream the right amount on small test."); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == 10 * 1024, "Didn't stream oversized amount."); fdclose(from->fd); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == -1, "Should fail if send side is closed."); mu_assert(from->avail >= 0, "Avail should never go below 0."); fdclose(to->fd); rc = IOBuf_stream(from, to, 10 * 1024); mu_assert(rc == -1, "Should fail if recv side is closed."); fake_conn_close(zero); fake_conn_close(null); return NULL; }
int Upload_file(Connection *conn, Handler *handler, int content_len) { int rc = 0; int tmpfd = 0; bstring tmp_name = NULL; bstring result = NULL; if(UPLOAD_STORE == NULL) { UPLOAD_STORE = Setting_get_str("upload.temp_store", NULL); error_unless(UPLOAD_STORE, conn, 413, "Request entity is too large: %d, and no upload.temp_store setting for where to put the big files.", content_len); UPLOAD_STORE = bstrcpy(UPLOAD_STORE); } if(UPLOAD_MODE == 0) { bstring mode = Setting_get_str("upload.temp_store_mode", &UPLOAD_MODE_DEFAULT); log_info("Will set mode for upload temp store to: %s", bdata(mode)); check(bdata(mode) != NULL, "Mode data is NULL") UPLOAD_MODE = strtoul((const char *)bdata(mode), NULL, 0); check(UPLOAD_MODE > 0, "Failed to convert upload.temp_store_mode to a number."); check(UPLOAD_MODE < 066666, "Invalid mode that's way too big: %s.", bdata(mode)); } tmp_name = bstrcpy(UPLOAD_STORE); tmpfd = mkstemp((char *)tmp_name->data); check(tmpfd != -1, "Failed to create secure tempfile, did you end it with XXXXXX?"); log_info("Writing tempfile %s for large upload.", bdata(tmp_name)); rc = chmod((char *)tmp_name->data, UPLOAD_MODE); check(rc == 0, "Failed to chmod."); rc = Upload_notify(conn, handler, "start", tmp_name); check(rc == 0, "Failed to notify of the start of upload."); rc = stream_to_disk(conn->iob, content_len, tmpfd); check(rc == 0, "Failed to stream to disk."); rc = Upload_notify(conn, handler, "done", tmp_name); check(rc == 0, "Failed to notify the end of the upload."); bdestroy(result); bdestroy(tmp_name); fdclose(tmpfd); return 0; error: if(result) bdestroy(result); fdclose(tmpfd); if(tmp_name != NULL) { unlink((char *)tmp_name->data); bdestroy(tmp_name); } return -1; }
static void proc_fini_parent(struct proc *p) { /* close unneeded file descriptors */ fdclose(p->fd[0][0]); p->fd[0][0] = -1; fdclose(p->fd[1][1]); p->fd[1][1] = -1; fdclose(p->fd[2][1]); p->fd[2][1] = -1; }
void Server_destroy(Server *srv) { if(srv) { if(srv->use_ssl) { free(srv->rng_ctx); mbedtls_x509_crt_free(&srv->own_cert); mbedtls_pk_free(&srv->pk_key); // srv->ciphers freed (if non-default) by h_free } RouteMap_destroy(srv->hosts); Server_destroy_handlers(srv); bdestroy(srv->bind_addr); bdestroy(srv->uuid); bdestroy(srv->chroot); bdestroy(srv->access_log); bdestroy(srv->error_log); bdestroy(srv->pid_file); bdestroy(srv->control_port); bdestroy(srv->default_hostname); if(srv->listen_fd >= 0) fdclose(srv->listen_fd); h_free(srv); } }
int32_t krd4set_S(CSOUND *csound, KREAD4 *p) { /* open in curdir or pathname */ char soundiname[1024]; if (UNLIKELY((p->format = (int32_t)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } strNcpy(soundiname, ((STRINGDAT *)p->ifilcod)->data, 1023); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32_t)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->k[0] = p->k[1] = p->k[2] = p->k[3] = FL(0.0); return OK; }
int32_t kdmpset_p(CSOUND *csound, KDUMP *p) { /* open in curdir or pathname */ char soundoname[1024]; if (UNLIKELY((p->format = (int32_t)*p->iformat) < 1 || p->format > 8)) { return csound->InitError(csound, Str("unknown format request")); } if (UNLIKELY(p->format == 2 || p->format == 3)) { return csound->InitError(csound, Str("alaw and ulaw not implemented here")); } if (csound->ISSTRCOD(*p->ifilcod)) strNcpy(soundoname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundoname, p->ifilcod, "dumpk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundoname, "wb", "", dumpf_format_table[p->format], 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundoname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32_t)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = p->timcount; return OK; }
void terminate(int s) { MURDER = s == SIGTERM; switch(s) { case SIGHUP: if(!RELOAD) { RELOAD = 1; if(RELOAD_TASK) { tasksignal(RELOAD_TASK, s); } } break; default: if(!RUNNING) { log_info("SIGINT CAUGHT AGAIN, ASSUMING MURDER."); MURDER = 1; } else { RUNNING = 0; log_info("SHUTDOWN REQUESTED: %s", MURDER ? "MURDER" : "GRACEFUL (SIGINT again to EXIT NOW)"); Server *srv = Server_queue_latest(); if(srv != NULL) { fdclose(srv->listen_fd); } } break; } }
int32_t krdsset_p(CSOUND *csound, KREADS *p) { /* open in curdir or pathname */ char soundiname[1024]; if (csound->ISSTRCOD(*p->ifilcod)) strNcpy(soundiname, get_arg_string(csound, *p->ifilcod), 1023); else csound->strarg2name(csound, soundiname, p->ifilcod, "readk.", 0); if (p->fdch.fd != NULL) fdclose(csound, &(p->fdch)); p->fdch.fd = csound->FileOpen2(csound, &(p->f), CSFILE_STD, soundiname, "rb", "SFDIR;SSDIR", 0, 0); if (UNLIKELY(p->fdch.fd == NULL)) return csound->InitError(csound, Str("Cannot open %s"), soundiname); fdrecord(csound, &p->fdch); if ((p->timcount = (int32_t)(*p->iprd * CS_EKR)) <= 0) p->timcount = 1; p->countdown = 0; p->lasts = (char*)csound->Malloc(csound, INITSIZE); p->lasts[0] = '\0'; if (p->str->data == NULL) { p->str->data = csound->Calloc(csound, INITSIZE); p->str->size = INITSIZE; } return OK; }
long _sysclose(int fd) { fdtochan(fd, -1, 0, 0); fdclose(fd, 0); return 0; }
long sysclose(ulong *arg) { fdtochan(arg[0], -1, 0, 0); fdclose(arg[0], 0); return 0; }
void IOBuf_destroy(IOBuf *buf) { if(buf) { if(buf->use_ssl) { ssl_close_notify(&buf->ssl); ssl_free(&buf->ssl); } fdclose(buf->fd); h_free(buf); } }
int IOBuf_close(IOBuf *buf) { int rc = 0; if(buf) { if(buf->use_ssl) { rc = ssl_close_notify(&buf->ssl); } fdclose(buf->fd); } return rc; }
static int ftp_listmake( struct ftpsub_buf *fbf, int sockfd, SORT *p_sort, char *localdir, char *ftpnlstres, int fd, int numfile, int maxgetcnt) { #if 0 char csvdate[10+1]; char *p_dest; int retval; int getnum; int i; /* ファイルリストアップ結果ファイル読み込み */ if( file_read_p( numfile, ftpnlstres, fd, p_sort ) == ERROR ){ fdclose( fd, __LINE__ ); return( ERROR ); } /* 対象ファイルリスト作成 */ /* csvファイル名からファイルの日付のみを抽出 */ for( i = 0; i < numfile; i++ ) { p_dest = strrchr( p_sort[i].csvname, '.' ); sprintf( csvdate, "%.10s", p_dest - 10 ); p_sort[i].csvdate = atoi( csvdate ); } /* ファイルの日付を昇順に入れ替える */ qsort( p_sort, numfile, sizeof(SORT), (VOID*)date_comp ); /* 取得ファイル数指定 */ /* ・最大取得ファイル数以上は取得しない */ /* ・更新日時が最新のファイルは取得対象外 */ if( numfile > maxgetcnt ) { getnum = maxgetcnt; } else { getnum = numfile - 1; } /* 取得ファイルがあるか確認 */ if( getnum < 1 ){ tLog_Write( "%s取得ファイルなし", pcstr ); return( NORMAL ); } /* FTP GET DELETE 呼び出し */ retval = ftp_get_del( fbf, sockfd, p_sort, localdir, getnum ); return( retval ); #endif return 0; }
void FileRecord_destroy(FileRecord *file) { if(file) { if(!file->is_dir) { fdclose(file->fd); bdestroy(file->date); bdestroy(file->last_mod); bdestroy(file->header); bdestroy(file->etag); } bdestroy(file->full_path); // file->content_type is not owned by us free(file); } }
int kfgrpclose(Fgrp *f, int fd) { if(waserror()) return -1; /* * Take no reference on the chan because we don't really need the * data structure, and are calling fdtochan only for error checks. * fdclose takes care of processes racing through here. */ fdtochan(f, fd, -1, 0, 0); fdclose(f, fd); poperror(); return 0; }
void Register_disconnect(int fd) { assert(registrations && "Call Register_init."); hnode_t *hn = hash_lookup(registrations, (void *)(intptr_t)fd); if(hn) { debug("Unregistering %d", fd); hash_delete_free(registrations, hn); fdclose(fd); } else { log_err("Ident %d was unregistered but doesn't exist in registrations.", fd); } }
void sysclose(Ar0* ar0, ...) { int fd; va_list list; va_start(list, ar0); /* * int close(int fd); */ fd = va_arg(list, int); va_end(list); fdtochan(fd, -1, 0, 0); fdclose(fd, 0); ar0->i = 0; }
int sys_socket(struct thread *td, struct socket_args *uap) { struct socket *so; struct file *fp; int fd, error, type, oflag, fflag; AUDIT_ARG_SOCKET(uap->domain, uap->type, uap->protocol); type = uap->type; oflag = 0; fflag = 0; if ((type & SOCK_CLOEXEC) != 0) { type &= ~SOCK_CLOEXEC; oflag |= O_CLOEXEC; } if ((type & SOCK_NONBLOCK) != 0) { type &= ~SOCK_NONBLOCK; fflag |= FNONBLOCK; } #ifdef MAC error = mac_socket_check_create(td->td_ucred, uap->domain, type, uap->protocol); if (error != 0) return (error); #endif error = falloc(td, &fp, &fd, oflag); if (error != 0) return (error); /* An extra reference on `fp' has been held for us by falloc(). */ error = socreate(uap->domain, &so, type, uap->protocol, td->td_ucred, td); if (error != 0) { fdclose(td, fp, fd); } else { finit(fp, FREAD | FWRITE | fflag, DTYPE_SOCKET, so, &socketops); if ((fflag & FNONBLOCK) != 0) (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td); td->td_retval[0] = fd; } fdrop(fp, td); return (error); }
int sysclose(int fd) { ERRSTACK(1); struct fd_table *fdt = ¤t->open_files; if (waserror()) { poperror(); return -1; } /* * Take no reference on the chan because we don't really need the * data structure, and are calling fdtochan only for error checks. * fdclose takes care of processes racing through here. */ fdtochan(fdt, fd, -1, 0, 0); fdclose(fdt, fd); poperror(); return 0; }
void complete_shutdown(Server *srv) { fdclose(srv->listen_fd); int attempts = 0; int rc = 0; rc = taskallsignal(SIGTERM); check(rc != -1, "Failed to send the TERM signal to all internal tasks."); log_info("Shutting down all running tasks as gracefully as possible."); // we will always be the last task, so wait until only 1 is running, us for(attempts = 0; tasksrunning() > 1 && attempts < 20; attempts++) { rc = taskallsignal(SIGTERM); check(rc != -1, "Failed to send the TERM signal to internal tasks on attempt: %d.", attempts); } log_info("Tasks now running (including main task): %d", tasksrunning()); Control_port_stop(); rc = Log_term(); check(rc != -1, "Failed to shutdown the logging subsystem."); Setting_destroy(); MIME_destroy(); if(access((char *)srv->pid_file->data, F_OK) == 0) { log_info("Removing pid file %s", bdata(srv->pid_file)); rc = unlink((const char *)srv->pid_file->data); check(rc != -1, "Failed to unlink pid_file: %s", bdata(srv->pid_file)); } rc = Server_queue_destroy(); check(rc == 0, "Failed cleaning up the server run queue."); Register_destroy(); fdshutdown(); taskexitall(0); error: taskexitall(1); }
char *test_IOBuf_send_operations() { Connection *conn = fake_conn("/dev/null", O_WRONLY); mu_assert(conn != NULL, "Failed to allocate buf."); IOBuf *buf = conn->iob; mu_assert(Register_fd_exists(IOBuf_fd(buf)) != NULL, "Damn fd isn't registered."); int rc = IOBuf_send(buf, "012345789", 10); mu_assert(!IOBuf_closed(buf), "Should not be closed."); mu_assert(rc == 10, "Should have sent 10 bytes."); fdclose(IOBuf_fd(buf)); rc = IOBuf_send(buf, "012345789", 10); mu_assert(IOBuf_closed(buf), "Should be closed."); mu_assert(rc == -1, "Should send nothing."); fake_conn_close(conn); return NULL; }
static void proc_fini(struct proc *p) { /* XXX: do I ever get here when these aren't already closed? */ fdclose(p->fd[0][0]); p->fd[0][0] = -1; fdclose(p->fd[0][1]); p->fd[0][1] = -1; fdclose(p->fd[1][0]); p->fd[1][0] = -1; fdclose(p->fd[1][1]); p->fd[1][1] = -1; fdclose(p->fd[2][0]); p->fd[2][0] = -1; fdclose(p->fd[2][1]); p->fd[2][1] = -1; string_fini(&p->stdio[0]); string_fini(&p->stdio[1]); string_fini(&p->stdio[2]); }
/* * it is possible here for a failure to occur when stderr is closed. */ static void _fdmove(int oldfd, int newfd) { int r, retry = 0; restart: r = dup2(oldfd, newfd); if (-1 == r) { switch(errno) { case EINTR: if (++retry > NPROC + 1) { _log_dup2(LOG_INFO, errno, oldfd); } goto restart; default: _die_dup2(errno, oldfd); } } fdclose(oldfd); }
int Register_disconnect(int fd) { check(fd < MAX_REGISTERED_FDS, "FD given to register is greater than max."); check(fd >= 0, "Invalid FD given for disconnect."); Registration *reg = darray_get(REGISTRATIONS, fd); check_debug(Register_valid(reg), "Attempt to unregister FD %d which is already gone.", fd); check(reg->fd == fd, "Asked to disconnect fd %d but register had %d", fd, reg->fd); if(IOBuf_close(reg->data->iob) != 0) { debug("Failed to close IOBuffer, probably SSL error."); } Register_clear(reg); // tracking the number of things we're processing NUM_REG_FD--; return 0; error: fdclose(fd); return -1; }
/* * We only need open() and close() routines. open() calls socreate() * to allocate a "real" object behind the stream and mallocs some state * info for use by the svr4 emulator; close() deallocates the state * information and passes the underlying object to the normal socket close * routine. */ static int streamsopen(struct cdev *dev, int oflags, int devtype, struct thread *td) { struct filedesc *fdp; struct svr4_strm *st; struct socket *so; struct file *fp; int family, type, protocol; int error, fd; if (td->td_dupfd >= 0) return ENODEV; switch (dev2unit(dev)) { case dev_udp: family = AF_INET; type = SOCK_DGRAM; protocol = IPPROTO_UDP; break; case dev_tcp: family = AF_INET; type = SOCK_STREAM; protocol = IPPROTO_TCP; break; case dev_ip: case dev_rawip: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_IP; break; case dev_icmp: family = AF_INET; type = SOCK_RAW; protocol = IPPROTO_ICMP; break; case dev_unix_dgram: family = AF_LOCAL; type = SOCK_DGRAM; protocol = 0; break; case dev_unix_stream: case dev_unix_ord_stream: family = AF_LOCAL; type = SOCK_STREAM; protocol = 0; break; case dev_ptm: return svr4_ptm_alloc(td); default: return EOPNOTSUPP; } fdp = td->td_proc->p_fd; if ((error = falloc(td, &fp, &fd, 0)) != 0) return error; /* An extra reference on `fp' has been held for us by falloc(). */ error = socreate(family, &so, type, protocol, td->td_ucred, td); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return error; } finit(fp, FREAD | FWRITE, DTYPE_SOCKET, so, &svr4_netops); /* * Allocate a stream structure and attach it to this socket. * We don't bother locking so_emuldata for SVR4 stream sockets as * its value is constant for the lifetime of the stream once it * is initialized here. */ st = malloc(sizeof(struct svr4_strm), M_TEMP, M_WAITOK); st->s_family = so->so_proto->pr_domain->dom_family; st->s_cmd = ~0; st->s_afd = -1; st->s_eventmask = 0; so->so_emuldata = st; fdrop(fp, td); td->td_dupfd = fd; return ENXIO; }
/* System calls. */ int sys_shm_open(struct thread *td, struct shm_open_args *uap) { struct filedesc *fdp; struct shmfd *shmfd; struct file *fp; char *path; Fnv32_t fnv; mode_t cmode; int fd, error; #ifdef CAPABILITY_MODE /* * shm_open(2) is only allowed for anonymous objects. */ if (IN_CAPABILITY_MODE(td) && (uap->path != SHM_ANON)) return (ECAPMODE); #endif if ((uap->flags & O_ACCMODE) != O_RDONLY && (uap->flags & O_ACCMODE) != O_RDWR) return (EINVAL); if ((uap->flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC)) != 0) return (EINVAL); fdp = td->td_proc->p_fd; cmode = (uap->mode & ~fdp->fd_cmask) & ACCESSPERMS; error = falloc(td, &fp, &fd, 0); if (error) return (error); /* A SHM_ANON path pointer creates an anonymous object. */ if (uap->path == SHM_ANON) { /* A read-only anonymous object is pointless. */ if ((uap->flags & O_ACCMODE) == O_RDONLY) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return (EINVAL); } shmfd = shm_alloc(td->td_ucred, cmode); } else { path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); error = copyinstr(uap->path, path, MAXPATHLEN, NULL); /* Require paths to start with a '/' character. */ if (error == 0 && path[0] != '/') error = EINVAL; if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); free(path, M_SHMFD); return (error); } fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&shm_dict_lock); shmfd = shm_lookup(path, fnv); if (shmfd == NULL) { /* Object does not yet exist, create it if requested. */ if (uap->flags & O_CREAT) { #ifdef MAC error = mac_posixshm_check_create(td->td_ucred, path); if (error == 0) { #endif shmfd = shm_alloc(td->td_ucred, cmode); shm_insert(path, fnv, shmfd); #ifdef MAC } #endif } else { free(path, M_SHMFD); error = ENOENT; } } else { /* * Object already exists, obtain a new * reference if requested and permitted. */ free(path, M_SHMFD); if ((uap->flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) error = EEXIST; else { #ifdef MAC error = mac_posixshm_check_open(td->td_ucred, shmfd, FFLAGS(uap->flags & O_ACCMODE)); if (error == 0) #endif error = shm_access(shmfd, td->td_ucred, FFLAGS(uap->flags & O_ACCMODE)); } /* * Truncate the file back to zero length if * O_TRUNC was specified and the object was * opened with read/write. */ if (error == 0 && (uap->flags & (O_ACCMODE | O_TRUNC)) == (O_RDWR | O_TRUNC)) { #ifdef MAC error = mac_posixshm_check_truncate( td->td_ucred, fp->f_cred, shmfd); if (error == 0) #endif shm_dotruncate(shmfd, 0); } if (error == 0) shm_hold(shmfd); } sx_xunlock(&shm_dict_lock); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return (error); } } finit(fp, FFLAGS(uap->flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); FILEDESC_XLOCK(fdp); if (fdp->fd_ofiles[fd] == fp) fdp->fd_ofileflags[fd] |= UF_EXCLOSE; FILEDESC_XUNLOCK(fdp); td->td_retval[0] = fd; fdrop(fp, td); return (0); }
long bindmount(int ismount, int fd, int afd, char* arg0, char* arg1, ulong flag, char* spec) { int ret; Chan *c0, *c1, *ac, *bc; struct{ Chan *chan; Chan *authchan; char *spec; int flags; }bogus; if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); if(ismount){ validaddr((ulong)spec, 1, 0); spec = validnamedup(spec, 1); if(waserror()){ free(spec); nexterror(); } if(up->pgrp->noattach) error(Enoattach); ac = nil; bc = fdtochan(fd, ORDWR, 0, 1); if(waserror()) { if(ac) cclose(ac); cclose(bc); nexterror(); } if(afd >= 0) ac = fdtochan(afd, ORDWR, 0, 1); bogus.flags = flag & MCACHE; bogus.chan = bc; bogus.authchan = ac; bogus.spec = spec; ret = devno('M', 0); c0 = devtab[ret]->attach((char*)&bogus); poperror(); /* ac bc */ if(ac) cclose(ac); cclose(bc); }else{ spec = 0; validaddr((ulong)arg0, 1, 0); c0 = namec(arg0, Abind, 0, 0); } if(waserror()){ cclose(c0); nexterror(); } validaddr((ulong)arg1, 1, 0); c1 = namec(arg1, Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } ret = cmount(&c0, c1, flag, spec); poperror(); cclose(c1); poperror(); cclose(c0); if(ismount){ fdclose(fd, 0); poperror(); free(spec); } return ret; }
/* Other helper routines. */ static int ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode, unsigned int value, int flags, int compat32) { struct filedesc *fdp; struct ksem *ks; struct file *fp; char *path; Fnv32_t fnv; int error, fd; if (value > SEM_VALUE_MAX) return (EINVAL); fdp = td->td_proc->p_fd; mode = (mode & ~fdp->fd_cmask) & ACCESSPERMS; error = falloc(td, &fp, &fd, O_CLOEXEC); if (error) { if (name == NULL) error = ENOSPC; return (error); } /* * Go ahead and copyout the file descriptor now. This is a bit * premature, but it is a lot easier to handle errors as opposed * to later when we've possibly created a new semaphore, etc. */ error = ksem_create_copyout_semid(td, semidp, fd, compat32); if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); return (error); } if (name == NULL) { /* Create an anonymous semaphore. */ ks = ksem_alloc(td->td_ucred, mode, value); if (ks == NULL) error = ENOSPC; else ks->ks_flags |= KS_ANONYMOUS; } else { path = malloc(MAXPATHLEN, M_KSEM, M_WAITOK); error = copyinstr(name, path, MAXPATHLEN, NULL); /* Require paths to start with a '/' character. */ if (error == 0 && path[0] != '/') error = EINVAL; if (error) { fdclose(fdp, fp, fd, td); fdrop(fp, td); free(path, M_KSEM); return (error); } fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&ksem_dict_lock); ks = ksem_lookup(path, fnv); if (ks == NULL) { /* Object does not exist, create it if requested. */ if (flags & O_CREAT) { ks = ksem_alloc(td->td_ucred, mode, value); if (ks == NULL) error = ENFILE; else { ksem_insert(path, fnv, ks); path = NULL; } } else error = ENOENT; } else { /* * Object already exists, obtain a new * reference if requested and permitted. */ if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) error = EEXIST; else { #ifdef MAC error = mac_posixsem_check_open(td->td_ucred, ks); if (error == 0) #endif error = ksem_access(ks, td->td_ucred); } if (error == 0) ksem_hold(ks); #ifdef INVARIANTS else ks = NULL; #endif } sx_xunlock(&ksem_dict_lock); if (path) free(path, M_KSEM); } if (error) { KASSERT(ks == NULL, ("ksem_create error with a ksem")); fdclose(fdp, fp, fd, td); fdrop(fp, td); return (error); } KASSERT(ks != NULL, ("ksem_create w/o a ksem")); finit(fp, FREAD | FWRITE, DTYPE_SEM, ks, &ksem_ops); fdrop(fp, td); return (0); }
/* if dc is non-zero, it means we're doing a mount and dc is the mount device to use. */ static int bindmount(int dc, int fd, int afd, char* arg0, char* arg1, int flag, char* spec) { Proc *up = externup(); int i; Dev *dev; Chan *c0, *c1, *ac, *bc; struct{ Chan *chan; Chan *authchan; char *spec; int flags; }bogus; if((flag&~MMASK) || (flag&MORDER)==(MBEFORE|MAFTER)) error(Ebadarg); bogus.flags = flag & MCACHE; if(dc){ if (! checkdc(dc)) error(Ebadarg); if(up->pgrp->noattach) error(Enoattach); ac = nil; bc = fdtochan(fd, ORDWR, 0, 1); if(waserror()) { if(ac) cclose(ac); cclose(bc); nexterror(); } if(afd >= 0) ac = fdtochan(afd, ORDWR, 0, 1); bogus.chan = bc; bogus.authchan = ac; bogus.spec = validaddr(spec, 1, 0); if(waserror()) error(Ebadspec); spec = validnamedup(spec, 1); poperror(); if(waserror()){ free(spec); nexterror(); } dev = devtabget(dc, 0); //XDYNX if(waserror()){ //devtabdecr(dev); nexterror(); } c0 = dev->attach((char*)&bogus); poperror(); //devtabdecr(dev); poperror(); /* spec */ free(spec); poperror(); /* ac bc */ if(ac) cclose(ac); cclose(bc); }else{ bogus.spec = nil; c0 = namec(validaddr(arg0, 1, 0), Abind, 0, 0); } if(waserror()){ cclose(c0); nexterror(); } c1 = namec(validaddr(arg1, 1, 0), Amount, 0, 0); if(waserror()){ cclose(c1); nexterror(); } i = cmount(&c0, c1, flag, bogus.spec); poperror(); cclose(c1); poperror(); cclose(c0); if(dc) fdclose(fd, 0); return i; }