static int sofs_open (const char *ePath, struct fuse_file_info *fi) { soColorProbe (126, "07;31", "sofs_open_bin (\"%s\", %p)\n", ePath, fi); int stat; if (pthread_mutex_lock (&accessCR) != 0) /* enter critical region */ return -ENOLCK; stat = soOpen (ePath, fi->flags); fi->fh = (uint64_t) 0; if (pthread_mutex_unlock (&accessCR) != 0) /* exit critical region */ return -ENOLCK; return stat; }
static int sofs_read (const char *ePath, char *buff, size_t count, off_t pos, struct fuse_file_info *fi) { soColorProbe (127, "07;31", "sofs_read_bin (\"%s\", %p, %"PRIu32", %"PRId32", %p)\n", ePath, buff, (uint32_t) count, (int32_t) pos, fi); int stat; if (pthread_mutex_lock (&accessCR) != 0) /* enter critical region */ return -ENOLCK; stat = soRead (ePath, buff, (uint32_t) count, (int32_t) pos); if (pthread_mutex_unlock (&accessCR) != 0) /* exit critical region */ return -ENOLCK; return stat; }
static int sofs_chown (const char *ePath, uid_t owner, gid_t group) { soColorProbe (122, "07;31", "sofs_chown_bin (\"%s\", %"PRIu32", %"PRIu32")\n", ePath, (uint32_t) owner, (uint32_t) group); int stat; if (pthread_mutex_lock (&accessCR) != 0) /* enter critical region */ return -ENOLCK; stat = soChown (ePath, owner, group); if (pthread_mutex_unlock (&accessCR) != 0) /* exit critical region */ return -ENOLCK; return stat; }
static int sofs_readdir (const char *ePath, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { soColorProbe (133, "07;31", "sofs_readdir_bin (\"%s\", %p, %p, %"PRId32", %p)\n", ePath, buf, filler, (int32_t)offset, fi); char name[MAX_NAME+1]; int stat; if (pthread_mutex_lock (&accessCR) != 0) /* enter critical region */ return -ENOLCK; stat = soReaddir (ePath, name, (int32_t) offset); if (stat > 0) { offset += stat; stat = filler (buf, name, NULL, offset); } if (pthread_mutex_unlock (&accessCR) != 0) /* exit critical region */ return -ENOLCK; return stat; }
static int sofs_write (const char *ePath, const char *buff, size_t count, off_t pos, struct fuse_file_info *fi) { soColorProbe (128, "07;31", "sofs_write_bin (\"%s\", %p, %"PRIu32", %"PRId32", %p)\n", ePath, buff, (uint32_t) count, (int32_t) pos, fi); int i; int stat; char *b; if (pthread_mutex_lock (&accessCR) != 0) /* enter critical region */ return -ENOLCK; b = malloc (count); for (i = 0; i < count; i++) b[i] = buff[i]; stat = soWrite (ePath, (void *) b, (uint32_t) count, (int32_t) pos); free (b); if (pthread_mutex_unlock (&accessCR) != 0) /* exit critical region */ return -ENOLCK; return stat; }
static int sofs_flush (const char *ePath, struct fuse_file_info *fi) { soColorProbe(129, "07;31", "sofs_flush_bin (\"%s\", %p)\n", ePath, fi); 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 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; }
static int sofs_listxattr (const char *ePath, char *list, size_t size) { soColorProbe (140, "07;31", "sofs_listxattr_bin (\"%s\", \"%s\", %"PRIu32")\n", ePath, list, (uint32_t) size); return -ENOSYS; }
static int sofs_getxattr (const char *ePath, const char *name, char *value, size_t size) { soColorProbe (139, "07;31", "sofs_getxattr_bin (\"%s\", \"%s\", %p, %"PRIu32")\n", ePath, name, value, (uint32_t) size); return -ENOSYS; }
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; }
int sofs_removexattr (const char *ePath, const char *name) { soColorProbe (141, "07;31", "sofs_removexattr_bin (\"%s\", \"%s\")\n", ePath, name); return -ENOSYS; }
static int sofs_fsyncdir (const char *ePath, int isdatasync, struct fuse_file_info *fi) { soColorProbe (135, "07;31", "sofs_fsyncdir_bin (\"%s\", %d, %p)\n", ePath, isdatasync, fi); return soFsync (ePath); }
static int sofs_getdir (const char *ePath, fuse_dirh_t handle, fuse_dirfil_t filler) { soColorProbe (142, "07;31", "sofs_getdir_bin (\"%s\", ...)\n", ePath); return -ENOSYS; }
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 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; }