📄 memdrv.c
字号:
#include "copyright_wrs.h"#include "vxWorks.h"#include "ioLib.h"#include "iosLib.h"#include "stat.h"#include "dirent.h"#include "memLib.h"#include "errnoLib.h"#include "string.h"#include "stdlib.h"#include "stdio.h"#include "memDrv.h"typedef struct /* MEM_DEV - memory device descriptor */ { DEV_HDR devHdr; MEM_DRV_DIRENTRY dir; /* Contents of this memDrv device */ int allowOffset; /* Allow files to be opened with an offset. */ } MEM_DEV;typedef struct /* MEM_FILE_DESC - memory file descriptor */ { MEM_DEV *pDevice; /* The memory device of this file */ MEM_DRV_DIRENTRY *pDir;/* Directory entry for this file */ int offset; /* current position */ int mode; /* O_RDONLY, O_WRONLY, O_RDWR */ } MEM_FILE_DESC;LOCAL int memDrvNum; /* driver number of memory driver *//* forward declarations */LOCAL MEM_DRV_DIRENTRY *memFindFile ();LOCAL MEM_FILE_DESC *memOpen ();LOCAL STATUS memFileStatGet ();LOCAL int memRead ();LOCAL int memWrite ();LOCAL int memClose ();LOCAL STATUS memIoctl ();/********************************************************************************* memDrv - install a memory driver** This routine initializes the memory driver. It must be called first,* before any other routine in the driver.** RETURNS: OK, or ERROR if the I/O system cannot install the driver.*/STATUS memDrv (void) { if (memDrvNum > 0) return (OK); /* driver already installed */ memDrvNum = iosDrvInstall ((FUNCPTR) memOpen, (FUNCPTR) NULL, (FUNCPTR) memOpen, memClose, memRead, memWrite, memIoctl); return (memDrvNum == ERROR ? ERROR : OK); }STATUS memDevCreate ( char * name, /* device name */ char * base, /* where to start in memory */ int length /* number of bytes */ ) { STATUS status; FAST MEM_DEV *pMemDv; if (memDrvNum < 1) { errnoSet (S_ioLib_NO_DRIVER); return (ERROR); } if ((pMemDv = (MEM_DEV *) calloc (1, sizeof (MEM_DEV))) == NULL) return (ERROR); pMemDv->dir.name = ""; pMemDv->dir.base = base; pMemDv->dir.pDir = NULL; pMemDv->dir.length = length; pMemDv->allowOffset = 1; /* * XXX * Specify byte,word,long accesses. * Semaphore read/write? */ status = iosDevAdd ((DEV_HDR *) pMemDv, name, memDrvNum); if (status == ERROR) free ((char *) pMemDv); return (status); }/********************************************************************************* memDevCreateDir - create a memory device for multiple files** This routine creates a memory device for a collection of files* organised into directories. The given array of directory entry* records describes a number of files, some of which may be directories,* represented by their own directory entry arrays. The structure may* be arbitrarily deep. This effectively allows a filesystem to* be created and installed in VxWorks, for essentially read-only use.* The filesystem structure can be created on the host using the* memdrvbuild utility.** Note that the array supplied is not copied; a reference to it is* kept. This array should not be modified after being passed to* memDevCreateDir.** RETURNS: OK, or ERROR if memory is insufficient or the I/O system cannot* add the device.** ERRNO: S_ioLib_NO_DRIVER**/STATUS memDevCreateDir ( char * name, /* device name */ MEM_DRV_DIRENTRY * files, /* array of dir. entries - not copied */ int numFiles /* number of entries */ ) { STATUS status; FAST MEM_DEV *pMemDv; if (memDrvNum < 1) { errnoSet (S_ioLib_NO_DRIVER); return (ERROR); } if ((pMemDv = (MEM_DEV *) calloc (1, sizeof (MEM_DEV))) == NULL) return (ERROR); pMemDv->dir.name = ""; pMemDv->dir.base = NULL; pMemDv->dir.pDir = files; pMemDv->dir.length = numFiles; /* * Let's not allow the "offset" notation for opening files, at * least for now, when we have "real" subdirectories. */ pMemDv->allowOffset = 0; /* * XXX * Specify byte,word,long accesses. * Semaphore read/write? */ status = iosDevAdd ((DEV_HDR *) pMemDv, name, memDrvNum); if (status == ERROR) free ((char *) pMemDv); return (status); }/********************************************************************************* memDevDelete - delete a memory device** This routine deletes a memory device containing a single file or a* collection of files. The device is deleted with it own name.** For example, to delete the device created by memDevCreate ("/mem/cpu0/", 0,* sysMemTop()), the proper call would be:* .CS* memDevDelete ("/mem/cpu0/");* .CE* * RETURNS: OK, or ERROR if the device doesn't exist.*/STATUS memDevDelete ( char * name /* device name */ ) { DEV_HDR * pDevHdr; /* get the device pointer corresponding to the device name */ if ((pDevHdr = iosDevFind (name, NULL)) == NULL) return (ERROR); /* delete the device from the I/O system */ iosDevDelete (pDevHdr); /* free the device pointer */ free ((MEM_DEV *) pDevHdr); return (OK); }/********************************************************************************* memFindFile - find a memory file by name** RETURNS: The file descriptor number, or ERROR if the name is not a* valid number.*/LOCAL MEM_DRV_DIRENTRY *memFindFile ( MEM_DEV *pMemDv, /* Device we are looking in. */ char *name, /* name of file to find */ MEM_DRV_DIRENTRY *pDir, /* pointer to memory device descriptor */ int *pOffset /* returned file pOffset */ ) { MEM_DRV_DIRENTRY *pFile = NULL; *pOffset = 0; /* Protect against NULL. */ if (name == NULL) name = ""; while (*name == '/') ++name; if (strcmp (pDir->name, name) == 0) { pFile = pDir; } else if (strncmp (pDir->name, name, strlen (pDir->name)) == 0) { int index; name += strlen (pDir->name); if (pDir->pDir != NULL) { /* Search for the referenced file in this directory. */ for (index = 0; index < pDir->length; ++index) { pFile = memFindFile (pMemDv, name, &pDir->pDir[index], pOffset); if (pFile != NULL) break; } } else if (pMemDv->allowOffset) { int off = 0; while (*name == '/') ++name; if (sscanf (name, "%d", &off) == 1) { pFile = pDir; *pOffset = off; } } } return pFile; }/********************************************************************************* memOpen - open a memory file** RETURNS: The file descriptor number, or ERROR if the name is not a* valid number.** ERRNO: EINVAL**/LOCAL MEM_FILE_DESC *memOpen ( MEM_DEV *pMemDv, /* pointer to memory device descriptor */ char *name, /* name of file to open (a number) */ int mode /* access mode (O_RDONLY,O_WRONLY,O_RDWR) */ ) { MEM_DRV_DIRENTRY *pFile = NULL; MEM_FILE_DESC *pMemFd = NULL; int offset = 0; int isDir = 0; pFile = memFindFile (pMemDv, name, &pMemDv->dir, &offset); if (pFile != NULL) { /* Directories open for read only. */ isDir = (pFile->pDir != NULL); if (!isDir || mode == O_RDONLY) { /* Get a free file descriptor */ pMemFd = (MEM_FILE_DESC *) calloc (1, sizeof (MEM_FILE_DESC)); if (pMemFd != NULL) { pMemFd->pDevice = pMemDv; pMemFd->pDir = pFile; pMemFd->offset = offset; pMemFd->mode = mode; } } } if (pMemFd != NULL) return pMemFd; else { errnoSet (EINVAL); return (MEM_FILE_DESC *) ERROR; } }/********************************************************************************* memFileStatGet - get file status (directory entry data)** This routine is called via an ioctl() call, using the FIOFSTATGET* function code. The passed stat structure is filled, using data* obtained from the directory entry which describes the file.** RETURNS: ERROR or OK** ERRNO: EINVAL**/LOCAL STATUS memFileStatGet ( MEM_FILE_DESC * pfd, /* pointer to file descriptor */ struct stat * pStat /* structure to fill with data */ ) { MEM_DEV *pMemDv = pfd->pDevice; /* pointer to device */ MEM_DRV_DIRENTRY *pDir = pfd->pDir; /* pointer to file info */ int isDir = 0; if (pStat == NULL || pDir == NULL) { errnoSet (EINVAL); return ERROR; } bzero ((char *) pStat, sizeof (struct stat)); /* zero out stat struct */ isDir = (pDir->pDir != NULL); /* Fill stat structure */ pStat->st_dev = (ULONG) pMemDv; /* device ID = DEV_HDR addr */ pStat->st_ino = 0; /* no file serial number */ pStat->st_nlink = 1; /* always only one link */ pStat->st_uid = 0; /* no user ID */ pStat->st_gid = 0; /* no group ID */ pStat->st_rdev = 0; /* no special device ID */ pStat->st_size = isDir ? 0 : pDir->length; /* file size, in bytes */ pStat->st_atime = 0; /* no last-access time */ pStat->st_mtime = 0; /* no last-modified time */ pStat->st_ctime = 0; /* no last-change time */ pStat->st_attrib = 0; /* file attribute byte */ /* * Set file access permissions to be read/write by all; for * directories, add exec (search). */ pStat->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); if (isDir) pStat->st_mode |= (S_IXUSR | S_IXGRP | S_IXOTH); /* Is it a file or directory? */ if (isDir) pStat->st_mode |= S_IFDIR; /* it is a directory */ else pStat->st_mode |= S_IFREG; /* it is a regular file */ return (OK); }/********************************************************************************* memRead - read from a memory file** RETURNS: ERROR if the file open mode is O_WRONLY; otherwise, the number of* bytes read (may be less than the amount requested), or 0 if the* file is at EOF.** ERRNO: EINVAL, EISDIR**/LOCAL int memRead ( MEM_FILE_DESC *pfd, /* file descriptor of file to read */ char *buffer, /* buffer to receive data */ int maxbytes /* max bytes to read in to buffer */ ) { MEM_DRV_DIRENTRY *pDir = pfd->pDir; /* pointer to file info */ int lLeft; /* Fail if the mode is invalid, or if it's a directory. */ if (pfd->mode == O_WRONLY) { errnoSet (EINVAL); return (ERROR); } if (pDir == NULL || pDir->pDir != NULL) { errnoSet (EISDIR); return (ERROR); } /* calculate #bytes left to read */ lLeft = pDir->length - pfd->offset; if (lLeft < 0) lLeft = 0; /* limit maxbytes to minimum of bytes left or buffer length */ if (maxbytes > lLeft) maxbytes = lLeft; if (maxbytes > 0) { bcopy (pDir->base + pfd->offset, buffer, maxbytes); pfd->offset += maxbytes; } return (maxbytes); }/********************************************************************************* memWrite - write to a memory file** RETURNS: The number of bytes written, or ERROR if past the end of memory or* is O_RDONLY only.** ERRNO: EINVAL, EISDIR**/LOCAL int memWrite ( MEM_FILE_DESC *pfd, /* file descriptor of file to write */ char *buffer, /* buffer to be written */ int nbytes /* number of bytes to write from buffer */ ) { MEM_DRV_DIRENTRY *pDir = pfd->pDir; /* pointer to file info */ int lLeft; /* Fail if the mode is invalid, or if it's a directory. */ if (pfd->mode == O_RDONLY) { errnoSet (EINVAL); return (ERROR); } if (pDir == NULL || pDir->pDir != NULL) { errnoSet (EISDIR); return (ERROR); } /* calculate #bytes left to write */ lLeft = pDir->length - pfd->offset; if (lLeft < 0) lLeft = 0; /* If write is too large, truncate it */ if (nbytes > lLeft) nbytes = lLeft; if (nbytes > 0) { bcopy (buffer, pDir->base + pfd->offset, nbytes); pfd->offset += nbytes; } return (nbytes); }/********************************************************************************* memIoctl - do device specific control function** Only the FIONREAD, FIOSEEK, FIOWHERE, FIOGETFL, FIOFSTATGET, and* FIOREADDIR options are supported.** RETURNS: OK, or ERROR if seeking passed the end of memory.** ERRNO: EINVAL, S_ioLib_UNKNOWN_REQUEST**/LOCAL STATUS memIoctl (pfd, function, arg) FAST MEM_FILE_DESC *pfd; /* descriptor to control */ FAST int function; /* function code */ int arg; /* some argument */ { MEM_DRV_DIRENTRY *pDir = pfd->pDir; /* pointer to file info */ DIR *dirp; int isDir = 0; int status = OK; if (pDir == NULL) { errnoSet (EINVAL); status = ERROR; } else { isDir = (pDir->pDir != NULL); switch (function) { case FIONREAD: if (isDir) { errnoSet (EINVAL); status = ERROR; } else { *((int *) arg) = pDir->length - pfd->offset; } break; case FIOSEEK: if (isDir || arg > pDir->length) { errnoSet (EINVAL); status = ERROR; } else { pfd->offset = arg; } break; case FIOWHERE: if (isDir) status = 0; else status = pfd->offset; break; case FIOGETFL: *((int *) arg) = pfd->mode; break; case FIOFSTATGET: status = memFileStatGet (pfd, (struct stat *) arg); break; case FIOREADDIR: /* * The index of the directory entry required is passed in via * dirp->dd_cookie. We're supposed to return the name in * dirp->dd_dirent. */ dirp = (DIR *) arg; if (!isDir || dirp->dd_cookie >= pDir->length) { errnoSet (EINVAL); status = ERROR; } else { strcpy (dirp->dd_dirent.d_name, pDir->pDir[dirp->dd_cookie].name); ++dirp->dd_cookie; } break; default: errnoSet (S_ioLib_UNKNOWN_REQUEST); status = ERROR; break; } } return (status); }/********************************************************************************* memClose - close a memory file** RETURNS: OK, or ERROR if file couldn't be flushed or entry couldn't * be found.*/LOCAL STATUS memClose (pfd) MEM_FILE_DESC *pfd; /* file descriptor of file to close */ { free (pfd); return OK; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -