📄 wdbtsfsdrv.c
字号:
case SO_SETRCVBUF: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_SO_SETRCVBUF; break; case SO_SETDONTROUTE: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_SO_SETDONTROUTE; break; case SO_GETDONTROUTE: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_SO_GETDONTROUTE; break; case SO_SETOOBINLINE: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_SO_SETOOBINLINE; break; case SO_GETOOBINLINE: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_SO_GETOOBINLINE; break; case FIOREADDIR: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_FIOREADDIR; /* * For FIOREADDIR we want to provide the address of the * struct dirent * and the dd_cookie. */ pChannel->result.extra1 = pDir->dd_cookie; pChannel->result.extra2 = (TGT_INT_T) &pDir->dd_dirent; break; case FIORENAME: pChannel->info.extra.ioctl.request = WDB_TSFS_IOCTL_FIORENAME; /* * If the new name starts with the device name, strip the * device name first. If it doesn't just continue. */ if ((pShortPath = strstr ((char *) arg, tsfsDev.devHdr.name)) != NULL) { /* * If the device name is in the path, but not the first * element of the path, use the whole path. Otherwise * remove the device name. For example, /tgtsvr/foo/goo * should yield /foo/goo, but /foo/tgtsvr/goo should * remain /foo/tgtsvr/goo (/tgtsvr is the dev name). */ if (pShortPath != (char *) arg) pShortPath = (char *) arg; else pShortPath = (char *) arg + strlen (tsfsDev.devHdr.name); } else { pShortPath = (char *) arg; } /* * We put the length of the new name in extra1, and the address * of the new name in extra2. */ pChannel->result.extra1 = strlen (pShortPath); pChannel->result.extra2 = (TGT_INT_T) pShortPath; break; case FIOMKDIR: /* * We handle this by using our own tsfsOpen to do the creation. * The device name must prefix the path or we generate an error. * Start by stripping off the device name. */ if ((pShortPath = strstr ((char *) arg, tsfsDev.devHdr.name)) == NULL) { errno = tsfsErrnoMap (WDB_ERR_INVALID_PARAMS); semGive (&pChannel->tsfsSem); return (ERROR); } /* The device must be the first thing in the path. */ if (pShortPath != (char *) arg) { errno = tsfsErrnoMap (WDB_ERR_INVALID_PARAMS); semGive (&pChannel->tsfsSem); return (ERROR); } pShortPath = (char *) arg + strlen (tsfsDev.devHdr.name); /* * Now we have the proper path, use our own tsfsOpen to create * the directory. The tsfsDev arg to tsfsOpen isn't used by * tsfsOpen. */ if ((pNewChannel = tsfsOpen (& tsfsDev, pShortPath, O_CREAT | O_RDONLY, FSTAT_DIR | wdbTsfsDefaultDirPerm)) == ERROR) { semGive (&pChannel->tsfsSem); return ERROR; } /* Close the new channel and return. */ if (tsfsClose ((TSFS_CHANNEL_DESC *) pNewChannel) != OK) { semGive (&pChannel->tsfsSem); return ERROR; } semGive (&pChannel->tsfsSem); return (OK); case FIORMDIR: { struct stat statBuf; statBuf.st_mode = 0; /* * We handle this using our own tsfsDelete to remove the * directory. The device name must prefix the path or we * generate an error. Start by stripping off the device name. */ if ((pShortPath = strstr ((char *) arg, tsfsDev.devHdr.name)) == NULL) { errno = tsfsErrnoMap (WDB_ERR_INVALID_PARAMS); semGive (&pChannel->tsfsSem); return (ERROR); } /* The device must be the first thing in the path. */ if (pShortPath != (char *) arg) { errno = tsfsErrnoMap (WDB_ERR_INVALID_PARAMS); semGive (&pChannel->tsfsSem); return (ERROR); } pShortPath = (char *) arg + strlen (tsfsDev.devHdr.name); /* * Now we have the proper path, but we have to ensure the file * is a directory before we can remove it. Use our own tsfsIoctl * with FIOSTATGET to find out if it is. We open the path, test * if it points to a directory, then close it. Then we delete it. */ pNewChannel = tsfsOpen (& tsfsDev, pShortPath, O_RDONLY, wdbTsfsDefaultDirPerm); tsfsIoctl ((TSFS_CHANNEL_DESC *) pNewChannel, FIOFSTATGET, (int) &statBuf); tsfsClose ((TSFS_CHANNEL_DESC *) pNewChannel); if (! (statBuf.st_mode & S_IFDIR)) { errno = tsfsErrnoMap (ENOTDIR); semGive (&pChannel->tsfsSem); return (ERROR); } /* * We are sure the file is a directory, so we use tsfsDelete to * remove the directory. The tsfsDev arg to tsfsDelete isn't * used by tsfsDelete. Try to return the most useful errno * by making sure errno records only the errors in tsfsDelete. */ errno = 0; if (tsfsDelete (& tsfsDev, pShortPath) != OK) { semGive (&pChannel->tsfsSem); return (ERROR); } semGive (&pChannel->tsfsSem); return (OK); } case FIOGETFL: /* this one is handled locally. */ *((int *) arg) = pChannel->openmode; semGive (&pChannel->tsfsSem); return (OK); /* don't pass unknown ioctl's up to target server. */ default: errno = tsfsErrnoMap (WDB_ERR_INVALID_PARAMS); semGive (&pChannel->tsfsSem); return ERROR; } /* prepare the event for transmission */ pChannel->info.info.channel = pChannel->channel; pChannel->info.info.opcode = WDB_TSFS_IOCTL; pChannel->info.info.semId = (TGT_ADDR_T) &pChannel->waitSem; pChannel->info.info.pResult = (TGT_ADDR_T) &pChannel->result.value; pChannel->info.info.pErrno = (TGT_ADDR_T) &pChannel->result.errNo; pChannel->info.info.semGiveAddr = (TGT_ADDR_T) &semGive; pChannel->info.extra.ioctl.arg = arg; pChannel->info.extra.ioctl.pExtra1 = (TGT_ADDR_T) &pChannel->result.extra1; pChannel->info.extra.ioctl.pExtra2 = (TGT_ADDR_T) &pChannel->result.extra2; /* Post the event. */ wdbEventPost (&pChannel->evtNode); /* Wait for the tgtsvr to get back to us with the result. */ semTake (&pChannel->waitSem, WAIT_FOREVER); if (pChannel->result.errNo != OK) errno = tsfsErrnoMap (pChannel->result.errNo); /* * Some ioctl() requests require us to fill in data pointed to by arg. * If so we take care of that here. */ switch (request) { case FIOFSTATGET: { struct stat * pStat = (struct stat *) arg; memset (pStat, 0, sizeof (struct stat)); pStat->st_dev = (int) &tsfsDev; pStat->st_size = pChannel->result.extra1; if (pChannel->result.extra2 & WDB_TSFS_S_IFREG) pStat->st_mode |= S_IFREG; if (pChannel->result.extra2 & WDB_TSFS_S_IFDIR) pStat->st_mode |= S_IFDIR; break; } case FIONREAD: { * ((int *) arg) = pChannel->result.extra1; break; } case FIOREADDIR: { pDir->dd_cookie = pChannel->result.extra1; break; } case SO_GETDEBUG: case SO_GETDONTROUTE: case SO_GETOOBINLINE: { * ((int *) arg) = pChannel->result.extra1; break; } } result = pChannel->result.value; semGive (&pChannel->tsfsSem); return result; }/******************************************************************************** tsfsErrnoMap - map errnos returned from host to vxWorks' errnos** This routine maps from the portable errno values defined in wdb.h for* the TSFS, to errnos defined on the target. All POSIX errnos are passed* through this mapping without change. WDB-specific errnos that have been* returned from the host are also not mapped.** INTERNAL* Errnos that are not defined as portable. This includes POSIX errnos, but* is may include more if some get through the cracks.** RETURNS: vxWorks' errno, or zero (0) if passed zero (0) * * NOMANUAL*/static int tsfsErrnoMap ( int hostErrno /* non-vxWorks errno returned from host */ ) { int wverr; /* * By default pass on the error because it may be a POSIX errno. It may * also be zero, so it shouldn't get modified. Unknown errnos will pass * right through. There should be no default case in the switch below. */ wverr = hostErrno; switch (hostErrno) { case WDB_TSFS_ERRNO_ENOTEMPTY: wverr = ENOTEMPTY; break; case WDB_TSFS_ERRNO_EDEADLK: wverr = EDEADLK; break; case WDB_TSFS_ERRNO_ENOLCK: wverr = ENOLCK; break; case WDB_TSFS_ERRNO_EMSGSIZE: wverr = EMSGSIZE; break; case WDB_TSFS_ERRNO_EOPNOTSUPP: wverr = EOPNOTSUPP; break; case WDB_TSFS_ERRNO_EADDRNOTAVAIL: wverr = EADDRNOTAVAIL; break; case WDB_TSFS_ERRNO_ENOTSOCK: wverr = ENOTSOCK; break; case WDB_TSFS_ERRNO_ENETRESET: wverr = ENETRESET; break; case WDB_TSFS_ERRNO_ECONNABORTED: wverr = ECONNABORTED; break; case WDB_TSFS_ERRNO_ECONNRESET: wverr = ECONNRESET; break; case WDB_TSFS_ERRNO_ECONNREFUSED: wverr = ECONNREFUSED; break; case WDB_TSFS_ERRNO_ENOBUFS: wverr = ENOBUFS; break; case WDB_TSFS_ERRNO_ENOTCONN: wverr = ENOTCONN; break; case WDB_TSFS_ERRNO_ESHUTDOWN: wverr = ESHUTDOWN; break; case WDB_TSFS_ERRNO_ETIMEDOUT: wverr = ETIMEDOUT; break; case WDB_TSFS_ERRNO_EINPROGRESS: wverr = EINPROGRESS; break; case WDB_TSFS_ERRNO_EWOULDBLOCK: wverr = EWOULDBLOCK; break; case WDB_TSFS_ERRNO_ENOSR: wverr = ENOSR; break; case WDB_TSFS_ERRNO_ELOOP: wverr = ELOOP; break; case WDB_TSFS_ERRNO_ENAMETOOLONG: wverr = ENAMETOOLONG; break; case WDB_TSFS_ERRNO_EBADMSG: wverr = EBADMSG; break; } return (wverr); }/******************************************************************************** tsfsEventGet - fill in WDB event parameters at transmission time* * RETURNS: N/A* NOMANUAL*/static void tsfsEventGet ( void * arg, WDB_EVT_DATA * pEvtData ) { TSFS_CHANNEL_DESC * pChannel = (TSFS_CHANNEL_DESC *) arg; int size; size = sizeof (WDB_TSFS_GENERIC_INFO); switch (pChannel->info.info.opcode) { case WDB_TSFS_OPEN: size += sizeof (WDB_TSFS_OPEN_INFO); break; case WDB_TSFS_DELETE: size += sizeof (WDB_TSFS_DELETE_INFO); break; case WDB_TSFS_WRITE: case WDB_TSFS_READ: size += sizeof (WDB_TSFS_RW_INFO); break; case WDB_TSFS_IOCTL: size += sizeof (WDB_TSFS_IOCTL_INFO); break; case WDB_TSFS_CLOSE: default: break; }; memcpy (&pEvtData->eventInfo, &pChannel->info, size); pEvtData->evtType = WDB_EVT_TSFS_OP; pEvtData->eventInfo.evtInfo.numInts = size / sizeof (TGT_INT_T) - 1; }/******************************************************************************** tsfsEventDeq - free allocated event data after transmission** NOMANUAL*/static void tsfsEventDeq ( void * arg ) { /* The tsfs event has no allocated data or other need for cleanup. */ return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -