/** * \brief Get an entry by path. * * The directory hierarchy of the file system is traversed to find an entry whose name is the rightmost component of * <tt>ePath</tt>. The path is supposed to be absolute and each component of <tt>ePath</tt>, with the exception of the * rightmost one, should be a directory name or symbolic link name to a path. * * The process that calls the operation must have execution (x) permission on all the components of the path with * exception of the rightmost one. * * \param ePath pointer to the string holding the name of the path * \param p_nInodeDir pointer to the location where the number of the inode associated to the directory that holds the * entry is to be stored * (nothing is stored if \c NULL) * \param p_nInodeEnt pointer to the location where the number of the inode associated to the entry is to be stored * (nothing is stored if \c NULL) * * \return <tt>0 (zero)</tt>, on success * \return -\c EINVAL, if the pointer to the string is \c NULL or the path string does not describe an absolute path * \return -\c ENAMETOOLONG, if the path or any of the path components exceed the maximum allowed length * \return -\c ERELPATH, if the path is relative and it is not a symbolic link * \return -\c ENOTDIR, if any of the components of <tt>ePath</tt>, but the last one, is not a directory * \return -\c ELOOP, if the path resolves to more than one symbolic link * \return -\c ENOENT, if no entry with a name equal to any of the components of <tt>ePath</tt> is found * \return -\c EACCES, if the process that calls the operation has not execution permission on any of the components * of <tt>ePath</tt>, but the last one * \return -\c EDIRINVAL, if the directory is inconsistent * \return -\c EDEINVAL, if the directory entry is inconsistent * \return -\c EIUININVAL, if the inode in use is inconsistent * \return -\c ELDCININVAL, if the list of data cluster references belonging to an inode is inconsistent * \return -\c EDCINVAL, if the data cluster header is inconsistent * \return -\c ELIBBAD, if some kind of inconsistency was detected at some internal storage lower level * \return -<em>other specific error</em> issued by \e lseek system call */ int soGetDirEntryByPath (const char *ePath, uint32_t *p_nInodeDir, uint32_t *p_nInodeEnt) { soProbe (111, "soGetDirEntryByPath (\"%s\", %p, %p)\n", ePath, p_nInodeDir, p_nInodeEnt); printf("\nePath = %s\n", ePath); /** Variables **/ int error; char absPath[1]; char auxPath[MAX_PATH + 1]; char dirPath[MAX_PATH + 1]; char basePath[MAX_NAME + 1]; uint32_t nInodeDir; uint32_t nInodeEnt; SOSuperBlock *sb; /** Parameter check **/ if(ePath == NULL) return -EINVAL; /** Conformity check **/ if(strlen(ePath) > MAX_PATH + 1) return -ENAMETOOLONG; /** Check if ePath is an absolute path **/ absPath[0] = '/'; if(ePath[0] != absPath[0]) return -ERELPATH; /** Get basename and dirname of ePath **/ strcpy((char *)auxPath, ePath); strcpy(dirPath, dirname(auxPath)); strcpy((char *)auxPath, ePath); strcpy(basePath, basename(auxPath)); /** Loading SuperBlock **/ if((error = soLoadSuperBlock()) != 0) return error; if((sb = soGetSuperBlock()) == NULL) return -EBADF; /** Get parent directory inode number **/ if((error = soTraversePath(sb, dirPath, NULL, &nInodeDir)) != 0) return error; /** Get entry inode number **/ /*if((error = soGetDirEntryByName_bin(nInodeDir, basePath, &nInodeEnt, NULL)) != 0) return error;*/ /*Get entry inode number*/ if(strcmp(basePath, "/") != 0){ if((error = soGetDirEntryByName(nInodeDir, basePath, &nInodeEnt, NULL)) != 0) return error; } /*Entry directory of root direcrory is "."*/ else if((error = soGetDirEntryByName(nInodeDir, ".", &nInodeEnt, NULL)) != 0) return error; /** Update return values **/ if(p_nInodeDir != NULL) *p_nInodeDir = nInodeDir; if(p_nInodeEnt != NULL) *p_nInodeEnt = nInodeEnt; /** Operation successful **/ return 0; }
int soRenameDirEntry (uint32_t nInodeDir, const char *oldName, const char *newName) { soColorProbe (315, "07;31", "soRenameDirEntry (%"PRIu32", \"%s\", \"%s\")\n", nInodeDir, oldName, newName); SOSuperBlock *p_sb; SOInode inode; SODataClust dirClust; int size; int stat; uint32_t p_idx; //uint32_t p_nInodeEnt; // obter informação do superbloco if((stat=soLoadSuperBlock())!=0) { return stat; } // ponteiro para o superblock p_sb=soGetSuperBlock(); // verificação de validade do iNode if(nInodeDir>=p_sb->iTotal || nInodeDir < 0) { return -EINVAL; } if (oldName == NULL || newName == NULL) { return -EINVAL; } // check ao tamanho do nome antigo size = strlen(oldName); if(size > (MAX_NAME)) { return -ENAMETOOLONG; } // check ao tamanho do novo nome size = strlen(newName); if(size > (MAX_NAME)) { return -ENAMETOOLONG; } /* verificaçã odas string, estas nao podem conter '/' no seu conteudo char test; test=strchr(&newName,'/'); if(test != NULL) { return -EINVAL; } test=strchr(&oldName,'/'); { return -EINVAL } esta verificação e feita pela funçao pela soGetEntryByName */ // leitura do inode if ((stat=soReadInode(&inode,nInodeDir,IUIN))!=0) { return stat; } if((stat=soQCheckInodeIU(p_sb,&inode))!=0) { return stat; } // verificação de permissoes de execução if((stat=soAccessGranted(nInodeDir,X))!=0) { return -EACCES; } // verificação de permissoes de escrita if((stat=soAccessGranted(nInodeDir,W))!=0) { return -EPERM; } // verificação se o inodeDir e um directorio if((inode.mode & INODE_DIR)!= INODE_DIR) { return -ENOTDIR; } /*if((stat=soQCheckDirCont(p_sb,&inode))!=0) { return stat; } perror("antesQcheck");*/ //verificação se o novo nome a alterar existe if((stat=soGetDirEntryByName(nInodeDir,oldName,NULL,&p_idx))!= 0){ return stat; } if((stat=soGetDirEntryByName(nInodeDir,newName,NULL,NULL)) == 0){ return -EEXIST; } /*if(stat != 0) { return stat; }*/ /* vamos carregar o cluster que possui a entrada de directorio que pretendemos renomear*/ if((stat=soReadFileCluster(nInodeDir,p_idx/DPC, &dirClust))!=0) { return stat; } // copiar nova string para a entrada onde se encontrava o oldName //memcpy((char*)dirClust.info.de[p_idx%DPC].name,(char*)newName,MAX_NAME+1); int i = 0; for(i=0;i < MAX_NAME+1;i++) { dirClust.info.de[p_idx%DPC].name[i]=0; } strcpy((char*)dirClust.info.de[p_idx%DPC].name,(char*)newName); if((stat=soWriteFileCluster(nInodeDir,p_idx/DPC, &dirClust))!=0) { return stat; } return 0; }
/*Auxiliary function to traverse the parent directory(s)*/ static int soTraversePath(SOSuperBlock *p_sb, char *ePath, uint32_t *p_nInodeDir, uint32_t *p_nInodeEnt){ /** Variables **/ int error; int entryFound; char auxPath[MAX_PATH + 1]; char dirPath[MAX_PATH + 1]; char basePath[MAX_NAME + 1]; SOInode parentDirInode; uint32_t nInodeDir; uint32_t nInodeEnt; /** Get basename and dirname of ePath **/ strcpy((char *)auxPath, ePath); strcpy(dirPath, dirname(auxPath)); strcpy((char *)auxPath, ePath); strcpy(basePath, basename(auxPath)); entryFound = 0; /** Get current dir inode number **/ if(strcmp(dirPath, "/") == 0){ /*Parent directory is the ".." entry*/ if((error = soGetDirEntryByName(0, "..", &nInodeDir, NULL)) != 0) return error; /*Get entry inode number*/ if(strcmp(basePath, "/") != 0){ if((error = soGetDirEntryByName(0, basePath, &nInodeEnt, NULL)) != 0) return error; } /*Entry directory of root direcrory is "."*/ else if((error = soGetDirEntryByName(0, ".", &nInodeEnt, NULL)) != 0) return error; /*Update auxiliary variable*/ entryFound = 1; } else if((error = soTraversePath(p_sb, dirPath, NULL, &nInodeDir)) != 0) return error; /** Read Parent directory inode **/ if((error = soReadInode(&parentDirInode, nInodeDir, IUIN)) != 0) return error; /** Check if inode of parent directory indeed refers to a directory **/ if((parentDirInode.mode & INODE_DIR) != INODE_DIR) return -ENOTDIR; /** Check parent directory consistency **/ if((error = soQCheckDirCont(p_sb, &parentDirInode)) != 0) return error; /** Check execution permission on parent directory **/ if((error = soAccessGranted(nInodeDir, X)) != 0) return error; /** Get Entry inode number if needed**/ if(entryFound == 0){ if((error = soGetDirEntryByName(nInodeDir, basePath, &nInodeEnt, NULL)) != 0) return error; } /** Update return values **/ if(p_nInodeDir != NULL) *p_nInodeDir = nInodeDir; if(p_nInodeEnt != NULL) *p_nInodeEnt = nInodeEnt; /** Traverse successful **/ return 0; }