Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
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;

}