/* WARNING: This write function is far beyond complete, * data block allocation and vnode expansion support should be added */ ssize_t write(int fildes, void *buf, size_t nbyte) { blkcnt_t blk, oldblk; off_t disp; size_t xfer = nbyte, i=0; struct scache *scp; struct ofile *ofp = (struct ofile*)fildes; /* do the data copy */ while(xfer) { /* calculate pos defined block number * and displacement. */ blk = ofp->pos/ofp->mount->blksize; blk += ofp->node->blkentry; blk += fs_daddr(ofp->mount->fs, ofp->mount->sblk); disp = ofp->pos%ofp->mount->blksize; /* load block to cache if not loaded */ if(oldblk != blk) { scp = scache_get(ofp->node->dev, blk, ofp->mount->blksize); oldblk = blk; } /* do the copy */ if((xfer+disp) > ofp->mount->blksize) { memcpy(&scp->buf[disp], &((char*)buf)[i], ofp->mount->blksize - disp); scp->mode |= S_CHANGED; ofp->pos += ofp->mount->blksize - disp; disp = 0; xfer -= ofp->mount->blksize - disp; i += ofp->mount->blksize - disp; } else { memcpy(&scp->buf[disp], &((char*)buf)[i], xfer); scp->mode |= S_CHANGED; ofp->pos += xfer; disp = 0; xfer -= xfer; i += xfer; } /* check end of file with pos */ if(ofp->pos > ofp->node->size) { ofp->pos = ofp->node->size; break; } } return nbyte; }
interface_info* get_iinfo(const char* iname, bool add_if_need) { interface_info *ret = 0; ret = scache_get(&statistic, iname, 0); if (!ret && add_if_need) { ret = (interface_info*)malloc(sizeof(interface_info)); ret->ibytes = 0; ret->obytes = 0; ret->last_time = 0; scache_set(&statistic, iname, ret); } return ret; }
off_t lseek(int fildes, off_t offset, int whence) { blkcnt_t blk; struct ofile *ofp = (struct ofile*)fildes; /* general methods: * 1. setup displacement * 2. update sector buffer */ switch(whence) { case SEEK_SET: ofp->pos = offset; break; case SEEK_CUR: ofp->pos+= offset; break; case SEEK_END: ofp->pos = ofp->node->size; ofp->pos+= offset; break; } /* boundary checks */ if((ofp->pos > ofp->node->size) || (ofp->pos < 0)) { return -1; /* offset out of boundary */ } /* calculate block index */ blk = ofp->pos/ofp->mount->blksize; blk+= ofp->node->blkentry; blk+= fs_daddr(ofp->mount->fs, ofp->mount->sblk); /* load block if not in buffer */ scache_get(ofp->node->dev, blk, ofp->mount->blksize); return ofp->pos; }
/* flags to support: * O_RDONLY * O_WRONLY * O_RDWR * O_CREAT * O_EXCL * O_TRUNC * O_APPEND */ int open(char *path, int oflag, ...) { struct vnode *vp; struct scache *scp; struct mountab *mtp; struct ofile *ofp; /* first, find the corresponding vnode of *path */ vp = vget(path, 0); if((vp == (struct vnode*)-1)||(vp == 0)) { /* file not found */ if(oflag&O_CREAT) { if((oflag&O_EXCL) == O_EXCL) { return 0; } /* create the file and continue the process */ } } else if(((oflag&O_CREAT) == O_CREAT) && ((oflag&O_EXCL) == O_EXCL)) { return -1; } /* checking read/write permitions, * kernel is the owner of all files */ if(((oflag&O_RDONLY) == O_RDONLY) && ((vp->mode&S_IRUSR) != S_IRUSR)) { return -1; } if(((oflag&O_WRONLY) == O_WRONLY) && ((vp->mode&S_IWUSR) != S_IWUSR)) { return -1; } /* load sectors containing the requested data position */ mtp = mountab_get(vp->dev); if(mtp == 0) { return -1; /* mount point not found */ } scp = scache_get(vp->dev, vp->blkentry, mtp->blksize); if(scp == 0) { return -1; /* cannot locate data block */ } /* request a open file descriptor * describing kernel file operation, * which containing vnode data, * mount data and beginning sector cache data*/ ofp = ofile_alloc(); if(ofp == 0) { MSG(1, "no open file descriptor available\n"); return -1; /* no ofile available */ } ofp->node = vp; ofp->mount = mtp; ofp->oflag = oflag; /* setup pos value, load pos sector to buffer */ if((oflag&&O_APPEND) == O_APPEND) { /* set pos to end of file */ ofp->pos = vp->size; } else if((oflag&&O_TRUNC) == O_TRUNC) { /* release all data blocks allocated, * setup file size to 0 and block data to 0*/ ofp->pos = 0; vp->size = 0; blkcnt_t bc; for(bc=vp->blkentry; bc<=vp->blkentry+vp->blocks; bc++) { fs_dfree(mtp->fs, mtp->sblk, vp->dev, bc); } vp->blkentry = 0; vp->blocks = 0; } else { ofp->pos = 0; } lseek((int)ofp, ofp->pos, SEEK_SET); return (int)ofp; }