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) { 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 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; }