📄 nfsdlib.c
字号:
readdirres * nfsproc_readdir_2 ( readdirargs * readDir /* Directory to read */ ) { struct entry * dirEntries; filename * fileNames; int fileNameSize; int entrySpace; char * currentName; char * dirName; DIR * theDir = NULL; struct dirent * localEntry; readdirres * retVal; int dirCount = 0; char * newFile; int numEntries; int entryCurrent; if ((dirName = (char *) alloca (nfsMaxPath)) == NULL) return (NULL); if ((newFile = (char *) alloca (nfsMaxPath)) == NULL) return (NULL); /* Increment statistics */ nfsdServerStatus.readdirCalls++; /* Compute the amount of space needed for each directory entry */ fileNameSize = MEM_ROUND_UP (NAME_LEN + 1); entrySpace = MEM_ROUND_UP (sizeof (readdirres)) + MEM_ROUND_UP (sizeof (entry)) + fileNameSize; /* Compute the number of possible entries to return */ numEntries = readDir->count / entrySpace; /* Allocate space for the entries */ if ((retVal = KHEAP_ALLOC(numEntries * entrySpace)) == NULL) { return (NULL); } else { bzero ((char *) retVal, numEntries * entrySpace); dirEntries = ((struct entry *) retVal) + 1; fileNames = (filename *) (dirEntries + numEntries); } nfsdFhNtoh ((NFS_FILE_HANDLE *) &readDir->dir); /* Create the directory name */ if (nfsdFhToName ((NFS_FILE_HANDLE *) &readDir->dir, dirName) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } /* Open the directory and set the cookie field to what was * passed in readDir */ if ((theDir = opendir (dirName)) == NULL) { retVal->status = nfsdErrToNfs (errno); return (retVal); } else theDir->dd_cookie = *((int *) &readDir->cookie); retVal->readdirres_u.reply.eof = FALSE; /* Read through all the files in the directory */ for (entryCurrent = 0; entryCurrent < numEntries; entryCurrent++) { errno = OK; localEntry = readdir (theDir); if (localEntry == NULL) { if (errno != OK) { retVal->status = nfsdErrToNfs (errno); closedir (theDir); return (retVal); } else { retVal->readdirres_u.reply.eof = TRUE; if (entryCurrent != 0) dirEntries[entryCurrent - 1].nextentry = NULL; else retVal->readdirres_u.reply.entries = NULL; break; } } strcpy (newFile, dirName); strcat (newFile, "/"); strcat (newFile, localEntry->d_name); dirEntries[entryCurrent].fileid = nameToInode (((NFS_FILE_HANDLE *) &readDir->dir)->volumeId, newFile); if (dirEntries[entryCurrent].fileid == ERROR) { retVal->status = nfsdErrToNfs (errno); closedir (theDir); return (retVal); } currentName = ((char *) fileNames) + entryCurrent * fileNameSize; strcpy(currentName, localEntry->d_name); dirEntries[entryCurrent].name = currentName; *((int *) dirEntries[entryCurrent].cookie) = theDir->dd_cookie; if (entryCurrent == numEntries - 1) dirEntries[entryCurrent].nextentry = NULL; else dirEntries[entryCurrent].nextentry = &dirEntries[entryCurrent + 1]; dirCount++; } retVal->status = NFS_OK; if (dirCount != 0) retVal->readdirres_u.reply.entries = dirEntries; else retVal->readdirres_u.reply.entries = NULL; closedir (theDir); return (retVal); }/******************************************************************************** nfsproc_statfs_2 - Get filesystem attributes* * Return information about the filesystem. The NFS equivalent of statfs().** NOMANUAL*/statfsres * nfsproc_statfs_2 ( nfs_fh * fh ) { char * fileName; struct statfs statInfo; statfsres * retVal = KHEAP_ALLOC(sizeof (statfsres)); if (retVal == NULL) return (NULL); if ((fileName = (char *) alloca (nfsMaxPath)) == NULL) return (NULL); /* Increment statistics */ nfsdServerStatus.statfsCalls++; nfsdFhNtoh ((NFS_FILE_HANDLE *) fh); if (nfsdFhToName ((NFS_FILE_HANDLE *) fh, fileName) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } if (statfs (fileName, &statInfo) == ERROR) { retVal->status = nfsdErrToNfs (errno); return (retVal); } retVal->status = NFS_OK; retVal->statfsres_u.reply.tsize = 8 * 1024; retVal->statfsres_u.reply.bsize = statInfo.f_bsize; retVal->statfsres_u.reply.blocks = statInfo.f_blocks; retVal->statfsres_u.reply.bfree = statInfo.f_bfree; retVal->statfsres_u.reply.bavail = statInfo.f_bavail; return (retVal); }/******************************************************************************** nfsdStatusGet - get the status of the NFS server* * This routine gets status information about the NFS server.* * RETURNS: OK, or ERROR if the information cannot be obtained.*/STATUS nfsdStatusGet ( NFS_SERVER_STATUS * serverStats /* pointer to status structure */ ) { memcpy (serverStats, &nfsdServerStatus, sizeof (nfsdServerStatus)); return (OK); }/******************************************************************************** nfsdStatusShow - show the status of the NFS server* * This routine shows status information about the NFS server.* * RETURNS: OK, or ERROR if the information cannot be obtained.*/STATUS nfsdStatusShow ( int options /* unused */ ) { NFS_SERVER_STATUS serverStat; char* outputFormat = "%15s %8d\n"; if (nfsdStatusGet (&serverStat) == ERROR) return (ERROR); printf ("%15s %8s\n", "Service", "Number of Calls"); printf ("%15s %8s\n", "-------", "---------------"); printf (outputFormat, "null", serverStat.nullCalls); printf (outputFormat, "getattr", serverStat.getattrCalls); printf (outputFormat, "setattr", serverStat.setattrCalls); printf (outputFormat, "root", serverStat.rootCalls); printf (outputFormat, "lookup", serverStat.lookupCalls); printf (outputFormat, "readlink", serverStat.readlinkCalls); printf (outputFormat, "read", serverStat.readCalls); printf (outputFormat, "writecache", serverStat.writecacheCalls); printf (outputFormat, "write", serverStat.writeCalls); printf (outputFormat, "create", serverStat.createCalls); printf (outputFormat, "remove", serverStat.removeCalls); printf (outputFormat, "rename", serverStat.renameCalls); printf (outputFormat, "link", serverStat.linkCalls); printf (outputFormat, "symlink", serverStat.symlinkCalls); printf (outputFormat, "mkdir", serverStat.mkdirCalls); printf (outputFormat, "rmdir", serverStat.rmdirCalls); printf (outputFormat, "readdir", serverStat.readdirCalls); printf (outputFormat, "statfs", serverStat.statfsCalls); return (OK); }/******************************************************************************** nfsdFhCreate - Create an NFS file handle** Given a handle to the parent directory, and the name of a file inside that* directory, create a new file handle that specifies the file.* * RETURNS: OK, or ERROR if a file handle for the specified file could not be* created.** NOMANUAL*/STATUS nfsdFhCreate ( NFS_FILE_HANDLE * parentDir, char * fileName, NFS_FILE_HANDLE * fh ) { struct stat str; char * fullName; char *p; /* to remove slash from end of fileName */ if ((fullName = (char *) alloca (nfsMaxPath)) == NULL) return (ERROR); memset (fh, 0, NFS_FHSIZE); if (nfsdFhToName (parentDir, fullName) == ERROR) return (ERROR); /* build fullname, but remove slash from the end of fileName */ /* in order to lkup correspond name from nfsHash */ strcat (fullName, "/"); strcat (fullName, fileName); pathCondense (fullName); for (p = strchr (fullName, EOS); p != fullName && *--p == '/'; ) *p = EOS; if (stat (fullName, &str) == ERROR) return (ERROR); fh->volumeId = parentDir->volumeId; fh->fsId = parentDir->fsId; fh->inode = nfsNmLkupIns (parentDir->volumeId, fullName); if (fh->inode == ERROR) return (ERROR); return (OK); }/******************************************************************************** nfsdFhToName - Convert a file handle to a complete file name* * Given a file handle, fill in the variable fileName with a string specifying* that file.* * RETURNS: OK, or ERROR if the file name could not be created.** NOMANUAL*/STATUS nfsdFhToName ( NFS_FILE_HANDLE * fh, char * fileName ) { NFS_EXPORT_ENTRY * fileSys; if ((fileSys = nfsExportFindById (fh->volumeId)) == NULL) return (ERROR); if (nfsFhLkup (fh, fileName) == ERROR) { errno = NFSERR_STALE; return (ERROR); } return (OK); }/******************************************************************************** nfsdFattrGet - Get the file attributes for a file specified by a file handle* * Given a file handle, fill in the file attribute structure pointed to by* fileAttributes.* * RETURNS: OK, or ERROR if the file attributes could not be obtained.** NOMANUAL*/STATUS nfsdFattrGet ( NFS_FILE_HANDLE * fh, struct fattr * fileAttributes ) { char * fileName; struct stat str; if ((fileName = (char *) alloca (nfsMaxPath)) == NULL) return (ERROR); if (nfsdFhToName (fh, fileName) == ERROR) return (ERROR); if (stat (fileName, &str) == ERROR) return (ERROR); /* set the type */ switch (str.st_mode & S_IFMT) { case S_IFIFO: fileAttributes->type = NFFIFO; break; case S_IFCHR: fileAttributes->type = NFCHR; break; case S_IFDIR: fileAttributes->type = NFDIR; break; case S_IFBLK: fileAttributes->type = NFBLK; break; case S_IFREG: fileAttributes->type = NFREG; break; case S_IFLNK: fileAttributes->type = NFLNK; break; case S_IFSOCK: fileAttributes->type = NFSOCK; break; } fileAttributes->mode = str.st_mode; fileAttributes->nlink = str.st_nlink; fileAttributes->uid = str.st_uid; fileAttributes->gid = str.st_gid; fileAttributes->size = str.st_size; fileAttributes->blocksize = str.st_blksize; fileAttributes->rdev = str.st_rdev; fileAttributes->blocks = str.st_blocks + 1; fileAttributes->fileid = fh->inode; fileAttributes->fsid = str.st_dev; fileAttributes->rdev = str.st_rdev; fileAttributes->atime.seconds = str.st_atime; fileAttributes->mtime.seconds = str.st_mtime; fileAttributes->ctime.seconds = str.st_ctime; fileAttributes->atime.useconds = 0; fileAttributes->mtime.useconds = 0; fileAttributes->ctime.useconds = 0; return (OK); }/******************************************************************************** nfsdErrToNfs - Convert a VxWorks error number to an NFS error number* * Given a VxWorks error number, find the equivalent NFS error number.* If an exact match is not found, return NFSERR_IO.* * RETURNS: The NFS error number.** NOMANUAL*/nfsstat nfsdErrToNfs ( int theErr /* The error number to convert */ ) { switch (theErr) { case EPERM: case S_dosFsLib_READ_ONLY: case S_dosFsLib_WRITE_ONLY: return (NFSERR_PERM); break; case ENOENT: case S_dosFsLib_FILE_NOT_FOUND: return (NFSERR_NOENT); break; case EIO: return (NFSERR_IO); break; case ENXIO: case S_dosFsLib_VOLUME_NOT_AVAILABLE: return (NFSERR_NXIO); break; case EACCES: return (NFSERR_ACCES); break; case EEXIST: case S_dosFsLib_FILE_EXISTS: return (NFSERR_EXIST); break; case ENODEV: return (NFSERR_NODEV); break; case ENOTDIR: case S_dosFsLib_NOT_DIRECTORY: return (NFSERR_NOTDIR); break; case EISDIR: return (NFSERR_ISDIR); break; case EFBIG: return (NFSERR_FBIG); break; case ENOSPC: case S_dosFsLib_DISK_FULL: return (NFSERR_NOSPC); break; case EROFS: return (NFSERR_ROFS); break; case ENAMETOOLONG: case S_dosFsLib_ILLEGAL_NAME: return (NFSERR_NAMETOOLONG); break; case S_dosFsLib_DIR_NOT_EMPTY: case ENOTEMPTY: return (NFSERR_NOTEMPTY); break; default: /* If the error number is less than 100, just return it. * NFS client implementations should understand anything * that looks like a UNIX error number. If it's greater than * 100, return NFSERR_IO. */ if (theErr < 100) return theErr; else return (NFSERR_IO); break; } }/******************************************************************************** nfsdFhHton - convert a file handle from host to network byte order** NOMANUAL*/void nfsdFhHton ( NFS_FILE_HANDLE * fh ) { fh->volumeId = htonl (fh->volumeId); fh->fsId = htonl (fh->fsId); fh->inode = htonl (fh->inode); }/******************************************************************************** nfsdFhNtoh - convert a file handle from host to network byte order** NOMANUAL*/void nfsdFhNtoh ( NFS_FILE_HANDLE * fh ) { fh->volumeId = ntohl (fh->volumeId); fh->fsId = ntohl (fh->fsId); fh->inode = ntohl (fh->inode); }/******************************************************************************** nfsdFsReadOnly - get the mode of the NFS file system* * This routine returns TRUE if the filesystem that contains the file* pointed to by <fh> is exported read-only.* * RETURNS: TRUE, or FALSE if the filesystem is exported read-write.* * NOMANUAL*/LOCAL BOOL nfsdFsReadOnly ( NFS_FILE_HANDLE * fh ) { NFS_EXPORT_ENTRY * fileSys; if ((fileSys = nfsExportFindById (fh->volumeId)) == NULL) return (ERROR); else return (fileSys->readOnly); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -