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;
}
Exemple #3
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;
    }
Exemple #5
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;
}
Exemple #11
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;
}