Skip to content
Open
155 changes: 117 additions & 38 deletions Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
// SINTA-SE LIVRE PARA ALTERAR A CLASSE MAIN
public class Main {

// Constantes úteis para a versão interativa.
// Para esse tipo de execução, o tamanho max do buffer de
// Constantes úteis para a versão interativa.
// Para esse tipo de execução, o tamanho max do buffer de
// leitura pode ser menor.
private static final String ROOT_USER = "root";
private static final String ROOT_DIR = "/";
Expand All @@ -29,27 +29,31 @@ public class Main {
// Usuário que está executando o programa
private static String user;

// O sistema de arquivos é inteiramente virtual, ou seja, será reiniciado a cada execução do programa.
// Logo, não é necessário salvar os arquivos em disco. O sistema será uma simulação em memória.
// O sistema de arquivos é inteiramente virtual, ou seja, será reiniciado a cada
// execução do programa.
// Logo, não é necessário salvar os arquivos em disco. O sistema será uma
// simulação em memória.
public static void main(String[] args) {
// Usuário que está executando o programa.
// Para quaisquer operações que serão feitas por esse usuário em um caminho /path/**,
// Para quaisquer operações que serão feitas por esse usuário em um caminho
// /path/**,
// deve-se checar se o usuário tem permissão de escrita (r) neste caminho.
if (args.length < 2) {
System.out.println("Usuário não fornecido");
return;
}
user = args[1];

// Carrega a lista de usuários do sistema a partir de arquivo
// Formato do arquivo users:
// username dir permission
// username dir permission
// Exemplo:
// maria /** rw-
// luzia /** rwx
// maria /** rw-
// luzia /** rwx
// Essa permissão vale para o diretório raiz e sub diretórios.
// A partir do momento que um usuário cria outro diretório ou arquivo,
// a permissão desse usuário é de leitura, escrita e execução nesse novo diretório/arquivo,
// A partir do momento que um usuário cria outro diretório ou arquivo,
// a permissão desse usuário é de leitura, escrita e execução nesse novo
// diretório/arquivo,
// e sempre será rwx para o usuário root.
try {
Scanner userScanner = new Scanner(new java.io.File("users/users"));
Expand All @@ -61,13 +65,15 @@ public static void main(String[] args) {
String userListed = parts[0];
String dir = parts[1];
String dirPermission = parts[2];

/* A FAZER:
* Processar a permissão de todos os usuários existentes por diretório.
* Por enquanto esse código somente imprime as permissões contidas no arquivo users.
*/
System.out.println(userListed + " " + dir + " " + dirPermission); // Somente imprime o usuário, diretório e permissão

/*
* A FAZER:
* Processar a permissão de todos os usuários existentes por diretório.
* Por enquanto esse código somente imprime as permissões contidas no arquivo
* users.
*/
System.out.println(userListed + " " + dir + " " + dirPermission); // Somente imprime o usuário,
// diretório e permissão

} else {
System.out.println("Formato ruim no arquivo de usuários. Linha: " + line);
Expand All @@ -80,19 +86,86 @@ public static void main(String[] args) {

return;
}

// Finalmente cria o Sistema de Arquivos
// Lista de usuários é imutável durante a execução do programa
// Obs: Como passar a lista de usuários para o FileSystem?
fileSystem = new FileSystem(/*usuários?*/);
fileSystem = new FileSystem(/* usuários? */);

fileSystem.addUser(user);

// Adicionar usuários do arquivo users ao sistema
try {
Scanner userScanner = new Scanner(new java.io.File("users/users"));
while (userScanner.hasNextLine()) {
String line = userScanner.nextLine().trim();
if (!line.isEmpty()) {
String[] parts = line.split(" ");
if (parts.length == 3) {
String userListed = parts[0];
String dir = parts[1];
String dirPermission = parts[2];

fileSystem.addUser(userListed);

// // DESCOMENTE O BLOCO ABAIXO PARA CRIAR O DIRETÓRIO RAIZ ANTES DE RODAR O MENU
// // Cria o diretório raiz do sistema. Root sempre tem permissão total "rwx"
// try {
// fileSystem.mkdir(ROOT_DIR, ROOT_USER);
// } catch (CaminhoJaExistenteException | PermissaoException e) {
// System.out.println(e.getMessage());
// }
if (dir.equals("/**")) {
try {
fileSystem.chmod("/", ROOT_USER, userListed, dirPermission);
} catch (Exception e) {
System.out.println(
"Erro ao definir permissão para " + userListed + ": " + e.getMessage());
}
}

System.out.println(userListed + " " + dir + " " + dirPermission);
} else {
System.out.println("Formato ruim no arquivo de usuários. Linha: " + line);
}
}
}
userScanner.close();
} catch (FileNotFoundException e) {
System.out.println("Arquivo de usuários não encontrado");
return;
}

// // DESCOMENTE O BLOCO ABAIXO PARA CRIAR O DIRETÓRIO RAIZ ANTES DE RODAR O
// MENU
// Cria o diretório raiz do sistema. Root sempre tem permissão total "rwx"
try {
fileSystem.mkdir(ROOT_DIR, ROOT_USER);
} catch (CaminhoJaExistenteException | PermissaoException e) {
System.out.println(e.getMessage());
}

// Configurar permissões para os usuários
try {
Scanner userScanner = new Scanner(new java.io.File("users/users"));
while (userScanner.hasNextLine()) {
String line = userScanner.nextLine().trim();
if (!line.isEmpty()) {
String[] parts = line.split(" ");
if (parts.length == 3) {
String userListed = parts[0];
String dir = parts[1];
String dirPermission = parts[2];

if (dir.equals("/**")) {
try {
fileSystem.chmod("/", ROOT_USER, userListed, dirPermission);
} catch (Exception e) {
System.out.println(
"Erro ao definir permissão para " + userListed + ": " + e.getMessage());
}
}
}
}
}
userScanner.close();
} catch (FileNotFoundException e) {
System.out.println("Arquivo de usuários não encontrado");
return;
}

// Menu interativo.
menu();
Expand Down Expand Up @@ -152,9 +225,14 @@ public static void menu() {
return;
default:
System.out.println("Comando inválido!");
}
}
} catch (CaminhoNaoEncontradoException | CaminhoJaExistenteException | PermissaoException e) {
System.out.println("Erro: " + e.getMessage());
} catch (IllegalArgumentException e) {
System.out.println("Erro de argumento: " + e.getMessage());
} catch (Exception e) {
System.out.println("Erro inesperado: " + e.getMessage());
e.printStackTrace();
}

System.out.println("Pressione Enter para continuar...");
Expand All @@ -171,14 +249,14 @@ public static void chmod() throws CaminhoNaoEncontradoException, PermissaoExcept
String usuarioAlvo = scanner.nextLine();
System.out.println("Insira a permissão (formato: 3 caracteres\"rwx\"):");
String permissoes = scanner.nextLine();

fileSystem.chmod(caminho, user, usuarioAlvo, permissoes);
}

public static void mkdir() throws CaminhoJaExistenteException, PermissaoException {
System.out.println("Insira o caminho do diretório a ser criado:");
String caminho = scanner.nextLine();

fileSystem.mkdir(caminho, user);
}

Expand All @@ -187,14 +265,14 @@ public static void rm() throws CaminhoNaoEncontradoException, PermissaoException
String caminho = scanner.nextLine();
System.out.println("Remover recursivamente? (true/false):");
boolean recursivo = Boolean.parseBoolean(scanner.nextLine());

fileSystem.rm(caminho, user, recursivo);
}

public static void touch() throws CaminhoJaExistenteException, PermissaoException {
System.out.println("Insira o caminho do arquivo a ser criado:");
String caminho = scanner.nextLine();

fileSystem.touch(caminho, user);
}

Expand All @@ -206,24 +284,25 @@ public static void write() throws CaminhoNaoEncontradoException, PermissaoExcept
System.out.println("Insira o conteúdo a ser escrito:");
String content = scanner.nextLine();
byte[] buffer = content.getBytes();

fileSystem.write(caminho, user, anexar, buffer);
}

public static void read() throws CaminhoNaoEncontradoException, PermissaoException {
System.out.println("Insira o caminho do arquivo a ser lido:");
String caminho = scanner.nextLine();
byte[] buffer = new byte[READ_BUFFER_SIZE]; // Exemplo de tamanho de buffer por load/leitura . O que acontece se o Buffer for menor que o conteúdo a ser lido?

fileSystem.read(caminho, user, buffer); // Lógica para ler arquivos maiores que o buffer deve ser implementada.
byte[] buffer = new byte[READ_BUFFER_SIZE]; // Exemplo de tamanho de buffer por load/leitura . O que acontece se
// o Buffer for menor que o conteúdo a ser lido?

fileSystem.read(caminho, user, buffer); // Lógica para ler arquivos maiores que o buffer deve ser implementada.
}

public static void mv() throws CaminhoNaoEncontradoException, PermissaoException {
System.out.println("Insira o caminho do arquivo a ser movido:");
String caminhoAntigo = scanner.nextLine();
System.out.println("Insira o novo caminho do arquivo:");
String caminhoNovo = scanner.nextLine();

fileSystem.mv(caminhoAntigo, caminhoNovo, user);
}

Expand All @@ -232,7 +311,7 @@ public static void ls() throws CaminhoNaoEncontradoException, PermissaoException
String caminho = scanner.nextLine();
System.out.println("Listar recursivamente? (true/false):");
boolean recursivo = Boolean.parseBoolean(scanner.nextLine());

fileSystem.ls(caminho, user, recursivo);
}

Expand All @@ -243,7 +322,7 @@ public static void cp() throws CaminhoNaoEncontradoException, PermissaoException
String caminhoDestino = scanner.nextLine();
System.out.println("Copiar recursivamente? (true/false):");
boolean recursivo = Boolean.parseBoolean(scanner.nextLine());

fileSystem.cp(caminhoOrigem, caminhoDestino, user, recursivo);
}
}
83 changes: 83 additions & 0 deletions filesys/Arquivo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package filesys;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import exception.PermissaoException;

public class Arquivo {
private Metadata metadata;
private static final int BLOCK_SIZE = 4096;
private List<Bloco> blocos = new ArrayList<>();


public Arquivo(String nomeArquivo, String usuario) {
this.metadata = new Metadata(nomeArquivo, usuario);
}

public void write(byte[] buffer, boolean append) throws PermissaoException {
if (metadata.getPermissions().values().stream().noneMatch(p -> p.contains("w"))) {
throw new PermissaoException("User " + metadata.getOwner() + " doesn't have permission to write!");
}

if (!append) {
blocos.clear();
}

int offset = 0;
while (offset < buffer.length) {
int remaining = buffer.length - offset;
int chunkSize = Math.min(BLOCK_SIZE, remaining);
byte[] chunk = new byte[chunkSize];
System.arraycopy(buffer, offset, chunk, 0, chunkSize);
blocos.add(new Bloco(chunk));
offset += chunkSize;
}
}

public byte[] read() {
ByteArrayOutputStream output = new ByteArrayOutputStream();
for (Bloco block : blocos) {
output.writeBytes(block.getDados());
}
return output.toByteArray();
}

public Metadata getMetadata() {
return metadata;
}

public void setMetadata(Metadata metadata) {
this.metadata = metadata;
}

public static int getBlockSize() {
return BLOCK_SIZE;
}

public List<Bloco> getBlocos() {
return blocos;
}

public void setBlocos(List<Bloco> blocos) {
this.blocos = blocos;
}

public void addBloco(Bloco bloco) {
this.blocos.add(bloco);
this.metadata.setSize(this.metadata.getSize() + bloco.getSize());
}

public void removeBloco(Bloco bloco) {
this.blocos.remove(bloco);
this.metadata.setSize(this.metadata.getSize() - bloco.getSize());
}

public void clearBloco() {
this.blocos.clear();
this.metadata.setSize(0);
}


}
30 changes: 30 additions & 0 deletions filesys/Bloco.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package filesys;

public class Bloco {
private byte[] dados;

public Bloco(byte[] dados) {
this.dados = dados;
}

public Bloco(int size) {
this.dados = new byte[size];
}

public Bloco() {
this.dados = new byte[0];
}

public byte[] getDados() {
return dados;
}

public void setDados(byte[] dados) {
this.dados = dados;
}

public int getSize() {
return dados.length;
}

}
Loading