/* * Given a process id, iterate through all open files of that process * looking for a match to the target file, and then determine how it * is being used by that process. This is quite different in QNX to * UNIX, as chroot and chdir do not hold open a reference to the file. * The iteration process attempts to dup each file descriptor into * this process, so it can then be queried; attempt to skip things which * aren't files (heuristic guess) and use a timeout as self-defence. */ int howused(pid_t pid, match_t *match) { struct _server_info sinfo; struct _fdinfo finfo; struct stat st; io_dup_t msg; uint64_t to; int fd, coid, usage; usage = 0; for (fd = 0; (fd = ConnectServerInfo(pid, fd, &sinfo)) != -1; ++fd) { if ((pid != sinfo.pid || !(fd & _NTO_SIDE_CHANNEL)) && (coid = ConnectAttach(sinfo.nd, sinfo.pid, sinfo.chid, 0, _NTO_COF_CLOEXEC)) != -1) { msg.i.type = _IO_DUP; msg.i.combine_len = sizeof(msg.i); msg.i.info.nd = netmgr_remote_nd(sinfo.nd, ND_LOCAL_NODE); msg.i.info.pid = pid; msg.i.info.chid = sinfo.chid; msg.i.info.scoid = sinfo.scoid; msg.i.info.coid = fd; TimerTimeout(CLOCK_MONOTONIC, _NTO_TIMEOUT_SEND | _NTO_TIMEOUT_REPLY, NULL, (to = 1000000000LL, &to), NULL); if (MsgSend(coid, &msg.i, sizeof(msg.i), NULL, 0) == -1) { ConnectDetach(coid); } else { if (fstat(coid, &st) != -1 && ismatch(match, st.st_dev, st.st_ino)) { if (iofdinfo(coid, 0, &finfo, NULL, 0) == -1 || sinfo.pid != PATHMGR_PID || finfo.mode != 0) usage |= USED_OPEN; } close(coid); } } } return(usage); }
int connectslaves(slave_t *pslave) { for(int i=0; i<pslave->amount; ++i) { if((pslave->pslave[i].coid != ConnectServerInfo(0, pslave->pslave[i].coid, NULL)) || (pslave->pslave[i].status == DOWN)) { pslave->pslave[i].coid = name_open(pslave->pslave[i].name, NAME_FLAG_ATTACH_GLOBAL); pslave->pslave[i].clientnow = 0; if(pslave->pslave[i].coid == -1) { perror(pslave->pslave[i].name); pslave->pslave[i].status = DOWN; } else { pslave->pslave[i].status = READY; } } } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int server_coid, a_coid; short msg; int a_chid; struct _asyncmsg_connection_attr aca; struct _server_info sinfo; int count = 1; /* look for server */ server_coid = name_open( RECV_NAME, 0 ); while( server_coid == -1 ) { sleep(1); server_coid = name_open( RECV_NAME, 0 ); } /* need server's pid, use this to get server info including pid */ ConnectServerInfo( 0, server_coid, &sinfo ); /* send message to server request the asynchronous channel id */ msg = GET_ACHID; if (MsgSend( server_coid, &msg, sizeof( msg ), &a_chid, sizeof(a_chid) )) { perror(PROGNAME "MsgSend"); exit( EXIT_FAILURE ); } /* setup array of send buffers */ memset(&aca, 0, sizeof(aca)); aca.buffer_size = 2048; aca.max_num_buffer = 5; /* don't locally accumulate more than 5 buffers */ aca.trigger_num_msg = 1; /* deliver each message as it is sent */ aca.call_back = callback; /* call this function after messages are sent */ /* create my asynchronous connection to the server */ a_coid = asyncmsg_connect_attach( 0, sinfo.pid, a_chid, 0, 0, &aca ); if( -1 == a_coid ) { perror( "async connect"); printf("server pid is %d\n", sinfo.pid ); exit( EXIT_FAILURE ); } while(1) { int ret, len; char buf[80]; len = sprintf(buf, "message #%d", count)+1; printf("sending %dth time\n", count ); /* deliver message to server, the count value will be passed into * my callback as the "handle" */ ret = asyncmsg_put( a_coid, buf, len, count, NULL ); if( -1 == ret ) { perror( "put"); exit( EXIT_FAILURE ); } count++; sleep(1); } }
int aio_cancel(int fd, struct aiocb *aiocbp) { unsigned flag, ret; int ncancled, ndone, nprogress; struct aiocb *ap, **app; struct _aio_prio_list *plist, **pplist; struct _server_info sinfo; if (!_aio_cb && _aio_init(NULL)) { return -1; } _mutex_lock(&_aio_cb->cb_mutex); /* a single aiocbp */ if (aiocbp) { flag = atomic_clr_value(&aiocbp->_aio_flag, _AIO_FLAG_QMASK); if (flag & _AIO_FLAG_DONE) { ret = AIO_ALLDONE; } else if (flag & _AIO_FLAG_IN_PROGRESS) { ret = AIO_NOTCANCELED; } else if (flag & _AIO_FLAG_ENQUEUE) { if ((plist = (struct _aio_prio_list *)aiocbp->_aio_plist) == NULL) { errno = EINVAL; return -1; } /* find the aiocbp */ for (app = &plist->head, ap = *app; ap; app = &ap->_aio_next, ap = ap->_aio_next) { if (ap == aiocbp && (*app = ap->_aio_next) == NULL) { plist->tail = app; /* Even if there is no request hang on this priority list, * we will not remove it now. remove a priority list entry * causing a single list search, and we have reason to * believe the entry will be reused soon. * The empty entry will be removed later on, by the * _aio_block() internal function, when it try to get a * request. */ #if 0 if (plist->head == NULL) { for (pplist = &_aio_cb->cb_plist; *pplist; pplist = &((*pplist)->next)) { if (*pplist == plist) { *pplist = plist->next; plist->next = _aio_cb->cb_plist_free; _aio_cb->cb_plist_free = plist; break; } } } #endif } break; } if (flag & _AIO_FLAG_SUSPEND) { struct _aio_waiter *w = aiocbp->_aio_suspend; aiocbp->_aio_suspend = NULL; if (w && atomic_sub_value(&w->w_count, 1) == 0) { pthread_cond_signal(&w->w_cond); } } aiocbp->_aio_flag = 0; aiocbp->_aio_error = ECANCELED; aiocbp->_aio_result = (unsigned)-1; ret = AIO_CANCELED; } else { /* we haven't seen this yet */ errno = EINVAL; ret = (unsigned)-1; } _mutex_unlock(&_aio_cb->cb_mutex); return ret; } /* got to scan the whole list for fd */ ncancled = ndone = nprogress = 0; for (pplist = &_aio_cb->cb_plist, plist = *pplist; plist; pplist = &plist->next, plist = *pplist) { for (app = &plist->head, ap = *app; ap; ap = *app) { if (ap->aio_fildes == fd) { flag = atomic_clr_value(&ap->_aio_flag, _AIO_FLAG_QMASK); if (flag & _AIO_FLAG_DONE) { ndone++; } else if (flag & _AIO_FLAG_IN_PROGRESS) { nprogress++; } else if (flag & _AIO_FLAG_ENQUEUE) { if ((*app = ap->_aio_next) == NULL) { plist->tail = app; /* Don't remove empty entry (see above), leave it * for _aio_block(). */ #if 0 if (plist->head == NULL) { for (pplist = &_aio_cb->cb_plist; *pplist; pplist = &((*pplist)->next)) { if (*pplist == plist) { *pplist = plist->next; plist->next = _aio_cb->cb_plist_free; _aio_cb->cb_plist_free = plist; } } } #endif } ap->_aio_flag = 0; ap->_aio_error = ECANCELED; ap->_aio_result = (unsigned)-1; ncancled++; } } else { app = &ap->_aio_next; } } } _mutex_unlock(&_aio_cb->cb_mutex); if (nprogress) return AIO_NOTCANCELED; if (!ncancled) { if (ndone) { /* all affected operations have completed */ return AIO_ALLDONE; } else { /* no operations matched the supplied fd, POSIX required to check * if this is a valid fd. PR#51564 */ if (ConnectServerInfo(0, fd, &sinfo) != fd) { errno = EBADF; return (unsigned)-1; } else { return AIO_ALLDONE; } } } return AIO_CANCELED; }
int _vfcntl(int fd, int cmd, va_list ap) { union { io_dup_t dup; io_space_t space; io_lock_t lock; } msg; iov_t iov[4]; int arg; pid_t pid; switch(cmd) { case F_DUPFD: { struct _server_info info; int fd2; if(fd == -1 || (fd & _NTO_SIDE_CHANNEL) || ConnectServerInfo(0, fd, &info) != fd) { errno = EBADF; return -1; } if((fd2 = va_arg(ap, int)) < 0 || (fd2 & _NTO_SIDE_CHANNEL)) { errno = EINVAL; return -1; } if((fd2 = ConnectAttach(info.nd, info.pid, info.chid, fd2, _NTO_COF_CLOEXEC)) == -1) { return -1; } msg.dup.i.type = _IO_DUP; msg.dup.i.combine_len = sizeof msg.dup; msg.dup.i.info.nd = netmgr_remote_nd(info.nd, ND_LOCAL_NODE); msg.dup.i.info.pid = getpid(); msg.dup.i.info.chid = info.chid; msg.dup.i.info.scoid = info.scoid; msg.dup.i.info.coid = fd; if(MsgSendnc(fd2, &msg.dup.i, sizeof msg.dup.i, 0, 0) == -1) { ConnectDetach_r(fd2); return -1; } ConnectFlags_r(0, fd2, FD_CLOEXEC, 0); return fd2; } case F_GETFD: return ConnectFlags(0, fd, 0, 0); case F_SETFD: return ConnectFlags(0, fd, ~0, va_arg(ap, int)); case F_GETFL: if(_devctl(fd, DCMD_ALL_GETFLAGS, &arg, sizeof arg, 0) == -1) { return -1; } return arg; case F_SETFL: arg = va_arg(ap, int); return _devctl(fd, DCMD_ALL_SETFLAGS, &arg, sizeof arg, _DEVCTL_FLAG_NORETVAL); case F_GETOWN: if(_devctl(fd, DCMD_ALL_GETOWN, &pid, sizeof pid, 0) == -1) { return -1; } return pid; case F_SETOWN: pid = va_arg(ap, pid_t); return _devctl(fd, DCMD_ALL_SETOWN, &pid, sizeof pid, _DEVCTL_FLAG_NORETVAL); case F_ALLOCSP64: case F_FREESP64: { flock64_t *area = va_arg(ap, flock64_t *); msg.space.i.start = area->l_start; msg.space.i.len = area->l_len; msg.space.i.whence = area->l_whence; goto common; } case F_ALLOCSP: cmd = F_ALLOCSP64; /* Always pass the 64 bit values */ goto stuff; case F_FREESP: cmd = F_FREESP64; /* Always pass the 64 bit values */ stuff: { flock_t *area = va_arg(ap, flock_t *); msg.space.i.start = area->l_start; msg.space.i.len = area->l_len; msg.space.i.whence = area->l_whence; } common: msg.space.i.type = _IO_SPACE; msg.space.i.combine_len = sizeof msg.space.i; msg.space.i.subtype = cmd; return MsgSend(fd, &msg.space.i, sizeof msg.space.i, 0, 0); case F_GETLK: case F_SETLK: case F_SETLKW: case F_GETLK64: case F_SETLK64: case F_SETLKW64: msg.lock.i.type = _IO_LOCK; msg.lock.i.combine_len = sizeof msg.lock.i; msg.lock.i.subtype = cmd; SETIOV(iov + 0, &msg.lock.i, sizeof msg.lock.i); SETIOV(iov + 1, va_arg(ap, flock_t *), sizeof(flock_t)); iov[3] = iov[1]; SETIOV(iov + 2, &msg.lock.o, sizeof msg.lock.o); return MsgSendv(fd, iov + 0, 2, iov + 2, (cmd == F_GETLK || cmd == F_GETLK64) ? 2 : 1); default: break; } errno = EINVAL; return -1; }