📄 netdrv.c
字号:
{ errnoSet (S_netDrv_WRITE_ONLY_CANNOT_READ); return (ERROR); } semTake (&pNetFd->netFdSem, WAIT_FOREVER); /* if file pointer is at end of file, can't read any characters */ if (pNetFd->filePtrByte == pNetFd->endOfFile) { semGive (&pNetFd->netFdSem); return (0); } cindex = pNetFd->filePtrByte % DATASIZE; /* char index in datablock */ dptr = pNetFd->filePtrBlock; cptr = &dptr->databuf [cindex]; /* point to current char in datablock */ bptr = buf; /* point to beginning of read buffer */ /* read until maxBytes characters have been read */ while (byteCount < maxBytes) { if ((maxBytes - byteCount) < (dptr->used - cindex)) { /* stop reading when maxBytes characters have been read. * This is the last block to read from in order to finish * filling up the buffer. */ bcopy (cptr, bptr, maxBytes - byteCount); byteCount = maxBytes; } else { /* copy the rest of the datablock into buffer */ bcopy (cptr, bptr, dptr->used - cindex); byteCount = byteCount + dptr->used - cindex; if (dptr == (DATABLOCK *) lstLast (&pNetFd->dataLst)) { /* this is the last block in the file. Seek to the end. */ status = netSeek (pNetFd, pNetFd->endOfFile); semGive (&pNetFd->netFdSem); return (status == ERROR ? ERROR : byteCount); } else /* get next block */ { dptr = (DATABLOCK *) lstNext ((NODE *) dptr); cindex = 0; cptr = dptr->databuf; /* point to first character in block */ bptr = buf + byteCount; /* move buffer pointer */ } } } /* end of while */ status = netSeek (pNetFd, pNetFd->filePtrByte + byteCount); semGive (&pNetFd->netFdSem); return (status == ERROR ? ERROR : byteCount); }/********************************************************************************* netWrite - write bytes to remote file** netWrite copies up to the specified number of bytes from the buffer* to the open network file descriptor. Bytes are written starting* at the spot pointed to by the file's block and byte pointers.* The file pointer is updated to point immediately after the last* character that was written.** Called only by the I/O system.** SIDE EFFECTS: moves file pointer** RETURNS:* Number of bytes written (error if != nbytes), or* ERROR if nBytes < 0, or no more space can be allocated.*/LOCAL int netWrite ( FAST NET_FD *pNetFd, /* open file descriptor */ char *buffer, /* buffer being written from */ FAST int nBytes /* number of bytes to write to file */ ) { STATUS status; FAST int byteCount = 0; /* number of written read so far */ FAST DATABLOCK *dptr; /* points to current datablock */ FAST int cindex; /* character index datablock's databuf */ FAST char *cptr; /* points to char being overwritten in file */ FAST char *bptr; /* points to current position in buffer */ /* check for valid number of bytes */ if (nBytes < 0) { errnoSet (S_netDrv_INVALID_NUMBER_OF_BYTES); return (ERROR); } /* if file opened for O_RDONLY, don't write */ if ((pNetFd->options & FD_MODE) == O_RDONLY) { errnoSet (S_netDrv_READ_ONLY_CANNOT_WRITE); return (ERROR); } semTake (&pNetFd->netFdSem, WAIT_FOREVER); cindex = pNetFd->filePtrByte % DATASIZE; dptr = pNetFd->filePtrBlock; cptr = &dptr->databuf [cindex]; bptr = buffer; while (byteCount < nBytes) { if ((nBytes - byteCount) < (DATASIZE - cindex)) { /* almost done writing nBytes. This is the last block to write to */ bcopy (bptr, cptr, nBytes - byteCount); byteCount = nBytes; /* if we wrote past end of file, adjust end of file pointer */ if ((pNetFd->filePtrByte + byteCount > pNetFd->endOfFile) && moveEndOfFile (pNetFd, pNetFd->filePtrByte + byteCount) == ERROR) { semGive (&pNetFd->netFdSem); return (ERROR); } } else /* not last block to write to */ { bcopy (bptr, cptr, DATASIZE - cindex); byteCount = byteCount + DATASIZE - cindex; /* if we wrote past end of file, adjust end of file pointer. * If necessary, moveEndOfFile will attach a new datablock * to the end of the data chain. */ if ((pNetFd->filePtrByte + byteCount > pNetFd->endOfFile) && moveEndOfFile (pNetFd, pNetFd->filePtrByte + byteCount) == ERROR) { semGive (&pNetFd->netFdSem); return (ERROR); } /* point to first character in next datablock */ dptr = (DATABLOCK *) lstNext ((NODE *) dptr); cindex = 0; cptr = dptr->databuf; /* adjust buffer pointer */ bptr = buffer + byteCount; } } /* end of while loop */ pNetFd->options |= FD_DIRTY; status = netSeek (pNetFd, pNetFd->filePtrByte + byteCount); semGive (&pNetFd->netFdSem); return (status == ERROR ? ERROR : byteCount); }/********************************************************************************* netIoctl - do device specific control function** Called only by the I/O system.** RETURNS: Whatever the called function returns.*/LOCAL int netIoctl ( FAST NET_FD *pNetFd, /* open network file descriptor */ FAST int function, /* function code */ FAST int arg /* argument for function */ ) { struct stat *pStat; /* pointer to struct for stat() call */ switch (function) { case FIOSEEK: return (netSeek (pNetFd, arg)); case FIOWHERE: return (pNetFd->filePtrByte); case FIONREAD: *((int *) arg) = pNetFd->endOfFile - pNetFd->filePtrByte; return (OK); case FIODIRENTRY: /* this is a kludge for 'ls'. Do the listing, then return ERROR so that 'ls' doesn't try listing an rt-11 device */ netLs (pNetFd); return (ERROR); case FIOGETFL: *((int *) arg) = pNetFd->options & FD_MODE; return (OK); case FIOFSTATGET: /* get status of a file */ pStat = (struct stat *) arg; /* get file attributes returned in pStat */ /* zero out the pStat structure */ bzero ((char *) pStat, sizeof (*pStat)); /* fill in the elements of the stat struct that we have */ pStat->st_dev = (ULONG) pNetFd->pNetDev; pStat->st_mode = S_IFREG; pStat->st_size = pNetFd->endOfFile; return (OK); break; default: errnoSet (S_netDrv_UNKNOWN_REQUEST); return (ERROR); } }/********************************************************************************* netSeek - change file's current character position** This routine moves the file pointer by the offset to a new* position. If the new position is past the end of file, fill the* unused space with 0's. The end of file pointer gets moved to the* position immediately following the last '0' written.* If the resulting file pointer would be negative, ERROR is returned.** Called only by the I/O system.** INTERNAL* There is deliberate co-recursion between netSeek and netWrite.** RETURNS: OK or ERROR.*/LOCAL int netSeek ( FAST NET_FD *pNetFd, FAST int newPos ) { FAST DATABLOCK *saveFilePtrBlock; FAST int saveFilePtrByte; int endOfFile; int newBlock; int curBlock; char *buf; DATABLOCK *dptr; int nbytes; if (newPos < 0) { errnoSet (S_netDrv_BAD_SEEK); return (ERROR); } saveFilePtrBlock = pNetFd->filePtrBlock; saveFilePtrByte = pNetFd->filePtrByte; endOfFile = pNetFd->endOfFile; newBlock = newPos / DATASIZE; curBlock = pNetFd->filePtrByte / DATASIZE; /* if new position is past end of file */ if (newPos > endOfFile) { /* put 0's at the end of the file */ if ((buf = (char *) malloc ((unsigned) (newPos - endOfFile))) == NULL) { return (ERROR); } bzero (buf, newPos - endOfFile); /* move file pointer to end of file before writing 0's */ pNetFd->filePtrBlock = (DATABLOCK *) lstLast (&pNetFd->dataLst); pNetFd->filePtrByte = endOfFile; /* netWrite will update the file pointer and end of file pointer */ nbytes = netWrite (pNetFd, buf, (newPos - endOfFile)); if (nbytes != (newPos - endOfFile)) { if (nbytes != ERROR) errnoSet (S_netDrv_SEEK_PAST_EOF_ERROR); pNetFd->filePtrBlock = saveFilePtrBlock; pNetFd->filePtrByte = saveFilePtrByte; free (buf); return (ERROR); } free (buf); } else /* else, new position is within current file size */ { /* point to new block */ /* system error if we go out of range of the datablocks */ dptr = (DATABLOCK *) lstNStep ((NODE *) pNetFd->filePtrBlock, newBlock - curBlock); if (dptr == NULL) { errnoSet (S_netDrv_SEEK_FATAL_ERROR); return (ERROR); } pNetFd->filePtrBlock = dptr; /* point to new byte */ pNetFd->filePtrByte = newPos; } return (OK); }/********************************************************************************* moveEndOfFile - moves end of file pointer to new position** Adds a new datablock to the end of the datablock list if necessary.* Assumes that end of file moves at most to the first position of* the next datablock.** RETURNS: OK or ERROR.*/LOCAL STATUS moveEndOfFile ( FAST NET_FD *pNetFd, FAST int newPos ) { FAST DATABLOCK *dptr; /* pointer to new datablock */ /* * As soon as system error handling is implemented, a message should * be put here. * * If the new position is before the current end of file, * OR more than one datablock ahead, * OR further away than the first byte of the next datablock, * this is a system error ....looks awful, I know */ if ((newPos <= pNetFd->endOfFile) || ((newPos - pNetFd->endOfFile) > DATASIZE) || ((newPos % DATASIZE < pNetFd->endOfFile % DATASIZE) && (newPos % DATASIZE != 0))) { errnoSet (S_netDrv_BAD_EOF_POSITION); return (ERROR); } /* if new position is in datablock after end of file, * add another datablock to the file */ if ((newPos / DATASIZE) > (pNetFd->endOfFile / DATASIZE)) { /* current datablock is full. * New position is in the block after the current * end of file. */ ((DATABLOCK *) lstLast (&pNetFd->dataLst))->used = DATASIZE; if ((dptr = (DATABLOCK *) malloc (sizeof (DATABLOCK))) == NULL) return (ERROR); dptr->used = 0; lstAdd (&pNetFd->dataLst, (NODE *) dptr); } else ((DATABLOCK *) lstLast (&pNetFd->dataLst))->used = newPos % DATASIZE; pNetFd->endOfFile = newPos; return (OK); }/********************************************************************************* releaseNetFd - free up NetFd*/LOCAL void releaseNetFd ( FAST NET_FD *pNetFd ) { lstFree (&pNetFd->dataLst); /* free up data list */ semTerminate (&pNetFd->netFdSem); /* terminate netFdSem */ free ((char *) pNetFd); /* deallocate network fd */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -