int soReadFileCluster (uint32_t nInode, uint32_t clustInd, SODataClust *buff) { soColorProbe (411, "07;31", "soReadFileCluster (%"PRIu32", %"PRIu32", %p)\n", nInode, clustInd, buff); int stat, i; SOSuperBlock *p_sb; SODataClust cluster; uint32_t numDC, nFClust; if( (stat = soLoadSuperBlock()) != 0){ return stat; } p_sb = soGetSuperBlock(); if(nInode >= p_sb->iTotal){ return -EINVAL; } if(buff == NULL){ return -EINVAL; } if(clustInd >= MAX_FILE_CLUSTERS){ return -EINVAL; } if((stat = soHandleFileCluster(nInode, clustInd, GET, &numDC)) != 0){ return stat; } if(numDC == NULL_CLUSTER){ for(i = 0; i < BSLPC; i++) { buff->info.data[i] = '\0'; } } else{ nFClust = p_sb->dZoneStart + numDC * BLOCKS_PER_CLUSTER; if( (stat = soReadCacheCluster(nFClust, &cluster)) != 0){ return stat; } memcpy(buff, &cluster, sizeof(SODataClust)); if((stat = soWriteCacheCluster(nFClust, &cluster)) != 0){ return stat; } } if( (stat = soStoreSuperBlock()) != 0){ return stat; } return 0; }
int soAllocInode (uint32_t type, uint32_t* p_nInode) { soProbe (411, "soAllocInode (%"PRIu32", %p)\n", type, p_nInode); /** Variables **/ int status; SOSuperBlock *sb; SOInode *headInode; SOInode *nextInode; uint32_t headBlock; uint32_t nextBlock; uint32_t headOffset; uint32_t nextOffset; uint32_t nInode; /** Parameter check **/ if((type != INODE_DIR) && (type != INODE_FILE) && (type != INODE_SYMLINK)) return -EINVAL; if(p_nInode == NULL) return -EINVAL; /** Loading SuperBlock **/ if((status = soLoadSuperBlock()) != 0) return status; if((sb = soGetSuperBlock()) == NULL) return -EBADF; /** Inode table consistency check **/ if((status = soQCheckInT(sb)) != 0) return status; /** Check if there are free inodes **/ if(sb->ifree == 0) return -ENOSPC; /** Obtain Block number and inode offset **/ if((status = soConvertRefInT(sb->ihead, &headBlock, &headOffset)) != 0) return status; /** Read head inode from inode table **/ if((status = soLoadBlockInT(headBlock)) != 0) return status; headInode = soGetBlockInT(); /** Check if inode is free **/ if((status = soQCheckFInode(&headInode[headOffset])) != 0) return status; /** Allocated inode number **/ nInode = sb->ihead; /**Update Superblock reference to head of double-linked list of free headInodes**/ if(sb->ifree == 1) { sb->ihead = NULL_INODE; sb->itail = NULL_INODE; } else sb->ihead = headInode[headOffset].vD1.next; /** Update next inode information **/ if(sb->ihead != NULL_INODE) { if((status = soConvertRefInT(sb->ihead, &nextBlock, &nextOffset)) != 0) return status; if((status = soLoadBlockInT(nextBlock)) != 0) return status; nextInode = soGetBlockInT(); nextInode[nextOffset].vD2.prev = NULL_INODE; if((status = soStoreBlockInT()) != 0) return status; } /** Update and write superblock **/ sb->ifree--; if((status = soStoreSuperBlock()) != 0) return status; /** "Re-Obtain" Block number and inode offset **/ if((status = soConvertRefInT(nInode, &headBlock, &headOffset)) != 0) return status; /** "Re-Read" head inode from inode table **/ if((status = soLoadBlockInT(headBlock)) != 0) return status; headInode = soGetBlockInT(); /** Check if headInode is in dirty state **/ if((status = soQCheckFCInode(&headInode[headOffset])) != 0) { if((status = soCleanInode(headBlock * IPB + headOffset)) != 0) return status; /*Since inode was updated, it will be readed again*/ if((status = soConvertRefInT(nInode, &headBlock, &headOffset)) != 0) return status; /*Read head inode from inode table*/ if((status = soLoadBlockInT(headBlock)) != 0) return status; headInode = soGetBlockInT(); } /** Allocate headInode **/ headInode[headOffset].mode = type; headInode[headOffset].refcount = 0; headInode[headOffset].owner = getuid(); headInode[headOffset].group = getgid(); headInode[headOffset].size = 0; headInode[headOffset].clucount = 0; headInode[headOffset].vD1.atime = time(NULL); headInode[headOffset].vD2.mtime = headInode[headOffset].vD1.atime; /*Write updated inode information to disk*/ if((status = soStoreBlockInT()) != 0) return status; /*Consistency check*/ if((status = soQCheckInodeIU(sb, &headInode[headOffset])) != 0) return status; /** Operation successful **/ *p_nInode = nInode; return 0; }
int soAllocDataCluster(uint32_t nInode, uint32_t *p_nClust) { soColorProbe(613, "07;33", "soAllocDataCluster (%"PRIu32", %p)\n", nInode, p_nClust); int stat; // variavel para o estado de erro //uint32_t nClust, clusterStat, NFClt; //variaveis para localizar o cluster, contem variavel extra usada no teste de consistencia do header do cluster SOSuperBlock *p_sb; //ponteiro para o superbloco SODataClust cluster; //ponteiro para o cluster que vai ser reservado SOInode *p_inode; uint32_t nBlock, offset, nClust, clusterStat, NFClt; //carregar o super bloco if ((stat = soLoadSuperBlock()) != 0) return stat; p_sb = soGetSuperBlock(); //if ((stat = soQCheckSuperBlock(p_sb)) != 0) // return stat; if ((stat = soQCheckDZ(p_sb)) != 0) return stat; //carregar inode pretendido if ((stat = soConvertRefInT(nInode, &nBlock, &offset)) != 0) return stat; if ((stat = soLoadBlockInT(nBlock)) != 0) return stat; p_inode = soGetBlockInT(); //teste de consistencia ao inode if ((stat = soQCheckInodeIU(p_sb, &p_inode[offset])) != 0) return stat; //guardar o inode so precisavamos de testar a consistencia if ((stat = soStoreBlockInT()) != 0) return stat; //teste se o inode pretendido de encontra dentro dos valores possiveis e se o ponteiro nao vem com NULL_CLUSTER associado if (nInode > p_sb->iTotal - 1 || p_nClust == NULL) return -EINVAL; //verificar se ha clusters livres if (p_sb->dZoneFree == 0) return -ENOSPC; //se a cache estiver vazia, enche-la if (p_sb->dZoneRetriev.cacheIdx == DZONE_CACHE_SIZE) soReplenish(p_sb); //carregar o super bloco if ((stat = soLoadSuperBlock()) != 0) return stat; p_sb = soGetSuperBlock(); //nclust = numero logico do cluster nClust = p_sb->dZoneRetriev.cache[p_sb->dZoneRetriev.cacheIdx]; // passar o numero do proximo cluster livre para nClust //teste de consistencia ao proximo cluster a reservar if ((stat = soQCheckStatDC(p_sb, nClust, &clusterStat)) != 0) return stat; //ir buscar o cluster nClust. nClust precisa de ser o numero fisico //relação entre numero fisico e numero logico //NFClt = dzone_start + NLClt * BLOCKS_PER_CLUSTER; NFClt = p_sb->dZoneStart + nClust * BLOCKS_PER_CLUSTER; if ((stat = soReadCacheCluster(NFClt, &cluster)) != 0) return stat; // codigo deste if, vem do pdf "manipulacao do cluster de dados", slide 23 // check if the data cluster is dirty if (cluster.stat != NULL_INODE) { if ((stat = soCleanDataCluster(cluster.stat, nClust)) != 0) return stat; } p_sb->dZoneRetriev.cache[p_sb->dZoneRetriev.cacheIdx] = NULL_CLUSTER; //esse cluster já nao vai estar disponivel, por isso NULL_CLUSTER p_sb->dZoneRetriev.cacheIdx += 1; p_sb->dZoneFree -= 1; cluster.prev = cluster.next = NULL_CLUSTER; cluster.stat = nInode; //atribuir o numero do cluster ao ponteiro fornecido nos argumentos para esse efeito *p_nClust = nClust; //voltar a guardar o cluster if ((stat = soWriteCacheCluster(NFClt, &cluster)) != 0) return stat; //voltar a guardar o super bloco if ((stat = soStoreSuperBlock()) != 0) return stat; return 0; }
int soAllocInode (uint32_t type, uint32_t* p_nInode) { soColorProbe (611, "07;31", "soAllocInode (%"PRIu32", %p)\n", type, p_nInode); SOInode *array; SOSuperBlock *p_sb; uint32_t numBlock, offset, next; int status, i; // Se o type não existe ou ponteiro p_nInode é nulo if((type != INODE_DIR && type != INODE_FILE && type != INODE_SYMLINK) || p_nInode == NULL) return -EINVAL; // Superbloco na memória if((status = soLoadSuperBlock()) != 0) return status; // Ponteiro do superbloco if (!(p_sb = soGetSuperBlock())) return -EIO; // Tem de haver pelo menos um nó livre na lista de nós livres if(p_sb->ifree == 0) { return -ENOSPC; } // Verifica se a tabela de inodes esta consistente if ((status = soQCheckSuperBlock(p_sb)) != 0) { return status; } *p_nInode = p_sb->ihead; // Obter nº bloco e o offset do inode if ((status = soConvertRefInT(p_sb->ihead, &numBlock, &offset))) { return status; } // Ler o bloco do primeiro nó livre if ((status = soLoadBlockInT(numBlock))) { return status; } array = soGetBlockInT(); next = array[offset].vD2.next; // Preenchimento array[offset].mode = type | 0x0; array[offset].refcount = 0; array[offset].owner = getuid(); array[offset].group = getgid(); array[offset].size = 0; array[offset].clucount = 0; for (i = 0; i < N_DIRECT; i++) { array[offset].d[i] = NULL_CLUSTER; } array[offset].i1 = NULL_CLUSTER; array[offset].i2 = NULL_CLUSTER; array[offset].vD1.atime = time(NULL); array[offset].vD2.mtime = time(NULL); // Algoritmo if (p_sb->ifree == 1) { // A lista só tem um elemento p_sb->ihead = NULL_INODE; p_sb->itail = NULL_INODE; if ((status = soStoreBlockInT()) != 0) { return status; } } else{ // A lista tem dois ou mais elementos // Actualiza ihead do bloco p_sb->ihead = next; // Guarda o inode if ((status = soStoreBlockInT()) != 0) { return status; } // Nº Bloco e Offset inode head if ((status = soConvertRefInT (next, &numBlock, &offset)) != 0) { return status; } // Como a lista não está vazia, vamos alterar o ihead if ((status = soLoadBlockInT(numBlock)) != 0) { return status; } array = soGetBlockInT(); array[offset].vD1.prev = NULL_INODE; // Guarda o inode if ((status = soStoreBlockInT()) != 0) { return status; } } // Decrementa o numero de free inodes p_sb->ifree--; // Guarda inode if ((status = soStoreSuperBlock()) != 0) { return status; } return 0; }
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 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 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; }
/** * \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 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; }