value lwt_unix_init_notification() { SOCKET sockets[2]; switch (notification_mode) { case NOTIFICATION_MODE_NOT_INITIALIZED: notification_mode = NOTIFICATION_MODE_NONE; init_notifications(); break; case NOTIFICATION_MODE_WINDOWS: notification_mode = NOTIFICATION_MODE_NONE; closesocket(socket_r); closesocket(socket_w); break; case NOTIFICATION_MODE_NONE: break; default: caml_failwith("notification system in unknown state"); } /* Since pipes do not works with select, we need to use a pair of sockets. */ lwt_unix_socketpair(AF_INET, SOCK_STREAM, IPPROTO_TCP, sockets); socket_r = set_close_on_exec(sockets[0]); socket_w = set_close_on_exec(sockets[1]); notification_mode = NOTIFICATION_MODE_WINDOWS; notification_send = windows_notification_send; notification_recv = windows_notification_recv; return win_alloc_socket(socket_r); }
int OOBase::POSIX::socketpair(int type, SmartFD fds[2]) { int fd[2] = {-1, -1}; #if defined(SOCK_CLOEXEC) if (::socketpair(PF_UNIX,type | SOCK_CLOEXEC,0,fd) != 0) #else if (::socketpair(PF_UNIX,type,0,fd) != 0) #endif { return errno; } #if !defined(SOCK_CLOEXEC) int err = set_close_on_exec(fd[0],true); if (!err) err = set_close_on_exec(fd[1],true); if (err) { POSIX::close(fd[0]); POSIX::close(fd[1]); return err; } #endif fds[0] = fd[0]; fds[1] = fd[1]; return 0; }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { int error = 0; int __user *argp = (int __user *)arg; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: /* BKL needed to avoid races tweaking f_flags */ lock_kernel(); error = ioctl_fionbio(filp, argp); unlock_kernel(); break; case FIOASYNC: /* BKL needed to avoid races tweaking f_flags */ lock_kernel(); error = ioctl_fioasync(fd, filp, argp); unlock_kernel(); break; case FIOQSIZE: if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || S_ISREG(filp->f_path.dentry->d_inode->i_mode) || S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; default: if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = vfs_ioctl(filp, cmd, arg); break; } return error; }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { int error = 0; int __user *argp = (int __user *)arg; struct inode *inode = file_inode(filp); switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: error = ioctl_fionbio(filp, argp); break; case FIOASYNC: error = ioctl_fioasync(fd, filp, argp); break; case FIOQSIZE: if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) { loff_t res = inode_get_bytes(inode); error = copy_to_user(argp, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; case FS_IOC_FIEMAP: return ioctl_fiemap(filp, arg); case FIGETBSZ: return put_user(inode->i_sb->s_blocksize, argp); default: if (S_ISREG(inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = vfs_ioctl(filp, cmd, arg); break; } return error; }
static void do_pipe (int *pipe_fds) { retry_pipe: if (pipe (pipe_fds) < 0) { if (errno == EINTR) goto retry_pipe; g_error ("error creating pipe: %s", g_strerror (errno)); } set_close_on_exec (pipe_fds[0]); set_close_on_exec (pipe_fds[1]); }
static SOCKET conn2(const char *host, int port, int use_ssl, char *ebuf, size_t ebuf_len) { struct sockaddr_in sin; struct hostent *he; SOCKET sock = INVALID_SOCKET; if (host == NULL) { snprintf(ebuf, ebuf_len, "%s", "NULL host"); } else if (use_ssl && SSLv23_client_method == NULL) { snprintf(ebuf, ebuf_len, "%s", "SSL is not initialized"); // TODO(lsm): use something threadsafe instead of gethostbyname() } else if ((he = gethostbyname(host)) == NULL) { snprintf(ebuf, ebuf_len, "gethostbyname(%s): %s", host, strerror(ERRNO)); } else if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { snprintf(ebuf, ebuf_len, "socket(): %s", strerror(ERRNO)); } else { set_close_on_exec(sock); sin.sin_family = AF_INET; sin.sin_port = htons((uint16_t) port); sin.sin_addr = * (struct in_addr *) he->h_addr_list[0]; if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) != 0) { snprintf(ebuf, ebuf_len, "connect(%s:%d): %s", host, port, strerror(ERRNO)); closesocket(sock); sock = INVALID_SOCKET; } } return sock; }
value lwt_unix_init_notification() { switch (notification_mode) { #if defined(HAVE_EVENTFD) case NOTIFICATION_MODE_EVENTFD: notification_mode = NOTIFICATION_MODE_NONE; if (close(notification_fd) == -1) uerror("close", Nothing); break; #endif case NOTIFICATION_MODE_PIPE: notification_mode = NOTIFICATION_MODE_NONE; if (close(notification_fds[0]) == -1) uerror("close", Nothing); if (close(notification_fds[1]) == -1) uerror("close", Nothing); break; case NOTIFICATION_MODE_NOT_INITIALIZED: notification_mode = NOTIFICATION_MODE_NONE; init_notifications(); break; case NOTIFICATION_MODE_NONE: break; default: caml_failwith("notification system in unknown state"); } #if defined(HAVE_EVENTFD) notification_fd = eventfd(0, 0); if (notification_fd != -1) { notification_mode = NOTIFICATION_MODE_EVENTFD; notification_send = eventfd_notification_send; notification_recv = eventfd_notification_recv; set_close_on_exec(notification_fd); return Val_int(notification_fd); } #endif if (pipe(notification_fds) == -1) uerror("pipe", Nothing); set_close_on_exec(notification_fds[0]); set_close_on_exec(notification_fds[1]); notification_mode = NOTIFICATION_MODE_PIPE; notification_send = pipe_notification_send; notification_recv = pipe_notification_recv; return Val_int(notification_fds[0]); }
static int socket_server_wait_peer(void) { struct sockaddr_un addr; socklen_t len; int fd; memset(&addr, 0, sizeof(addr)); len = sizeof(addr); fd = accept(globals.socket, (struct sockaddr *)&addr, &len); if (fd == -1) { DEBUG(DEBUG_CRIT,("Unable to accept on ctdb socket '%s': %s\n", globals.socketname, strerror(errno))); return -1; } //set_blocking(fd, false); set_close_on_exec(fd); return fd; }
/* called when we get contacted by another node currently makes no attempt to check if the connection is really from a ctdb node in our cluster */ static void ctdb_listen_event(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *private_data) { struct ctdb_context *ctdb = talloc_get_type(private_data, struct ctdb_context); struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); ctdb_sock_addr addr; socklen_t len; int fd, nodeid; struct ctdb_incoming *in; int one = 1; const char *incoming_node; memset(&addr, 0, sizeof(addr)); len = sizeof(addr); fd = accept(ctcp->listen_fd, (struct sockaddr *)&addr, &len); if (fd == -1) return; incoming_node = ctdb_addr_to_str(&addr); nodeid = ctdb_ip_to_nodeid(ctdb, incoming_node); if (nodeid == -1) { DEBUG(DEBUG_ERR, ("Refused connection from unknown node %s\n", incoming_node)); close(fd); return; } in = talloc_zero(ctcp, struct ctdb_incoming); in->fd = fd; in->ctdb = ctdb; set_nonblocking(in->fd); set_close_on_exec(in->fd); DEBUG(DEBUG_DEBUG, (__location__ " Created SOCKET FD:%d to incoming ctdb connection\n", fd)); if (setsockopt(in->fd,SOL_SOCKET,SO_KEEPALIVE,(char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set KEEPALIVE on fd - %s\n", strerror(errno))); } in->queue = ctdb_queue_setup(ctdb, in, in->fd, CTDB_TCP_ALIGNMENT, ctdb_tcp_read_cb, in, "ctdbd-%s", incoming_node); }
/* create a unix domain socket and bind it return a file descriptor open on the socket */ static int socket_server_create(void) { struct sockaddr_un addr; globals.socket = socket(AF_UNIX, SOCK_STREAM, 0); if (globals.socket == -1) { DEBUG(DEBUG_CRIT,("Unable to create server socket: %s\n", strerror(errno))); return -1; } set_close_on_exec(globals.socket); //set_blocking(globals.socket, false); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, globals.socketname, sizeof(addr.sun_path)-1); if (bind(globals.socket, (struct sockaddr *)&addr, sizeof(addr)) == -1) { DEBUG(DEBUG_CRIT,("Unable to bind on socket '%s': %s\n", globals.socketname, strerror(errno))); goto failed; } if (chown(globals.socketname, geteuid(), getegid()) != 0 || chmod(globals.socketname, 0700) != 0) { DEBUG(DEBUG_CRIT,("Unable to secure socket '%s': %s\n", globals.socketname, strerror(errno))); goto failed; } if (listen(globals.socket, 100) != 0) { DEBUG(DEBUG_CRIT,("Unable to listen on socket '%s': %s\n", globals.socketname, strerror(errno))); goto failed; } return 0; failed: close(globals.socket); globals.socket = -1; return -1; }
/* * Signal that we are now inside a directory pointed to by dir_fd. * The caller can't tell if this is the first time this happens, so * we have to be careful not to call dup() more than once */ static void inside_dir(int dir_fd) { if (ftsoptions & FTS_CWDFD) { assert (dir_fd == AT_FDCWD || dir_fd >= 0); state.cwd_dir_fd = dir_fd; if (curr_fd < 0) { if (AT_FDCWD == dir_fd) { curr_fd = AT_FDCWD; } else if (dir_fd >= 0) { curr_fd = dup(dir_fd); set_close_on_exec(curr_fd); } else { /* curr_fd is invalid, but dir_fd is also invalid. * This should not have happened. */ assert (curr_fd >= 0 || dir_fd >= 0); } } } else { /* FTS_CWDFD is not in use. We can always assume that * AT_FDCWD refers to the directory we are currentl searching. * * Therefore there is nothing to do. */ } }
/** * Closes all file descriptors greater or equal to ``first_fd''. */ void close_file_descriptors(const int first_fd) { int fd; g_return_if_fail(first_fd >= 0); if (try_close_from(first_fd)) return; fd = getdtablesize() - 1; while (fd >= first_fd) { #ifdef HAVE_GTKOSXAPPLICATION /* OS X doesn't allow fds being closed not opened by us. During * GUI initialisation a new kqueue fd is created for UI events. This * is visible to us as a fifo which we are not allowed to close. * Set close on exec on all fifo's so we won't leak any of our other * fifo's * -- JA 2011-11-28 */ if (is_a_fifo(fd)) set_close_on_exec(fd); else #endif /* OS X frowns upon random fds being closed --RAM 2011-11-13 */ if (fd_is_opened(fd)) { if (close(fd)) { #if defined(F_MAXFD) fd = fcntl(0, F_MAXFD); continue; #endif /* F_MAXFD */ } } fd--; } }
/** * Open file, returning file descriptor or -1 on error with errno set. * Errors are logged as a warning, unless `missing' is true, in which * case no error is logged for ENOENT. */ static int do_open(const char *path, int flags, int mode, bool missing, bool absolute) { const char *what; int fd; if (absolute && !is_absolute_path(path)) { s_warning("%s(): can't open absolute \"%s\": relative path", G_STRFUNC, path); errno = EPERM; return -1; } #ifdef O_NOCTTY flags |= O_NOCTTY; #endif /* O_NOCTTY */ fd = open(path, flags, mode); if (fd < 0) { if (flags & O_CREAT) what = "create"; else if (flags & O_RDONLY) what = "read"; else if (flags & O_WRONLY) what = "write into"; else what = "open"; /* * If we ran out of file descriptors, try to reclaim one from the * banning pool and retry. */ if ( (errno == EMFILE || errno == ENFILE) && reclaim_fd != NULL && (*reclaim_fd)() ) { fd = open(path, flags, mode); if (fd >= 0) { s_warning("%s(): had to close a banned fd to %s file", G_STRFUNC, what); } } } if (fd >= 0) { fd = get_non_stdio_fd(fd); set_close_on_exec(fd); /* Just in case */ return fd; } /* * Hack for broken libc, which can return -1 with errno = 0! * This happens when compiling with gcc-3.x and linking with -lpthread * on a Debian linux system. * --RAM, 15/02/2004 */ if (errno == 0) { s_warning("%s(): open() returned -1 with errno = 0, assuming ENOENT", G_STRFUNC); errno = ENOENT; } if (!missing || errno != ENOENT) { s_warning("%s(): can't %s file \"%s\": %m", G_STRFUNC, what, path); } return -1; }
int main(int argc, char *argv[]) { int log_fd, write_fd; pid_t pid; int status, output, ret; progname = argv[0]; if (argc < 5) { usage(); exit(1); } reset_scheduler(); log_fd = atoi(argv[1]); write_fd = atoi(argv[2]); set_close_on_exec(write_fd); close(STDOUT_FILENO); close(STDERR_FILENO); dup2(log_fd, STDOUT_FILENO); dup2(log_fd, STDERR_FILENO); close(log_fd); if (setpgid(0, 0) != 0) { fprintf(stderr, "Failed to create process group for event script - %s\n", strerror(errno)); exit(1); } signal(SIGTERM, sigterm); pid = fork(); if (pid < 0) { int save_errno = errno; fprintf(stderr, "Failed to fork - %s\n", strerror(errno)); sys_write(write_fd, &save_errno, sizeof(save_errno)); exit(1); } if (pid == 0) { ret = check_executable(argv[3]); if (ret != 0) { _exit(ret); } ret = execv(argv[3], &argv[3]); if (ret != 0) { int save_errno = errno; fprintf(stderr, "Error executing '%s' - %s\n", argv[3], strerror(save_errno)); } /* This should never happen */ _exit(ENOEXEC); } ret = waitpid(pid, &status, 0); if (ret == -1) { output = -errno; fprintf(stderr, "waitpid() failed - %s\n", strerror(errno)); sys_write(write_fd, &output, sizeof(output)); exit(1); } if (WIFEXITED(status)) { output = WEXITSTATUS(status); /* Only errors should be returned as -ve values */ if (output == ENOENT || output == ENOEXEC) { output = -output; } sys_write(write_fd, &output, sizeof(output)); exit(0); } if (WIFSIGNALED(status)) { output = -EINTR; fprintf(stderr, "Process terminated with signal - %d\n", WTERMSIG(status)); sys_write(write_fd, &output, sizeof(output)); exit(0); } fprintf(stderr, "waitpid() status=%d\n", status); exit(1); }
/* * Schedule a new lock child process * Set up callback handler and timeout handler */ static void ctdb_lock_schedule(struct ctdb_context *ctdb) { struct lock_context *lock_ctx, *next_ctx, *active_ctx; int ret; TALLOC_CTX *tmp_ctx; const char *helper = BINDIR "/ctdb_lock_helper"; static const char *prog = NULL; char **args; if (prog == NULL) { const char *t; t = getenv("CTDB_LOCK_HELPER"); if (t != NULL) { prog = talloc_strdup(ctdb, t); } else { prog = talloc_strdup(ctdb, helper); } CTDB_NO_MEMORY_VOID(ctdb, prog); } if (ctdb->lock_pending == NULL) { return; } /* Find a lock context with requests */ lock_ctx = ctdb->lock_pending; while (lock_ctx != NULL) { next_ctx = lock_ctx->next; if (! lock_ctx->req_queue) { DEBUG(DEBUG_INFO, ("Removing lock context without lock requests\n")); DLIST_REMOVE(ctdb->lock_pending, lock_ctx); ctdb->lock_num_pending--; CTDB_DECREMENT_STAT(ctdb, locks.num_pending); if (lock_ctx->ctdb_db) { CTDB_DECREMENT_DB_STAT(lock_ctx->ctdb_db, locks.num_pending); } talloc_free(lock_ctx); } else { active_ctx = find_lock_context(ctdb->lock_current, lock_ctx->ctdb_db, lock_ctx->key, lock_ctx->priority, lock_ctx->type); if (active_ctx == NULL) { if (lock_ctx->ctdb_db == NULL || lock_ctx->ctdb_db->lock_num_current < MAX_LOCK_PROCESSES_PER_DB) { /* Found a lock context with lock requests */ break; } } /* There is already a child waiting for the * same key. So don't schedule another child * just yet. */ } lock_ctx = next_ctx; } if (lock_ctx == NULL) { return; } lock_ctx->child = -1; ret = pipe(lock_ctx->fd); if (ret != 0) { DEBUG(DEBUG_ERR, ("Failed to create pipe in ctdb_lock_schedule\n")); return; } set_close_on_exec(lock_ctx->fd[0]); /* Create data for child process */ tmp_ctx = talloc_new(lock_ctx); if (tmp_ctx == NULL) { DEBUG(DEBUG_ERR, ("Failed to allocate memory for helper args\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); return; } /* Create arguments for lock helper */ args = lock_helper_args(tmp_ctx, lock_ctx, lock_ctx->fd[1]); if (args == NULL) { DEBUG(DEBUG_ERR, ("Failed to create lock helper args\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); talloc_free(tmp_ctx); return; } lock_ctx->child = vfork(); if (lock_ctx->child == (pid_t)-1) { DEBUG(DEBUG_ERR, ("Failed to create a child in ctdb_lock_schedule\n")); close(lock_ctx->fd[0]); close(lock_ctx->fd[1]); talloc_free(tmp_ctx); return; } /* Child process */ if (lock_ctx->child == 0) { ret = execv(prog, args); if (ret < 0) { DEBUG(DEBUG_ERR, ("Failed to execute helper %s (%d, %s)\n", prog, errno, strerror(errno))); } _exit(1); } /* Parent process */ ctdb_track_child(ctdb, lock_ctx->child); close(lock_ctx->fd[1]); talloc_set_destructor(lock_ctx, ctdb_lock_context_destructor); talloc_free(tmp_ctx); /* Set up timeout handler */ lock_ctx->ttimer = tevent_add_timer(ctdb->ev, lock_ctx, timeval_current_ofs(10, 0), ctdb_lock_timeout_handler, (void *)lock_ctx); if (lock_ctx->ttimer == NULL) { ctdb_kill(ctdb, lock_ctx->child, SIGKILL); lock_ctx->child = -1; talloc_set_destructor(lock_ctx, NULL); close(lock_ctx->fd[0]); return; } /* Set up callback */ lock_ctx->tfd = tevent_add_fd(ctdb->ev, lock_ctx, lock_ctx->fd[0], EVENT_FD_READ, ctdb_lock_handler, (void *)lock_ctx); if (lock_ctx->tfd == NULL) { TALLOC_FREE(lock_ctx->ttimer); ctdb_kill(ctdb, lock_ctx->child, SIGKILL); lock_ctx->child = -1; talloc_set_destructor(lock_ctx, NULL); close(lock_ctx->fd[0]); return; } tevent_fd_set_auto_close(lock_ctx->tfd); /* Move the context from pending to current */ DLIST_REMOVE(ctdb->lock_pending, lock_ctx); ctdb->lock_num_pending--; DLIST_ADD_END(ctdb->lock_current, lock_ctx, NULL); if (lock_ctx->ctdb_db) { lock_ctx->ctdb_db->lock_num_current++; CTDB_INCREMENT_STAT(lock_ctx->ctdb, locks.num_current); CTDB_INCREMENT_DB_STAT(lock_ctx->ctdb_db, locks.num_current); } }
/* called when we should try and establish a tcp connection to a node */ void ctdb_tcp_node_connect(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { struct ctdb_node *node = talloc_get_type(private_data, struct ctdb_node); struct ctdb_tcp_node *tnode = talloc_get_type(node->private_data, struct ctdb_tcp_node); struct ctdb_context *ctdb = node->ctdb; ctdb_sock_addr sock_in; int sockin_size; int sockout_size; ctdb_sock_addr sock_out; ctdb_tcp_stop_connection(node); sock_out = node->address; tnode->fd = socket(sock_out.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (tnode->fd == -1) { DEBUG(DEBUG_ERR, (__location__ " Failed to create socket\n")); return; } set_nonblocking(tnode->fd); set_close_on_exec(tnode->fd); DEBUG(DEBUG_DEBUG, (__location__ " Created TCP SOCKET FD:%d\n", tnode->fd)); /* Bind our side of the socketpair to the same address we use to listen * on incoming CTDB traffic. * We must specify this address to make sure that the address we expose to * the remote side is actually routable in case CTDB traffic will run on * a dedicated non-routeable network. */ sock_in = *ctdb->address; /* AIX libs check to see if the socket address and length arguments are consistent with each other on calls like connect(). Can not get by with just sizeof(sock_in), need sizeof(sock_in.ip). */ switch (sock_in.sa.sa_family) { case AF_INET: sock_in.ip.sin_port = 0 /* Any port */; sockin_size = sizeof(sock_in.ip); sockout_size = sizeof(sock_out.ip); break; case AF_INET6: sock_in.ip6.sin6_port = 0 /* Any port */; sockin_size = sizeof(sock_in.ip6); sockout_size = sizeof(sock_out.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock_in.sa.sa_family)); close(tnode->fd); return; } if (bind(tnode->fd, (struct sockaddr *)&sock_in, sockin_size) == -1) { DEBUG(DEBUG_ERR, (__location__ " Failed to bind socket %s(%d)\n", strerror(errno), errno)); close(tnode->fd); return; } if (connect(tnode->fd, (struct sockaddr *)&sock_out, sockout_size) != 0 && errno != EINPROGRESS) { ctdb_tcp_stop_connection(node); tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, timeval_current_ofs(1, 0), ctdb_tcp_node_connect, node); return; } /* non-blocking connect - wait for write event */ tnode->connect_fde = tevent_add_fd(node->ctdb->ev, tnode, tnode->fd, TEVENT_FD_WRITE|TEVENT_FD_READ, ctdb_node_connect_write, node); /* don't give it long to connect - retry in one second. This ensures that we find a node is up quickly (tcp normally backs off a syn reply delay by quite a lot) */ tnode->connect_te = tevent_add_timer(ctdb->ev, tnode, timeval_current_ofs(1, 0), ctdb_tcp_node_connect, node); }
static int pmda_ctdb_daemon_connect(void) { const char *socket_name; int ret; struct sockaddr_un addr; ev = tevent_context_init(NULL); if (ev == NULL) { fprintf(stderr, "Failed to init event ctx\n"); return -1; } ctdb = ctdb_init(ev); if (ctdb == NULL) { fprintf(stderr, "Failed to init ctdb\n"); goto err_ev; } socket_name = getenv("CTDB_SOCKET"); if (socket_name == NULL) { socket_name = CTDB_SOCKET; } ret = ctdb_set_socketname(ctdb, socket_name); if (ret == -1) { fprintf(stderr, "ctdb_set_socketname failed - %s\n", ctdb_errstr(ctdb)); goto err_ctdb; } /* * ctdb_socket_connect() sets a default queue callback handler that * calls exit() if ctdbd is unavailable on recv, use our own wrapper to * work around this */ memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, ctdb->daemon.name, sizeof(addr.sun_path)); ctdb->daemon.sd = socket(AF_UNIX, SOCK_STREAM, 0); if (ctdb->daemon.sd == -1) { fprintf(stderr, "Failed to open client socket\n"); goto err_ctdb; } set_nonblocking(ctdb->daemon.sd); set_close_on_exec(ctdb->daemon.sd); if (connect(ctdb->daemon.sd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "Failed to connect to ctdb daemon via %s\n", ctdb->daemon.name); goto err_sd; } ctdb->daemon.queue = ctdb_queue_setup(ctdb, ctdb, ctdb->daemon.sd, CTDB_DS_ALIGNMENT, pmda_ctdb_q_read_cb, ctdb, "to-ctdbd"); if (ctdb->daemon.queue == NULL) { fprintf(stderr, "Failed to setup queue\n"); goto err_sd; } ctdb->pnn = ctdb_ctrl_getpnn(ctdb, timeval_current_ofs(3, 0), CTDB_CURRENT_NODE); if (ctdb->pnn == (uint32_t)-1) { fprintf(stderr, "Failed to get ctdb pnn\n"); goto err_sd; } return 0; err_sd: close(ctdb->daemon.sd); err_ctdb: talloc_free(ctdb); err_ev: talloc_free(ev); ctdb = NULL; return -1; }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { unsigned int flag; int on, error = 0; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ /* SunOS compatibility item. */ if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; break; case FIOASYNC: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = on ? FASYNC : 0; /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { lock_kernel(); error = filp->f_op->fasync(fd, filp, on); unlock_kernel(); } else error = -ENOTTY; } if (error != 0) break; if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; break; case FIOQSIZE: if (S_ISDIR(filp->f_dentry->d_inode->i_mode) || S_ISREG(filp->f_dentry->d_inode->i_mode) || S_ISLNK(filp->f_dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; default: if (S_ISREG(filp->f_dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = do_ioctl(filp, cmd, arg); break; } return error; }
asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { struct file * filp; unsigned int flag; int on, error = -EBADF; filp = fget(fd); if (!filp) goto out; error = security_file_ioctl(filp, cmd, arg); if (error) { fput(filp); goto out; } lock_kernel(); switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ /* SunOS compatibility item. */ if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; break; case FIOASYNC: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = on ? FASYNC : 0; /* Did FASYNC state change ? */ if ((flag ^ filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) error = filp->f_op->fasync(fd, filp, on); else error = -ENOTTY; } if (error != 0) break; if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; break; case FIOQSIZE: if (S_ISDIR(filp->f_dentry->d_inode->i_mode) || S_ISREG(filp->f_dentry->d_inode->i_mode) || S_ISLNK(filp->f_dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; default: error = -ENOTTY; if (S_ISREG(filp->f_dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else if (filp->f_op && filp->f_op->ioctl) error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); } unlock_kernel(); fput(filp); out: return error; }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { int error = 0; int __user *argp = (int __user *)arg; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: error = ioctl_fionbio(filp, argp); break; case FIOASYNC: error = ioctl_fioasync(fd, filp, argp); break; case FIOQSIZE: if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || S_ISREG(filp->f_path.dentry->d_inode->i_mode) || S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; case FS_IOC_FIEMAP: return ioctl_fiemap(filp, arg); case FIGETBSZ: { struct super_block *sb = filp->f_path.dentry->d_inode->i_sb; int __user *p = (int __user *)arg; if (sb->s_blocksize == 1ul << sb->s_blocksize_bits) return put_user(sb->s_blocksize, p); /* fail through */ } default: if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = vfs_ioctl(filp, cmd, arg); break; } return error; }
/* automatically find which address to listen on */ static int ctdb_tcp_listen_automatic(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); ctdb_sock_addr sock; int lock_fd, i; const char *lock_path = CTDB_RUNDIR "/.socket_lock"; struct flock lock; int one = 1; int sock_size; struct tevent_fd *fde; /* If there are no nodes, then it won't be possible to find * the first one. Log a failure and short circuit the whole * process. */ if (ctdb->num_nodes == 0) { DEBUG(DEBUG_CRIT,("No nodes available to attempt bind to - is the nodes file empty?\n")); return -1; } /* in order to ensure that we don't get two nodes with the same adddress, we must make the bind() and listen() calls atomic. The SO_REUSEADDR setsockopt only prevents double binds if the first socket is in LISTEN state */ lock_fd = open(lock_path, O_RDWR|O_CREAT, 0666); if (lock_fd == -1) { DEBUG(DEBUG_CRIT,("Unable to open %s\n", lock_path)); return -1; } lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 1; lock.l_pid = 0; if (fcntl(lock_fd, F_SETLKW, &lock) != 0) { DEBUG(DEBUG_CRIT,("Unable to lock %s\n", lock_path)); close(lock_fd); return -1; } for (i=0; i < ctdb->num_nodes; i++) { if (ctdb->nodes[i]->flags & NODE_FLAGS_DELETED) { continue; } sock = ctdb->nodes[i]->address; switch (sock.sa.sa_family) { case AF_INET: sock_size = sizeof(sock.ip); break; case AF_INET6: sock_size = sizeof(sock.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock.sa.sa_family)); continue; } ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (ctcp->listen_fd == -1) { ctdb_set_error(ctdb, "socket failed\n"); continue; } set_close_on_exec(ctcp->listen_fd); if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR, (char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n", strerror(errno))); } if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) == 0) { break; } if (errno == EADDRNOTAVAIL) { DEBUG(DEBUG_DEBUG,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); } else { DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); } close(ctcp->listen_fd); ctcp->listen_fd = -1; } if (i == ctdb->num_nodes) { DEBUG(DEBUG_CRIT,("Unable to bind to any of the node addresses - giving up\n")); goto failed; } ctdb->address = talloc_memdup(ctdb, &ctdb->nodes[i]->address, sizeof(ctdb_sock_addr)); if (ctdb->address == NULL) { ctdb_set_error(ctdb, "Out of memory at %s:%d", __FILE__, __LINE__); goto failed; } ctdb->name = talloc_asprintf(ctdb, "%s:%u", ctdb_addr_to_str(ctdb->address), ctdb_addr_to_port(ctdb->address)); if (ctdb->name == NULL) { ctdb_set_error(ctdb, "Out of memory at %s:%d", __FILE__, __LINE__); goto failed; } DEBUG(DEBUG_INFO,("ctdb chose network address %s\n", ctdb->name)); if (listen(ctcp->listen_fd, 10) == -1) { goto failed; } fde = tevent_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, TEVENT_FD_READ, ctdb_listen_event, ctdb); tevent_fd_set_auto_close(fde); close(lock_fd); return 0; failed: close(lock_fd); if (ctcp->listen_fd != -1) { close(ctcp->listen_fd); ctcp->listen_fd = -1; } return -1; }
/* listen on our own address */ int ctdb_tcp_listen(struct ctdb_context *ctdb) { struct ctdb_tcp *ctcp = talloc_get_type(ctdb->private_data, struct ctdb_tcp); ctdb_sock_addr sock; int sock_size; int one = 1; struct tevent_fd *fde; /* we can either auto-bind to the first available address, or we can use a specified address */ if (!ctdb->address) { return ctdb_tcp_listen_automatic(ctdb); } sock = *ctdb->address; switch (sock.sa.sa_family) { case AF_INET: sock_size = sizeof(sock.ip); break; case AF_INET6: sock_size = sizeof(sock.ip6); break; default: DEBUG(DEBUG_ERR, (__location__ " unknown family %u\n", sock.sa.sa_family)); goto failed; } ctcp->listen_fd = socket(sock.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); if (ctcp->listen_fd == -1) { ctdb_set_error(ctdb, "socket failed\n"); return -1; } set_close_on_exec(ctcp->listen_fd); if (setsockopt(ctcp->listen_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one)) == -1) { DEBUG(DEBUG_WARNING, ("Failed to set REUSEADDR on fd - %s\n", strerror(errno))); } if (bind(ctcp->listen_fd, (struct sockaddr * )&sock, sock_size) != 0) { DEBUG(DEBUG_ERR,(__location__ " Failed to bind() to socket. %s(%d)\n", strerror(errno), errno)); goto failed; } if (listen(ctcp->listen_fd, 10) == -1) { goto failed; } fde = tevent_add_fd(ctdb->ev, ctcp, ctcp->listen_fd, TEVENT_FD_READ, ctdb_listen_event, ctdb); tevent_fd_set_auto_close(fde); return 0; failed: if (ctcp->listen_fd != -1) { close(ctcp->listen_fd); } ctcp->listen_fd = -1; return -1; }
static void f_create_process( INT32 args ) { struct perishables storage; struct array *cmd = 0; struct mapping *optional = 0; struct svalue *tmp; int e; int stds[3]; int *fds; int num_fds = 3; int wanted_gid=0, wanted_uid=0; int gid_request=0, uid_request=0; char *tmp_cwd = NULL; pid_t pid=-2; extern char **environ; fds = stds; storage.env = NULL; storage.argv = NULL; storage.disabled = 0; storage.fds = NULL; storage.limits = NULL; check_all_args("create_process",args, BIT_ARRAY, BIT_MAPPING | BIT_VOID, 0); switch(args) { default: optional=Pike_sp[1-args].u.mapping; mapping_fix_type_field(optional); if(m_ind_types(optional) & ~BIT_STRING) Pike_error("Bad index type in argument 2 to Caudium.create_process()\n"); case 1: cmd=Pike_sp[-args].u.array; if(cmd->size < 1) Pike_error("Too few elements in argument array.\n"); for(e=0; e<cmd->size; e++) if(ITEM(cmd)[e].type!=T_STRING) Pike_error("Argument is not a string.\n"); array_fix_type_field(cmd); if(cmd->type_field & ~BIT_STRING) Pike_error("Bad argument 1 to Caudium.create_process().\n"); } if (optional) { if ((tmp = simple_mapping_string_lookup(optional, "gid"))) { switch(tmp->type) { case T_INT: wanted_gid = tmp->u.integer; gid_request = 1; break; default: Pike_error("Invalid argument for gid."); break; } } if ((tmp = simple_mapping_string_lookup(optional, "uid"))) { switch(tmp->type) { case T_INT: wanted_uid = tmp->u.integer; uid_request = 1; break; default: Pike_error("Invalid argument for uid."); break; } } if((tmp = simple_mapping_string_lookup( optional, "cwd" )) && tmp->type == T_STRING && !tmp->u.string->size_shift) tmp_cwd = tmp->u.string->str; if((tmp = simple_mapping_string_lookup( optional, "stdin" )) && tmp->type == T_OBJECT) { fds[0] = fd_from_object( tmp->u.object ); if(fds[0] == -1) Pike_error("Invalid stdin file\n"); } if((tmp = simple_mapping_string_lookup( optional, "stdout" )) && tmp->type == T_OBJECT) { fds[1] = fd_from_object( tmp->u.object ); if(fds[1] == -1) Pike_error("Invalid stdout file\n"); } if((tmp = simple_mapping_string_lookup( optional, "stderr" )) && tmp->type == T_OBJECT) { fds[2] = fd_from_object( tmp->u.object ); if(fds[2] == -1) Pike_error("Invalid stderr file\n"); } if((tmp=simple_mapping_string_lookup(optional, "rlimit"))) { struct svalue *tmp2; if(tmp->type != T_MAPPING) Pike_error("Wrong type of argument for the 'rusage' option. " "Should be mapping.\n"); #define ADD_LIMIT(X,Y,Z) internal_add_limit(&storage,X,Y,Z); #ifdef RLIMIT_NPROC if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "nproc"))) ADD_LIMIT( "nproc", RLIMIT_NPROC, tmp2 ); #endif #ifdef RLIMIT_MEMLOCK if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "memlock"))) ADD_LIMIT( "memlock", RLIMIT_MEMLOCK, tmp2 ); #endif #ifdef RLIMIT_RSS if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "rss"))) ADD_LIMIT( "rss", RLIMIT_RSS, tmp2 ); #endif #ifdef RLIMIT_CORE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "core"))) ADD_LIMIT( "core", RLIMIT_CORE, tmp2 ); #endif #ifdef RLIMIT_CPU if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "cpu"))) ADD_LIMIT( "cpu", RLIMIT_CPU, tmp2 ); #endif #ifdef RLIMIT_DATA if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "data"))) ADD_LIMIT( "data", RLIMIT_DATA, tmp2 ); #endif #ifdef RLIMIT_FSIZE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "fsize"))) ADD_LIMIT( "fsize", RLIMIT_FSIZE, tmp2 ); #endif #ifdef RLIMIT_NOFILE if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "nofile"))) ADD_LIMIT( "nofile", RLIMIT_NOFILE, tmp2 ); #endif #ifdef RLIMIT_STACK if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "stack"))) ADD_LIMIT( "stack", RLIMIT_STACK, tmp2 ); #endif #ifdef RLIMIT_VMEM if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "map_mem")) ||(tmp2=simple_mapping_string_lookup(tmp->u.mapping, "vmem"))) ADD_LIMIT( "map_mem", RLIMIT_VMEM, tmp2 ); #endif #ifdef RLIMIT_AS if((tmp2=simple_mapping_string_lookup(tmp->u.mapping, "as")) ||(tmp2=simple_mapping_string_lookup(tmp->u.mapping, "mem"))) ADD_LIMIT( "mem", RLIMIT_AS, tmp2 ); #endif #undef ADD_LIMIT } } if((tmp=simple_mapping_string_lookup(optional, "env"))) { if(tmp->type == T_MAPPING) { struct mapping *m=tmp->u.mapping; struct array *i,*v; int ptr=0; i=mapping_indices(m); v=mapping_values(m); storage.env=(char **)xalloc((1+m_sizeof(m)) * sizeof(char *)); for(e=0;e<i->size;e++) { if(ITEM(i)[e].type == T_STRING && ITEM(v)[e].type == T_STRING) { check_stack(3); ref_push_string(ITEM(i)[e].u.string); push_string(make_shared_string("=")); ref_push_string(ITEM(v)[e].u.string); f_add(3); storage.env[ptr++]=Pike_sp[-1].u.string->str; } } storage.env[ptr++]=0; free_array(i); free_array(v); } } storage.argv = (char **)xalloc((1 + cmd->size) * sizeof(char *)); for (e = 0; e < cmd->size; e++) storage.argv[e] = ITEM(cmd)[e].u.string->str; storage.argv[e] = 0; th_atfork_prepare(); pid = fork(); if (pid) { th_atfork_parent(); } else { th_atfork_child(); } if (pid == -1) { Pike_error("Caudium.create_process() failed."); } else if (pid) { pop_n_elems(args); push_int(pid); return; } else { if(storage.limits) { struct plimit *l = storage.limits; while(l) { int tmpres = setrlimit( l->resource, &l->rlp ); l = l->next; } } if(storage.env) environ = storage.env; chdir(tmp_cwd); seteuid(0); setegid(0); setgroups(0, NULL); if (gid_request) setgid(wanted_gid); if (uid_request) setuid(wanted_uid); dup2(fds[0], 0); dup2(fds[1], 1); dup2(fds[2], 2); set_close_on_exec(0,0); set_close_on_exec(1,0); set_close_on_exec(2,0); execvp(storage.argv[0],storage.argv); exit(99); } pop_n_elems(args); push_int(0); }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { unsigned int flag; int on, error = 0; umode_t mode; struct _file *_filp = tx_cache_get_file(filp); /* Patch up ioctl for bad tx cases*/ if((!_filp) || !_filp->f_dentry ){ #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Fixing up ioctl\n"); #endif return 0; } mode = d_get_inode_ro(f_get_dentry(_filp))->i_mode; switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = O_NONBLOCK; #ifdef __sparc__ /* SunOS compatibility item. */ if(O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif if (on) _filp->f_flags |= flag; else _filp->f_flags &= ~flag; break; case FIOASYNC: if ((error = get_user(on, (int __user *)arg)) != 0) break; flag = on ? FASYNC : 0; /* Did FASYNC state change ? */ if ((flag ^ _filp->f_flags) & FASYNC) { if (filp->f_op && filp->f_op->fasync) { lock_kernel(); error = filp->f_op->fasync(fd, filp, on); unlock_kernel(); } else error = -ENOTTY; } if (error != 0) break; if (on) _filp->f_flags |= FASYNC; else _filp->f_flags &= ~FASYNC; break; case FIOQSIZE: if (S_ISDIR(mode) || S_ISREG(mode) || S_ISLNK(mode)) { loff_t res = inode_get_bytes(f_get_dentry(_filp)->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; default: if(live_transaction()){ /* Short circuit this stupid ioctl */ if(cmd == TIOCGWINSZ){ #ifdef CONFIG_TX_KSTM_WARNINGS printk(KERN_ERR "Warning: some bozo wants to know the terminal width in a transaction.\n"); #endif error = -EINVAL; break; } else if(cmd != TCGETS) BUG(); } if (S_ISREG(mode)) error = file_ioctl(filp, cmd, arg); else error = do_ioctl(filp, cmd, arg); break; } return error; }
static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, struct file *filp) { long err = -EINVAL; switch (cmd) { case F_DUPFD: err = f_dupfd(arg, filp, 0); break; case F_DUPFD_CLOEXEC: err = f_dupfd(arg, filp, O_CLOEXEC); break; case F_GETFD: err = get_close_on_exec(fd) ? FD_CLOEXEC : 0; break; case F_SETFD: err = 0; set_close_on_exec(fd, arg & FD_CLOEXEC); break; case F_GETFL: err = filp->f_flags; break; case F_SETFL: err = setfl(fd, filp, arg); break; #if BITS_PER_LONG != 32 /* 32-bit arches must use fcntl64() */ case F_OFD_GETLK: #endif case F_GETLK: err = fcntl_getlk(filp, cmd, (struct flock __user *) arg); break; #if BITS_PER_LONG != 32 /* 32-bit arches must use fcntl64() */ case F_OFD_SETLK: case F_OFD_SETLKW: #endif /* Fallthrough */ case F_SETLK: case F_SETLKW: err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); break; case F_GETOWN: /* * XXX If f_owner is a process group, the * negative return value will get converted * into an error. Oops. If we keep the * current syscall conventions, the only way * to fix this will be in libc. */ err = f_getown(filp); force_successful_syscall_return(); break; case F_SETOWN: err = f_setown(filp, arg, 1); break; case F_GETOWN_EX: err = f_getown_ex(filp, arg); break; case F_SETOWN_EX: err = f_setown_ex(filp, arg); break; case F_GETOWNER_UIDS: err = f_getowner_uids(filp, arg); break; case F_GETSIG: err = filp->f_owner.signum; break; case F_SETSIG: /* arg == 0 restores default behaviour. */ if (!valid_signal(arg)) { break; } err = 0; filp->f_owner.signum = arg; break; case F_GETLEASE: err = fcntl_getlease(filp); break; case F_SETLEASE: err = fcntl_setlease(fd, filp, arg); break; case F_NOTIFY: err = fcntl_dirnotify(fd, filp, arg); break; case F_SETPIPE_SZ: case F_GETPIPE_SZ: err = pipe_fcntl(filp, cmd, arg); break; case F_ADD_SEALS: case F_GET_SEALS: err = shmem_fcntl(filp, cmd, arg); break; default: break; } return err; }
/* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. * * do_vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. * It's just a simple helper for sys_ioctl and compat_sys_ioctl. */ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { int error = 0; int __user *argp = (int __user *)arg; #ifdef CONFIG_LTT_LITE char ltt_string[LTT_LITE_MAX_LOG_STRING_SIZE]; sprintf(ltt_string, "fd=%X/cmd=%X/arg=%X/pid=%d\n", fd, cmd, (int)arg, current->pid); ltt_lite_syscall_param(LTT_EV_FILE_SYSTEM_IOCTL, ltt_string, strlen(ltt_string)); sprintf(ltt_string, "f_op=%X/pid=%d\n", (int)filp->f_op, current->pid); ltt_lite_syscall_param(LTT_EV_FILE_SYSTEM_IOCTL, ltt_string, strlen(ltt_string)); #endif switch (cmd) { case FIOCLEX: set_close_on_exec(fd, 1); break; case FIONCLEX: set_close_on_exec(fd, 0); break; case FIONBIO: /* BKL needed to avoid races tweaking f_flags */ lock_kernel(); error = ioctl_fionbio(filp, argp); unlock_kernel(); break; case FIOASYNC: /* BKL needed to avoid races tweaking f_flags */ lock_kernel(); error = ioctl_fioasync(fd, filp, argp); unlock_kernel(); break; case FIOQSIZE: if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || S_ISREG(filp->f_path.dentry->d_inode->i_mode) || S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; } else error = -ENOTTY; break; case FIFREEZE: error = ioctl_fsfreeze(filp); break; case FITHAW: error = ioctl_fsthaw(filp); break; default: if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) error = file_ioctl(filp, cmd, arg); else error = vfs_ioctl(filp, cmd, arg); break; } return error; }