int soGetDirEntryByName (uint32_t nInodeDir, const char *eName, uint32_t *p_nInodeEnt, uint32_t *p_idx) { soColorProbe (312, "07;31", "soGetDirEntryByName (%"PRIu32", \"%s\", %p, %p)\n", nInodeDir, eName, p_nInodeEnt, p_idx); SOSuperBlock *p_sb; SOInode p_Inode; SODataClust clustDir; // Variavel usada para retorno de erros uint32_t status; int i, j; if((status = soLoadSuperBlock())!= 0){ return status; } p_sb = soGetSuperBlock(); if(nInodeDir >= p_sb->iTotal){ return -EINVAL; } // Verificação se o campo eName é igual a NULL ou esta vazio if(eName == NULL || (strlen(eName))==0){ return -EINVAL; } // Verifica se a string nome excede o comprimento máximo if(strlen(eName) > MAX_NAME){ return -ENAMETOOLONG; } // Verifica se a string é um nome de um ficheiro e não um caminho for(i=0; eName[i]!='\0';i++) { if(eName[i] == '/') return -EINVAL; } // Le o inode. Verifica se está em uso if((status = soReadInode(&p_Inode,nInodeDir,IUIN))){ return status; } // Verifica se o nó-i é do tipo diretório if((p_Inode.mode & INODE_TYPE_MASK) != INODE_DIR){ return -ENOTDIR; } if((status = soQCheckDirCont(p_sb,&p_Inode))!=0){ return status; } // Verifica se existe permissão de execução if((status = soAccessGranted(nInodeDir,X))!=0){ return status; } // Numero de entradas de directorio uint32_t numRefMax = p_Inode.size/(DPC*sizeof(SODirEntry)); for (i = 0; i < numRefMax; i++){ //Le o conteudo do cluster referenciado pelo inode if((status = soReadFileCluster(nInodeDir,i,&clustDir))){ return status; } // Procura pelo nome, verificando todas as entradas de directorio for (j = 0; j < DPC; j++){ if (strcmp((char*)(clustDir.info.de[j].name),eName)==0){ // Se o argumento é diferente de NULL retorna o inode referenciado pelo nome if(p_nInodeEnt != NULL){ *p_nInodeEnt = (clustDir.info.de[j].nInode); } if(p_idx != NULL){ *p_idx =((i*DPC)+j); } return 0; } // Verifica se a entrada j esta free if((clustDir.info.de[j].name[0] == '\0') && (clustDir.info.de[j].name[MAX_NAME] == '\0')){ if(p_idx != NULL){ *p_idx = ((i*DPC)+j); } return -ENOENT; } } } // Se nao existir entradas free if(p_idx != NULL){ *p_idx = (p_Inode.cluCount)*DPC; } return -ENOENT; }
int soRead (const char *ePath, void *buff, uint32_t count, int32_t pos) { soColorProbe (229, "07;31", "soRead (\"%s\", %p, %u, %u)\n", ePath, buff, count, pos); int stat; // variavel para o estado SOSuperBlock *p_sb; // ponteiro para o super bloco SOInode p_inode; // pointer to inode table for nBlk block position uint32_t p_nInodeEnt; // ponteiro para a localizacao onde o nº do nó I associado à entrada é armazenado uint32_t offset; // numero do offset () uint32_t p_clustInd; // ponteiro para indice do cluster uint32_t p_clustIndF; // ponteiro para indice do cluster final uint32_t offsetFinal; // offset final int bytesRead = 0; // variável para indicar o numero de bytes lidos em sucesso SODataClust p_buff; // ponteiro para o buffer /*------VALIDATIONS----------*/ /* carregar super bloco*/ if( (stat = soLoadSuperBlock()) != 0) return stat; /* obter super bloco*/ p_sb = soGetSuperBlock(); /* if the pointer to the string is null */ if(ePath == NULL) return -EINVAL; /* if the path does not describe a absolute path*/ if(ePath[0] != '/') return -EINVAL; /*if the path name or any of its components exceed the maximum allowed length*/ if(strlen(ePath) > MAX_PATH) return -ENAMETOOLONG; /* Obter o Inode associado ao ePath e verificar se há erros */ if( (stat = soGetDirEntryByPath(ePath, NULL, &p_nInodeEnt)) != 0) return stat; /* Ler e verificar o inode (tem que ser um ficheiro regular) */ if( (stat = soReadInode(&p_inode, p_nInodeEnt, IUIN)) != 0) return stat; /*verificar se ePath descreve um directorio*/ if( (stat = soQCheckDirCont(p_sb, &p_inode)) != 0) return -EISDIR; /*if any of the components of ePath, but the last one, is not a directory*/ if( (stat != -ENOTDIR)) return stat; /*verificar se o processo tem permissão de execucção*/ if( (stat = soAccessGranted(p_nInodeEnt, X)) != 0) return -EACCES; /*verificar se o processo tem permissao de leitura*/ if( (stat = soAccessGranted(p_nInodeEnt, R)) != 0) return -EPERM; /*if the starting [byte] position in the file data continuum assumes a value passing its maximum size*/ /*Verifica se o pos está fora do ficheiro*/ if(pos > p_inode.size) return -EFBIG; /*------END OF VALIDATIONS-------*/ /* Corrige o count se pos+count ultrapassar o limite do ficheiro */ if((pos + count) > p_inode.size) count = p_inode.size - pos; /* vai obter o clustInd e offset apartir do pos */ if( (stat = soConvertBPIDC(pos, &p_clustInd, &offset)) != 0) return stat; // byte position é definido como : // pos = clustInd * BSLPC + offset /* vai obter o clustInd e offset do final do ficheiro apartir do pos + count */ if( (stat = soConvertBPIDC(pos + count, &p_clustIndF, &offsetFinal)) != 0) return stat; /* leitura do 1º cluster do inode*/ if( (stat = soReadFileCluster(p_nInodeEnt, p_clustInd, &p_buff)) != 0) return stat; /* Se for necessario ler um pedaço do mesmo cluster */ if(p_clustInd == p_clustIndF) { memcpy(buff, &p_buff.info.data[BSLPC] + offset, (offsetFinal - offset)); bytesRead = offsetFinal - offset; return bytesRead; } /*Se for para ler mais que 1 cluster, ler o resto do primeiro */ memcpy(buff, &p_buff.info.data[BSLPC] + offset, (BSLPC - offset)); bytesRead = BSLPC - offset; p_clustInd++; // incrementa o indice do cluster /* ler proximo cluster*/ if( (stat = soReadFileCluster(p_nInodeEnt, p_clustInd, &p_buff)) != 0) return stat; /* ler clusters "intermédios" */ while(p_clustInd < p_clustIndF) { memcpy(buff+bytesRead, &p_buff.info.data[BSLPC], BSLPC); bytesRead += BSLPC; /*ler proximo cluster */ if( (stat = soReadFileCluster(p_nInodeEnt, p_clustInd, &p_buff)) != 0) return stat; } /* caso o que cluster que vamos ler é o ultimo*/ memcpy(buff + bytesRead, &p_buff.info.data[BSLPC], offsetFinal); bytesRead += offsetFinal; return bytesRead; }
int soHandleFileCluster(uint32_t nInode, uint32_t clustInd, uint32_t op, uint32_t *p_outVal) { soColorProbe(413, "07;31", "soHandleFileCluster (%"PRIu32", %"PRIu32", %"PRIu32", %p)\n", nInode, clustInd, op, p_outVal); int stat; // function return stat control SOSuperBlock *p_sb; // pointer to the superblock SOInode inode; // inode to fill with soReadInode if ((stat = soLoadSuperBlock())) return stat; p_sb = soGetSuperBlock(); /* START OF VALIDATION */ /* if nInode is out of range */ if (nInode >= p_sb->iTotal) return -EINVAL; /* index (clustInd) to the list of direct references are out of range */ if (clustInd >= MAX_FILE_CLUSTERS) return -EINVAL; /* requested operation is invalid */ if (op > 4) return -EINVAL; /* the pointer p_outVal is NULL when it should not be (GET / ALLOC) */ if ((op == GET || op == ALLOC) && p_outVal == NULL) return -EINVAL; if (op == CLEAN) { // if operation is CLEAN, readInode as Free in Dirty State if ((stat = soReadInode(&inode, nInode, FDIN)) != 0) return stat; } else { // for all other operations read inode as inode in use if ((stat = soReadInode(&inode, nInode, IUIN)) != 0) return stat; } /* END OF VALIDATION */ if (clustInd < N_DIRECT) { // flow trough direct references if ((stat = soHandleDirect(p_sb, nInode, &inode, clustInd, op, p_outVal)) != 0) return stat; } else if (clustInd < N_DIRECT + RPC) { // flow trough single indirect references if ((stat = soHandleSIndirect(p_sb, nInode, &inode, clustInd, op, p_outVal)) != 0) return stat; } else { // flow trough double indirect references if ((stat = soHandleDIndirect(p_sb, nInode, &inode, clustInd, op, p_outVal)) != 0) return stat; } //printf("clucountPrincipal = %u\n", inode.cluCount); if (op == CLEAN) { if ((stat = soWriteInode(&inode, nInode, FDIN)) != 0) return stat; } else if (op != GET) { if ((stat = soWriteInode(&inode, nInode, IUIN)) != 0) return stat; } 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; }
int soHandleFileClusters (uint32_t nInode, uint32_t clustIndIn, uint32_t op) { soColorProbe (414, "07;31", "soHandleFileClusters (%"PRIu32", %"PRIu32", %"PRIu32")\n", nInode, clustIndIn, op); SOSuperBlock* p_sb; SOInode inode; SODataClust *clust1, *clust2; uint32_t stat, ind, ref_offset, ref_Soffset, ref_Doffset; if((stat = soLoadSuperBlock())){ return stat; } p_sb = soGetSuperBlock(); if(nInode < 0 || nInode >= p_sb->iTotal){ return -EINVAL; } if(clustIndIn >= MAX_FILE_CLUSTERS){ return -EINVAL; } if(op < 2 || op > 4){ return -EINVAL; } if(op == CLEAN){ if ((stat=soReadInode(&inode,nInode,FDIN))!=0){ return stat; } }else{ if ((stat=soReadInode(&inode,nInode,IUIN))!=0){ return stat; } } /*Referencas Duplamente Indirectas*/ if(inode.i2 != NULL_CLUSTER){ if ((stat = soLoadSngIndRefClust((inode.i2 * BLOCKS_PER_CLUSTER) + p_sb->dZoneStart)) != 0){ return stat; } clust2 = soGetSngIndRefClust(); ind = N_DIRECT + RPC; //tamanho da tabela das referencias simplesmentre indirectas for(;inode.i2 != NULL_CLUSTER && ind < MAX_FILE_CLUSTERS;){ ref_Soffset = (ind - (RPC + N_DIRECT)) / RPC; ref_Doffset = (ind - N_DIRECT - RPC) % RPC; if(clust2->info.ref[ref_Soffset] != NULL_CLUSTER){ if((stat = soLoadDirRefClust((clust2->info.ref[ref_Soffset]* BLOCKS_PER_CLUSTER) + p_sb->dZoneStart)) != 0){ return stat; } clust1 = soGetDirRefClust(); for(; ref_Doffset < RPC; ref_Doffset++, ind++){ if(clust1->info.ref[ref_Doffset] != NULL_CLUSTER && clustIndIn <= ind){ if((stat = soHandleFileCluster(nInode, ind, op, NULL)) != 0){ return stat; } } } }else{ ind += RPC; } } } /*Referencias Simplesmente Indirectas*/ if(inode.i1 != NULL_CLUSTER){ if((stat = soLoadDirRefClust((inode.i1 * BLOCKS_PER_CLUSTER) + p_sb->dZoneStart)) != 0){ return stat; } clust1 = soGetDirRefClust(); ind = N_DIRECT; for(; inode.i1 != NULL_CLUSTER && ind < N_DIRECT + RPC;ind++){ ref_offset = ind - N_DIRECT; if(clust1->info.ref[ref_offset] != NULL_CLUSTER && clustIndIn <= ind){ if((stat = soHandleFileCluster(nInode, ind, op, NULL)) != 0 ){ return stat; } } } } /*Referencias Directas*/ ind = 0; for(; ind < N_DIRECT; ind++){ if(inode.d[ind] != NULL_CLUSTER && clustIndIn <= ind){ if((stat = soHandleFileCluster(nInode, ind, op, NULL)) != 0){ return stat; } } } return 0; }
int soCleanDataCluster (uint32_t nInode, uint32_t nLClust) { soColorProbe (415, "07;31", "soCleanDataCluster (%"PRIu32", %"PRIu32")\n", nInode, nLClust); int stat, i, j; // stat = error stat of the function; i= auxiliary variable for iterations SOSuperBlock *p_sb; // pointer to the super block SOInode inode; // inode instance to clean the references uint32_t clusterCount = 0; // physical number of the cluster SODataClust *p_clusterS, *p_clusterD; // cluster pointers to direct and indirect references // Load the super block if((stat = soLoadSuperBlock()) != 0) return stat; //get pointer to the super block p_sb = soGetSuperBlock(); //check if inode is in the allowed parameters if(nInode >= p_sb->iTotal) return -EINVAL; //check if nLClust is in allowed parameters if (!(nLClust > 0 && nLClust < p_sb->dZoneTotal)) return -EINVAL; //read nInode data into inode if((stat = soReadInode(&inode, nInode, FDIN)) != 0) return stat; //Direct References for(i = 0; i < N_DIRECT; i++){ if(inode.d[i] != NULL_CLUSTER){ if(inode.d[i] == nLClust){ //if cluster is in d[i] clean it if((stat = soHandleFileCluster(nInode, i, CLEAN, NULL)) != 0) return stat; return 0; } else clusterCount++; } //if we parsed all the clusters in the inode and it's not found if(clusterCount == inode.cluCount) return -EDCINVAL; } //Direct References Cluster //if nLClust is i1 if(inode.i1 == nLClust){ if ((stat = soLoadDirRefClust(p_sb->dZoneStart + inode.i1 * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterS = soGetDirRefClust(); //clean all references in i1 for(i = 0; i < RPC; i++){ if(p_clusterS->info.ref[i-N_DIRECT] != NULL_CLUSTER){ if((stat = soHandleFileCluster(nInode, i + N_DIRECT, CLEAN, NULL)) != 0) return stat; } } return 0; } //if nLClust is not i1 it can be any of the RPC else{ if((stat = soLoadDirRefClust(p_sb->dZoneStart + inode.i1 * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterS = soGetDirRefClust(); for(i = 0; i < RPC; i++){ if(p_clusterS->info.ref[i] != NULL_CLUSTER){ //if nLCuster is found clean it if(p_clusterS->info.ref[i] == nLClust){ if((stat = soHandleFileCluster(nInode, i + N_DIRECT, CLEAN, NULL)) != 0) return stat; return 0; } else clusterCount++; } //if we parsed all the clusters in the inode and it's not found if(clusterCount == inode.cluCount) return -EDCINVAL; } } //Referencias duplamente indirectas //if nLClust is i2 if(inode.i2 == nLClust){ if ((stat = soLoadSngIndRefClust(p_sb->dZoneStart + inode.i2 * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterS = soGetSngIndRefClust(); //clean all clusters in indirect and direct references for(i = 0; i < RPC; i++){ if(p_clusterS->info.ref[i] != NULL_CLUSTER){ if ((stat = soLoadDirRefClust(p_sb->dZoneStart + p_clusterS->info.ref[i] * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterD = soGetDirRefClust(); for(j = 0; j < RPC; j++){ if(p_clusterD->info.ref[j] != NULL_CLUSTER) if((stat = soHandleFileCluster(nInode, N_DIRECT + (RPC*(i+1)) + j, CLEAN, NULL)) != 0) return stat; } } } return 0; } //if nLClust is not i2 else{ if ((stat = soLoadSngIndRefClust(p_sb->dZoneStart + inode.i2 * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterS = soGetSngIndRefClust(); //parse i2 references for(i = 0; i < RPC; i++){ if(p_clusterS->info.ref[i] != NULL_CLUSTER){ //if nLClust is in direct references if(p_clusterS->info.ref[i] == nLClust){ if ((stat = soLoadDirRefClust(p_sb->dZoneStart + p_clusterS->info.ref[i] * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterD = soGetDirRefClust(); //clean all indirect references for the direct reference entry for(j = 0; j < RPC; j++){ if(p_clusterD->info.ref[j] != NULL_CLUSTER) if((stat = soHandleFileCluster(nInode, N_DIRECT + (RPC*(i+1)) + j, CLEAN, NULL)) != 0) return stat; } } //if it's not in the direct references, let's look in all the indirect else{ if ((stat = soLoadDirRefClust(p_sb->dZoneStart + p_clusterS->info.ref[i] * BLOCKS_PER_CLUSTER)) != 0) return stat; p_clusterD = soGetDirRefClust(); //search all the indirect references for each of the direct references for(j = 0; j < RPC; j++){ if(p_clusterD->info.ref[j] != NULL_CLUSTER){ //if nLCluster is found clean it if(p_clusterD->info.ref[j] == nLClust){ if((stat = soHandleFileCluster(nInode, N_DIRECT + (RPC*(i+1)) + j, CLEAN, NULL)) != 0) return stat; return 0; } else clusterCount++; } if(clusterCount == inode.cluCount) return -EDCINVAL; } clusterCount++; } //if we parsed all the clusters in the inode and it's not found if(clusterCount == inode.cluCount) return -EDCINVAL; } } } return 0; }