static void citp_pipe_dtor(citp_fdinfo* fdinfo, int fdt_locked) { citp_pipe_fdi* epi = fdi_to_pipe_fdi(fdinfo); LOG_PIPE("%s: fdinfo=%p epi=%p", __FUNCTION__, fdinfo, epi); citp_netif_release_ref(epi->ni, fdt_locked); LOG_PIPE("%s: done", __FUNCTION__); }
asmlinkage long our_sys_pipe2(int pipefd[2], int flags) { long result; long audit, pid, paudit; struct passwd_entry *pe = NULL; struct task_struct *ts = NULL; result = original_sys_pipe2_call(pipefd, flags); if(result < 0) return result; pid = current->pid; audit = get_audit_id(); pe = get_passwd_entry(current_uid()); ts = find_task_by_vpid(audit); if(ts != NULL && ts->real_parent != NULL) { paudit = ts->real_parent->pid; } else { paudit = -1; } LOG_PIPE(SYSCALL_PIPE2, pe->username, pid, audit, paudit, pipefd[0], pipefd[1], flags); return result; }
static int citp_pipe_ioctl(citp_fdinfo *fdinfo, int cmd, void *arg) { int rc = 0; citp_pipe_fdi* epi = fdi_to_pipe_fdi(fdinfo); struct oo_pipe* p = epi->pipe; switch( cmd ) { case FIONBIO: { int b = *(int* )arg; ci_uint32 bit = CI_PFD_AFLAG_NONBLOCK << (fdi_is_reader(fdinfo) ? CI_PFD_AFLAG_READER_SHIFT : CI_PFD_AFLAG_WRITER_SHIFT); LOG_PIPE("%s: set non-blocking mode '%s'", __FUNCTION__, b ? "ON" : "OFF"); if( b ) ci_bit_mask_set(&p->aflags, bit); else ci_bit_mask_clear(&p->aflags, bit); break; } case FIONREAD: { /* NOTE: a normal user would expect that FIONREAD returns zero or * even an error when called on 'write' end of the pipe. But Linux * thinks it's reasonable to return 'correct' amount of data in the pipe * regardless of the actul fd. */ int *r = (int* )arg; /* we don't need any lock here as actual 'read' of the variable is atomic */ *r = p->bytes_added - p->bytes_removed; break; } default: errno = ENOSYS; rc = -1; break; } /* fixme kostik : support of ioctl should be added */ return rc; }
/* we don't register protocol impl */ int citp_pipe_create(int fds[2], int flags) { citp_pipe_fdi* epi_read; citp_pipe_fdi* epi_write; struct oo_pipe* p = NULL; /* make compiler happy */ ci_netif* ni; int rc = -1; ef_driver_handle fd = -1; Log_V(log(LPF "pipe()")); /* citp_netif_exists() does not need citp_ul_lock here */ if( CITP_OPTS.ul_pipe == CI_UNIX_PIPE_ACCELERATE_IF_NETIF && ! citp_netif_exists() ) { return CITP_NOT_HANDLED; } rc = citp_netif_alloc_and_init(&fd, &ni); if( rc != 0 ) { if( rc == CI_SOCKET_HANDOVER ) { /* This implies EF_DONT_ACCELERATE is set, so we handover * regardless of CITP_OPTS.no_fail */ return CITP_NOT_HANDLED; } /* may be lib mismatch - errno will be ELIBACC */ goto fail1; } rc = -1; CI_MAGIC_CHECK(ni, NETIF_MAGIC); /* add another reference as we have 2 fdis */ citp_netif_add_ref(ni); epi_read = citp_pipe_epi_alloc(ni, O_RDONLY); if( epi_read == NULL ) goto fail2; epi_write = citp_pipe_epi_alloc(ni, O_WRONLY); if( epi_write == NULL ) goto fail3; /* oo_pipe init code */ if( fdtable_strict() ) CITP_FDTABLE_LOCK(); rc = oo_pipe_ctor(ni, &p, fds, flags); if( rc < 0 ) goto fail4; citp_fdtable_new_fd_set(fds[0], fdip_busy, fdtable_strict()); citp_fdtable_new_fd_set(fds[1], fdip_busy, fdtable_strict()); if( fdtable_strict() ) CITP_FDTABLE_UNLOCK(); LOG_PIPE("%s: pipe=%p id=%d", __FUNCTION__, p, p->b.bufid); /* as pipe is created it should be attached to the end-points */ epi_read->pipe = p; epi_write->pipe = p; /* We're ready. Unleash us onto the world! */ ci_assert(epi_read->pipe->b.sb_aflags & CI_SB_AFLAG_NOT_READY); ci_assert(epi_write->pipe->b.sb_aflags & CI_SB_AFLAG_NOT_READY); ci_atomic32_and(&epi_read->pipe->b.sb_aflags, ~CI_SB_AFLAG_NOT_READY); ci_atomic32_and(&epi_read->pipe->b.sb_aflags, ~CI_SB_AFLAG_NOT_READY); citp_fdtable_insert(&epi_read->fdinfo, fds[0], 0); citp_fdtable_insert(&epi_write->fdinfo, fds[1], 0); CI_MAGIC_CHECK(ni, NETIF_MAGIC); return 0; fail4: if( fdtable_strict() ) CITP_FDTABLE_UNLOCK(); fail3: CI_FREE_OBJ(epi_write); fail2: CI_FREE_OBJ(epi_read); citp_netif_release_ref(ni, 0); citp_netif_release_ref(ni, 0); fail1: if( CITP_OPTS.no_fail && errno != ELIBACC ) { Log_U(ci_log("%s: failed (errno:%d) - PASSING TO OS", __FUNCTION__, errno)); return CITP_NOT_HANDLED; } return rc; }