int rename(const char* from, const char* to) { int oerrno; int ooerrno; ooerrno = errno; while (link(from, to)) { #ifdef EPERM if (errno == EPERM) { errno = ooerrno; return mvdir(from, to); } #endif oerrno = errno; if (unlink(to)) { #ifdef EPERM if (errno == EPERM) { errno = ooerrno; return mvdir(from, to); } #endif errno = oerrno; return -1; } } errno = ooerrno; return unlink(from); }
/*------------------------------------------------------------------------ * lflClose -- close a file by flushing output and freeing device entry *------------------------------------------------------------------------ */ devcall lflClose ( struct dentry *devptr /* entry in device switch table */ ) { struct lflcblk *lfptr; /* ptr to open file table entry */ /* Obtain exclusive use of the file */ lfptr = &lfltab[devptr->dvminor]; wait(lfptr->lfmutex); /* If file is not open, return an error */ if (lfptr->lfstate != LF_USED) { signal(lfptr->lfmutex); return SYSERR; } /* Write index or data blocks to disk if they have changed */ if (lfptr->lfdbdirty || lfptr->lfibdirty) { lfflush(lfptr); } wait(lfDirCblkMutex); if (mvdir(lfptr->lfpath,lfptr->lfdepth-1) == SYSERR) { signal(lfDirCblkMutex); signal(lfptr->lfmutex); return SYSERR; } if (lflCloseHelper(lfptr->lfpath[lfptr->lfdepth-1],lfptr) == SYSERR) { signal(lfDirCblkMutex); signal(lfptr->lfmutex); return SYSERR; } /* Set device state to FREE and return to caller */ lfptr->lfstate = LF_FREE; signal(lfDirCblkMutex); signal(lfptr->lfmutex); return OK; }
/*------------------------------------------------------------------------ * lfsOpen - open a file and allocate a local file pseudo-device *------------------------------------------------------------------------ */ devcall lfsOpen ( struct dentry *devptr, /* entry in device switch table */ char *path, /* complete path of file to open */ char *mode /* mode chars: 'r' 'w' 'o' 'n' */ ) { did32 lfnext; /* minor number of an unused */ /* file pseudo-device */ struct lflcblk *lfptr; /* ptr to open file table entry */ int32 mbits; /* mode bits */ char pathTokens[LF_PATH_DEPTH][LF_NAME_LEN]; int pathDepth = tokenize(path,pathTokens); if (pathDepth == SYSERR) { return SYSERR; } if (1 == pathDepth && PATH_SEPARATOR==pathTokens[0][0]) { return SYSERR; } /* Parse mode argument and convert to binary */ mbits = lfgetmode(mode); if (mbits == SYSERR) { return SYSERR; } /* If named file is already open, return SYSERR */ lfnext = SYSERR; wait(lfDirCblkMutex); if (isopenfile(pathTokens,pathDepth,&lfnext)) { signal(lfDirCblkMutex); return SYSERR; } if (lfnext == SYSERR) { /* no slave file devices are available */ signal(lfDirCblkMutex); return SYSERR; } struct ldentry fileInfo; /* * Initialize lfltab[Nlfl+1] and lfltab[Nlfl] * to parent and grandparent of the file we * want to open. * e.g. to /a/b and to /a/ if we want to open * /a/b/c. */ if (mvdir(pathTokens,pathDepth-1) == SYSERR) { signal(lfDirCblkMutex); return SYSERR; } /* * Either create a new file or open an already existing file. */ if (lfsOpenHelper(pathTokens[pathDepth-1],&fileInfo,mbits) == SYSERR) { signal(lfDirCblkMutex); return SYSERR; } /* Initialize the local file pseudo-device */ lfptr = &lfltab[lfnext]; lfptr->lfstate = LF_USED; lfptr->lfmode = mbits & LF_MODE_RW; /* File starts at position 0 */ lfptr->lfpos = 0; /* Neither index block nor data block are initially valid */ lfptr->lfinum = LF_INULL; lfptr->lfdnum = LF_DNULL; /* Initialize byte pointer to address beyond the end of the */ /* buffer (i.e., invalid pointer triggers setup) */ lfptr->lfbyte = &lfptr->lfdblock[LF_BLKSIZ]; lfptr->lfibdirty = FALSE; lfptr->lfdbdirty = FALSE; lfptr->lfsize = fileInfo.ld_size; lfptr->lffirstib = fileInfo.ld_ilist; memcpy(lfptr->lfpath,pathTokens,LF_NAME_LEN * LF_PATH_DEPTH); lfptr->lfdepth = pathDepth; signal(lfDirCblkMutex); return lfptr->lfdev; }