📄 passfslib.c
字号:
** passFsFileStatfsGet - get file system status (directory entry data)** This routine is called via an ioctl() call, using the FIOFSTATFSGET* function code. The passed statfs structure is filled, using data* obtained from the directory entry which describes the file.** RETURNS: ERROR or OK*/LOCAL STATUS passFsFileStatfsGet ( PASS_FILE_DESC *pPassFd, /* pointer to file descriptor */ struct statfs *pStatfs /* structure to fill with data */ ) { struct unix_statvfs unixbuf; if (u_statvfs (pPassFd->passName, (char*)&unixbuf) == -1) return (ERROR); bzero ((char *) pStatfs, sizeof (struct statfs));/* zero out statfs struc */ /* Fill statfs structure */ pStatfs->f_bsize = unixbuf.f_frsize; /* file system block size */ pStatfs->f_blocks = unixbuf.f_blocks; /* total number of blocks */ pStatfs->f_bfree = unixbuf.f_bfree; /* number of free blocks */ pStatfs->f_bavail = unixbuf.f_bavail; /* free blocks avail to non-superuser */ pStatfs->f_files = unixbuf.f_files; /* number of file nodes */ pStatfs->f_ffree = unixbuf.f_ffree; /* number of free file nodes */ pStatfs->f_fsid.val[0]= unixbuf.f_fsid; /* file system id */ return (OK); }#endif /* CPU == SIMSPARCSOLARIS */ /********************************************************************************* passFsInit - prepare to use the passFs library** This routine initializes the passFs library. It must be called exactly once,* before any other routines in the library. The argument specifies the number* of passFs devices that may be open at once. This routine installs* passFsLib as a driver in the I/O system driver table, allocates and sets * up the necessary memory structures, and initializes semaphores.** Normally this routine is called from the root task, usrRoot(),* in usrConfig(). This initialization is enabled when the* configuration macro INCLUDE_PASSFS is defined.** NOTE* Maximum number of pass-through file systems is 1.** RETURNS: OK, or ERROR.*/STATUS passFsInit ( int nPassfs /* number of pass-through file systems */ ) { if (passFsDrvNum != 0) return (ERROR); /* can't call more than once */ /* Install passFsLib routines in I/O system driver table */ passFsDrvNum = iosDrvInstall ((FUNCPTR) passFsCreate, passFsDelete, (FUNCPTR) passFsOpen, passFsClose, passFsRead, passFsWrite, passFsIoctl); if (passFsDrvNum == ERROR) return (ERROR); /* can't install as driver */ if (nPassfs < 0 || nPassfs > 1) return (ERROR); /* can't install as driver */ if ((passVolume = calloc (nPassfs, sizeof (VOL_DESC))) == NULL) return (ERROR); return (OK); }/********************************************************************************* passFsIoctl - do device specific control function** This routine performs the following ioctl() functions:** .CS* FIODISKINIT: Initialize the disk volume. This routine does not* format the disk, that must be done by the driver.* FIORENAME: Rename the file to the string pointed to by arg.* FIOSEEK: Sets the file's current byte position to* the position specified by arg.* FIOWHERE: Returns the current byte position in the file.* FIOFLUSH: Flush file output buffer.* Guarantees that any output that has been requested* is actually written to the device.* FIONREAD: Return in arg the number of unread bytes.* FIODISKCHANGE: Indicate media change. See passFsReadyChange().* FIOUNMOUNT: Unmount disk volume. See passFsVolUnmount().* FIONFREE: Return amount of free space on volume.* FIOMKDIR: Create a new directory.* FIORMDIR: Remove a directory.* FIOLABELGET: Get volume label (located in root directory).* FIOLABELSET: Set volume label.* FIOATTRIBSET: Set file attribute.* FIOCONTIG: Allocate contiguous disk space for file or directory.* FIOSYNC: Write all modified files and data structures to device.* FIOREADDIR: Read next directory entry, uses DIR directory descriptor.* FIOFSTATGET: Get file status info (directory enty data).* .CE** Any other ioctl function codes are passed to the block device driver* for handling.** If an ioctl fails, the task's status (see errnoGet()) indicates* the nature of the error.** RETURNS: OK, or ERROR if function failed or driver returned error, or* current byte pointer for FIOWHERE.*/LOCAL STATUS passFsIoctl ( PASS_FILE_DESC *pPassFd, /* file descriptor of file to control */ int function, /* function code */ int arg /* some argument */ ) { int retValue = OK; int whereCur; /* current byte position in file, could include cache */ int where; /* exact current byte position in file */ int end; switch (function) { case FIODISKINIT: break; case FIORENAME: if (u_rename (pPassFd->passName, (char *)arg) == -1) retValue = ERROR; break; case FIOSEEK: /* invalidate any read cache */ pPassFd->cacheBytes = 0; pPassFd->cacheOffset = 0; /* do a lseek with offset arg0 from beginning of file */ if (u_lseek (pPassFd->unixFd, (int)arg, 0) == -1) retValue = ERROR; break; case FIOWHERE: /* do a lseek with offset 0 from current to get current offset */ retValue = u_lseek (pPassFd->unixFd, 0, 1/*SEEK_CUR*/); /* Adjust since we cache ahead, so LSEEK returns too far */ if (retValue > 0 && pPassFd->cacheBytes != 0) retValue -= (pPassFd->cacheBytes - pPassFd->cacheOffset); break; case FIOSYNC: case FIOFLUSH: break; case FIONREAD: /* * compute the number of bytes between the current location and * the end of this file. * We uses this method rather than a call to : * u_ioctl (pPassFd->unixFd, U_FIONREAD, 0); * because FIONREAD is not officially supported on Solaris and it * does not work on Solaris 2.5. (SPR #22476 & 23615). */ whereCur = u_lseek (pPassFd->unixFd, 0, 1/*SEEK_CUR*/); if (whereCur == ERROR) retValue = ERROR; else { /* Adjust since we cache ahead, so LSEEK returns too far */ if (pPassFd->cacheBytes != 0) where = whereCur - (pPassFd->cacheBytes - pPassFd->cacheOffset); else where = whereCur; end = u_lseek (pPassFd->unixFd, 0, 2/*SEEK_END*/); if (end == ERROR) retValue = ERROR; else { /* go back to the current location */ if (u_lseek (pPassFd->unixFd, whereCur, 0/*SEEK_SET*/) == ERROR) retValue = ERROR; else *((int *) arg) = end - where; } } break; case FIODISKCHANGE: break; case FIOUNMOUNT: break; case FIONFREE: /* this is hard to do on a UNIX file system - lie */ *((int *) arg) = 0x1000000; break; case FIOMKDIR: if (passFsDirMake (pPassFd->passVdptr, (char *) arg, FALSE) == ERROR) retValue = ERROR; break; case FIORMDIR: if (u_rmdir (pPassFd->passName) == -1) retValue = ERROR; break; case FIOLABELGET: strcpy ((char *)arg, passVolume->passDevName); break; case FIOLABELSET: break; case FIOATTRIBSET: break; case FIOCONTIG: break; case FIOREADDIR: retValue = passFsDirRead (pPassFd, (DIR *) arg); break; case FIOFSTATGET: retValue = passFsFileStatGet (pPassFd, (struct stat *) arg); break;#if CPU == SIMSPARCSOLARIS case FIOFSTATFSGET: retValue = passFsFileStatfsGet (pPassFd, (struct statfs *) arg); break;#endif /* CPU == SIMSPARCSOLARIS */ case FIOSETOPTIONS: /* XXX usually trying to set OPT_TERMINAL -- just ignore */ break; default: printErr ("passFsLib: unknown ioctl = %#x\n", function); retValue = ERROR; break; } return (retValue); }/********************************************************************************* passFsOpen - open a file on a passFs volume** This routine opens the file <name> with the specified mode * (READ/WRITE/UPDATE/CREATE/TRUNC). The directory structure is * searched, and if the file is found a passFs file descriptor * is initialized for it.** RETURNS: A pointer to a passFs file descriptor, or ERROR * if the volume is not available * or there are no available passFs file descriptors * or there is no such file.*/LOCAL PASS_FILE_DESC *passFsOpen ( VOL_DESC *vdptr, /* pointer to volume descriptor */ char *name, /* passFs full path/filename */ int flags, /* file open flags */ int mode /* file open permissions (mode) */ ) { PASS_FILE_DESC *pPassFd; /* file descriptor pointer */ /* Check if creating dir */ if ((flags & O_CREAT) && (mode & FSTAT_DIR)) { return (passFsDirCreate (vdptr, name)); } /* Get a free file descriptor */ if ((pPassFd = (PASS_FILE_DESC *) calloc (1, sizeof (PASS_FILE_DESC))) == NULL) { return ((PASS_FILE_DESC *) ERROR); } if ((pPassFd->unixFd = u_open (name, ARCHCVTFLAGS(flags), mode)) == -1) { free (pPassFd); return ((PASS_FILE_DESC *) ERROR); } strcpy (pPassFd->passName, name); pPassFd->passDir = (UNIX_DIR *)0; pPassFd->readCache = (char *)0; pPassFd->cacheBytes = 0; pPassFd->cacheOffset = 0; pPassFd->passVdptr = vdptr; return (pPassFd); }/********************************************************************************* passFsRead - read from a passFs file** This routine reads from the file specified by the file descriptor* (returned by passFsOpen()) into the specified buffer.* <maxbytes> bytes will be read, if there is that much data in the file* and the file I/O buffer is large enough.** RETURNS: Number of bytes actually read, or 0 if end of file, or* ERROR if <maxbytes> is <= 0 or unable to get next cluster.*/LOCAL int passFsRead ( PASS_FILE_DESC *pPassFd, /* file descriptor pointer */ char *pBuf, /* addr of input buffer */ int maxBytes /* maximum bytes to read into buffer */ ) { int ret; int bytesRead = 0; int readableCacheBytes; char *cachePtr; /* attempt to service the read from cache first */ if (pPassFd->cacheBytes) { readableCacheBytes = pPassFd->cacheBytes - pPassFd->cacheOffset; cachePtr = pPassFd->readCache + pPassFd->cacheOffset; /* if we have more cached data than asked for */ if (readableCacheBytes > maxBytes) { readableCacheBytes = maxBytes; pPassFd->cacheOffset += readableCacheBytes; } else { /* invalidate cache since its all going to be read */ pPassFd->cacheBytes = 0; pPassFd->cacheOffset = 0; } bcopy (cachePtr, pBuf, readableCacheBytes); /* if we are done, bail now */ if (readableCacheBytes == maxBytes) return (maxBytes); maxBytes -= readableCacheBytes; bytesRead += readableCacheBytes; pBuf += readableCacheBytes; } /* initialize read cache if first read */ if (pPassFd->readCache == (char *)0) { if ((pPassFd->readCache = (char*)calloc (1, CACHE_SIZE)) == (char *)0) return (ERROR); } /* ok, here we know the cache is allocated and invalidated */ /* caching can't help if they want a huge chunk */ if (maxBytes >= CACHE_SIZE) { if ((ret = u_read (pPassFd->unixFd, pBuf, maxBytes)) == -1) return (bytesRead ? bytesRead : ERROR); bytesRead += ret; } else { ret = u_read (pPassFd->unixFd,pPassFd->readCache, CACHE_SIZE); if ( ret == -1) return (bytesRead ? bytesRead : ERROR); pPassFd->cacheBytes = ret; /* If there wasn't as much as asked for */ if (ret < maxBytes) maxBytes = ret; bcopy (pPassFd->readCache, pBuf, maxBytes); bytesRead += maxBytes; pPassFd->cacheOffset = maxBytes; } return (bytesRead); }/********************************************************************************* passFsWrite - write to a passFs file** This routine writes to the file specified by the file descriptor* (returned by passFsOpen()) from the specified buffer. ** RETURNS: Number of bytes written (error if != nBytes), or ERROR if * nBytes < 0, or no more space for the file, or can't write cluster.*/LOCAL int passFsWrite ( PASS_FILE_DESC *pPassFd, /* file descriptor pointer */ char *pBuf, /* data to be written */ int maxBytes /* number of bytes to write */ ) { int nBytes; /* invalidate read cache */ pPassFd->cacheBytes = 0; pPassFd->cacheOffset = 0; if ((nBytes = u_write (pPassFd->unixFd, pBuf, maxBytes)) == -1) return (ERROR); return (nBytes); }#endif /* (CPU_FAMILY==SIMSPARCSUNOS || CPU_FAMILY==SIMHPPA || CPU_FAMILY==SIMSPARCSOLARIS) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -