From 489051d04e127353f1012d045dc0a162c119fd6d Mon Sep 17 00:00:00 2001 From: Athoosz Date: Thu, 5 Jun 2025 18:39:58 -0300 Subject: [PATCH 01/14] feat: implementando classes principais do sistema de arquivos: Arquivo, Bloco, Diretorio, MetaDados, FileSys, e Usuario --- filesys/Arquivo.java | 27 ++++++++++++++++++++++++ filesys/Bloco.java | 17 +++++++++++++++ filesys/Diretorio.java | 48 ++++++++++++++++++++++++++++++++++++++++++ filesys/FileSys.java | 16 ++++++++++++++ filesys/MetaDados.java | 46 ++++++++++++++++++++++++++++++++++++++++ filesys/Usuario.java | 31 +++++++++++++++++++++++++++ 6 files changed, 185 insertions(+) create mode 100644 filesys/Arquivo.java create mode 100644 filesys/Bloco.java create mode 100644 filesys/Diretorio.java create mode 100644 filesys/FileSys.java create mode 100644 filesys/MetaDados.java create mode 100644 filesys/Usuario.java diff --git a/filesys/Arquivo.java b/filesys/Arquivo.java new file mode 100644 index 0000000..7c73fb8 --- /dev/null +++ b/filesys/Arquivo.java @@ -0,0 +1,27 @@ +package filesys; + +import java.util.ArrayList; +import java.util.List; + +public class Arquivo { + private MetaDados metaDados; + private List blocos; + + public Arquivo(String nome, String dono) { + this.metaDados = new MetaDados(nome, dono); + this.blocos = new ArrayList<>(); + } + + public MetaDados getMetaDados() { + return metaDados; + } + + public List getBlocos() { + return blocos; + } + + public void adicionarBloco(Bloco bloco) { + blocos.add(bloco); + metaDados.setTamanho(metaDados.getTamanho() + bloco.getDados().length); + } +} diff --git a/filesys/Bloco.java b/filesys/Bloco.java new file mode 100644 index 0000000..be11773 --- /dev/null +++ b/filesys/Bloco.java @@ -0,0 +1,17 @@ +package filesys; + +public class Bloco { + private byte[] dados; + + public Bloco(int tamanho) { + this.dados = new byte[tamanho]; + } + + public byte[] getDados() { + return dados; + } + + public void setDados(byte[] dados) { + this.dados = dados; + } +} diff --git a/filesys/Diretorio.java b/filesys/Diretorio.java new file mode 100644 index 0000000..0d9e8ad --- /dev/null +++ b/filesys/Diretorio.java @@ -0,0 +1,48 @@ +package filesys; + +import java.util.ArrayList; +import java.util.List; + +public class Diretorio { + private MetaDados metaDados; + private List arquivos; + private List subdiretorios; + + public Diretorio(String nome, String dono) { + this.metaDados = new MetaDados(nome, dono); + this.arquivos = new ArrayList<>(); + this.subdiretorios = new ArrayList<>(); + } + + public MetaDados getMetaDados() { + return metaDados; + } + + public List getArquivos() { + return arquivos; + } + + public List getSubdiretorios() { + return subdiretorios; + } + + public void adicionarArquivo(Arquivo a) { + arquivos.add(a); + } + + public void adicionarSubdiretorio(Diretorio d) { + subdiretorios.add(d); + } + + public Diretorio buscarSubdiretorio(String nome) { + return subdiretorios.stream() + .filter(d -> d.getMetaDados().getNome().equals(nome)) + .findFirst().orElse(null); + } + + public Arquivo buscarArquivo(String nome) { + return arquivos.stream() + .filter(a -> a.getMetaDados().getNome().equals(nome)) + .findFirst().orElse(null); + } +} diff --git a/filesys/FileSys.java b/filesys/FileSys.java new file mode 100644 index 0000000..532b8fb --- /dev/null +++ b/filesys/FileSys.java @@ -0,0 +1,16 @@ +package filesys; + +public class FileSys { + private Diretorio raiz; + + public FileSys(String dono) { + this.raiz = new Diretorio("/", dono); + } + + public Diretorio getRaiz() { + return raiz; + } + public void setRaiz(Diretorio raiz) { + this.raiz = raiz; + } +} diff --git a/filesys/MetaDados.java b/filesys/MetaDados.java new file mode 100644 index 0000000..e5fea09 --- /dev/null +++ b/filesys/MetaDados.java @@ -0,0 +1,46 @@ +package filesys; + +import java.util.HashMap; + +public class MetaDados { + private String nome; + private int tamanho; + private String dono; + private HashMap permissoes; // ex: "rwx", "rw-", "r--" + + public MetaDados(String nome, String dono) { + this.nome = nome; + this.dono = dono; + this.tamanho = 0; + this.permissoes = new HashMap<>(); + this.permissoes.put(dono, "rwx"); // dono tem tudo por padrão + } + + public String getNome() { + return nome; + } + + public int getTamanho() { + return tamanho; + } + + public String getDono() { + return dono; + } + + public void setTamanho(int tamanho) { + this.tamanho = tamanho; + } + + public void setPermissao(String usuario, String perm) { + permissoes.put(usuario, perm); + } + + public String getPermissao(String usuario) { + return permissoes.getOrDefault(usuario, "---"); + } + + public boolean temPermissao(String usuario, char tipo) { + return getPermissao(usuario).indexOf(tipo) != -1; + } +} diff --git a/filesys/Usuario.java b/filesys/Usuario.java new file mode 100644 index 0000000..b3e9d9b --- /dev/null +++ b/filesys/Usuario.java @@ -0,0 +1,31 @@ +package filesys; + +public class Usuario { + private final String nome; + private final String permissao; // ex: "rwx", "rw-", "r--" + + public Usuario(String nome, String permissao) { + this.nome = nome; + this.permissao = permissao; + } + + public String getNome() { + return nome; + } + + public boolean podeLer() { + return permissao.contains("r"); + } + + public boolean podeEscrever() { + return permissao.contains("w"); + } + + public boolean podeExecutar() { + return permissao.contains("x"); + } + + public String getPermissao() { + return permissao; + } +} From 4fb36001fe831eb76ec349e1a0104abb3e24165f Mon Sep 17 00:00:00 2001 From: Athoosz Date: Thu, 5 Jun 2025 22:51:04 -0300 Subject: [PATCH 02/14] feat: Implementando mkdir e ls, e corrigindo problema do MakeFile --- Main.java | 22 ++++--- Makefile | 2 +- filesys/FileSystem.java | 6 +- filesys/FileSystemImpl.java | 121 ++++++++++++++++++++++++++++++++++-- 4 files changed, 134 insertions(+), 17 deletions(-) diff --git a/Main.java b/Main.java index 3b8673a..79e343f 100644 --- a/Main.java +++ b/Main.java @@ -1,5 +1,8 @@ import filesys.IFileSystem; +import filesys.Usuario; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; import java.io.FileNotFoundException; @@ -35,11 +38,11 @@ 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/**, // deve-se checar se o usuário tem permissão de escrita (r) neste caminho. - if (args.length < 2) { + if (args.length < 1) { System.out.println("Usuário não fornecido"); return; } - user = args[1]; + user = args[0]; // Carrega a lista de usuários do sistema a partir de arquivo // Formato do arquivo users: @@ -51,6 +54,7 @@ public static void main(String[] args) { // 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. + Map usuariosMap = new HashMap<>(); try { Scanner userScanner = new Scanner(new java.io.File("users/users")); while (userScanner.hasNextLine()) { @@ -67,7 +71,7 @@ public static void main(String[] args) { * 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 - + usuariosMap.put(userListed, new Usuario(userListed, dirPermission)); } else { System.out.println("Formato ruim no arquivo de usuários. Linha: " + line); @@ -84,15 +88,15 @@ public static void main(String[] args) { // 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(usuariosMap); // // 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()); - // } + try { + fileSystem.mkdir(ROOT_DIR, ROOT_USER); + } catch (CaminhoJaExistenteException | PermissaoException e) { + System.out.println(e.getMessage()); + } // Menu interativo. menu(); diff --git a/Makefile b/Makefile index fb358c4..52b1d2d 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ clean: # Run the application with a username run: compile - $(JAVA) -cp $(BIN_DIR) $(MAIN_CLASS) -u $(USERNAME) + $(JAVA) -cp $(BIN_DIR) $(MAIN_CLASS) $(USERNAME) # Help target help: diff --git a/filesys/FileSystem.java b/filesys/FileSystem.java index 8d7a83b..809e781 100644 --- a/filesys/FileSystem.java +++ b/filesys/FileSystem.java @@ -1,5 +1,7 @@ package filesys; +import java.util.Map; + import exception.CaminhoJaExistenteException; import exception.CaminhoNaoEncontradoException; import exception.PermissaoException; @@ -9,8 +11,8 @@ final public class FileSystem implements IFileSystem { private final IFileSystem fileSystemImpl; - public FileSystem() { - fileSystemImpl = new FileSystemImpl(); + public FileSystem(Map usuarios) { + this.fileSystemImpl = new FileSystemImpl(usuarios); } @Override diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 45fa05d..6b7e533 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -1,5 +1,7 @@ package filesys; +import java.util.Map; + import exception.CaminhoJaExistenteException; import exception.CaminhoNaoEncontradoException; import exception.PermissaoException; @@ -10,12 +12,58 @@ // e atributos & métodos privados podem ser adicionados public final class FileSystemImpl implements IFileSystem { private static final String ROOT_USER = "root"; // pode ser necessário + private final FileSys fileSys; + private final Map usuarios; - public FileSystemImpl() {} + public FileSystemImpl(Map usuarios) { + this.fileSys = new FileSys(ROOT_USER); + this.usuarios = usuarios; + } @Override - public void mkdir(String caminho, String nome) throws CaminhoJaExistenteException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'mkdir'"); + public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException { + if (!usuarios.containsKey(usuario)) { + throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); + } + + if (caminho.equals("/")) { + return; + } + + String[] partes = caminho.split("/"); + Diretorio atual = fileSys.getRaiz(); + + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + } + + for (int i = 1; i < partes.length - 1; i++) { + String nome = partes[i]; + Diretorio encontrado = atual.buscarSubdiretorio(nome); + + atual = encontrado; + } + + String nomeNovo = partes[partes.length - 1]; + + if (atual.buscarSubdiretorio(nomeNovo) != null) { + throw new CaminhoJaExistenteException("O diretório '" + nomeNovo + "' já existe."); + } + + if (!temPermissao(atual, usuario, 'w')) { + throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de escrita em '" + + atual.getMetaDados().getNome() + "'"); + } + + Diretorio novo = new Diretorio(nomeNovo, usuario); + atual.adicionarSubdiretorio(novo); + + // Debug pra testes: Imprime os subdiretorios do diretorio atual + System.out.print("Subdiretorios de '" + atual.getMetaDados().getNome() + "': "); + for (Diretorio d : atual.getSubdiretorios()) { + System.out.print(d.getMetaDados().getNome() + " "); + } + System.out.println(); } @Override @@ -54,8 +102,54 @@ public void mv(String caminhoAntigo, String caminhoNovo, String usuario) } @Override - public void ls(String caminho, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'ls'"); + public void ls(String caminho, String usuario, boolean recursivo) + throws CaminhoNaoEncontradoException, PermissaoException { + if (!usuarios.containsKey(usuario)) { + throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); + } + + Diretorio dir = fileSys.getRaiz(); + if (!caminho.equals("/")) { + String[] partes = caminho.split("/"); + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + } + for (int i = 1; i < partes.length; i++) { + String nome = partes[i]; + if (nome.isEmpty()) + continue; + Diretorio encontrado = dir.buscarSubdiretorio(nome); + if (encontrado == null) { + throw new CaminhoNaoEncontradoException( + "Diretório '" + nome + "' não encontrado em '" + caminho + "'"); + } + dir = encontrado; + } + } + + if (!temPermissao(dir, usuario, 'r')) { + throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de leitura em '" + caminho + "'"); + } + + lsDiretorio(dir, caminho.equals("/") ? "/" : dir.getMetaDados().getNome(), recursivo, ""); + } + + private void lsDiretorio(Diretorio dir, String nome, boolean recursivo, String prefixo) { + System.out.println(prefixo + nome + ":"); + + for (Arquivo arq : dir.getArquivos()) { + System.out.println(prefixo + " " + arq.getMetaDados().getNome()); + } + + for (Diretorio sub : dir.getSubdiretorios()) { + System.out.println(prefixo + " " + sub.getMetaDados().getNome() + "/"); + } + // Se recursivo, entra nos subdiretorios + if (recursivo) { + for (Diretorio sub : dir.getSubdiretorios()) { + lsDiretorio(sub, sub.getMetaDados().getNome(), true, prefixo + " "); + } + } } @Override @@ -67,4 +161,21 @@ public void cp(String caminhoOrigem, String caminhoDestino, String usuario, bool public void addUser(String user) { throw new UnsupportedOperationException("Método não implementado 'addUser'"); } + + private boolean temPermissao(Diretorio dir, String usuario, char tipo) { + if (usuario.equals("root")) + return true; // root sempre tem permissao + + String perm = dir.getMetaDados().getPermissao(usuario); + + if (perm.equals("---")) { + Usuario u = usuarios.get(usuario); + if (u != null) { + perm = u.getPermissao(); // rwx, rw-, r-- + } + } + + return perm.indexOf(tipo) != -1; + } + } From 488df24ac7ee21561cc610c3678301489a4f46a8 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Fri, 6 Jun 2025 19:13:03 -0300 Subject: [PATCH 03/14] feat: Implementando CaminhoNaoEncontradoException no mkdir e melhorado o gerenciamento de permissoes do usuario por caminho --- Main.java | 82 +++++++++++++++++++++---------------- Makefile | 2 +- filesys/FileSystem.java | 2 +- filesys/FileSystemImpl.java | 37 +++++++++-------- filesys/IFileSystem.java | 2 +- filesys/Usuario.java | 58 +++++++++++++++++++++++--- users/users | 3 +- 7 files changed, 125 insertions(+), 61 deletions(-) diff --git a/Main.java b/Main.java index 79e343f..5d9dd8b 100644 --- a/Main.java +++ b/Main.java @@ -16,8 +16,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 = "/"; @@ -32,27 +32,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 < 1) { + if (args.length < 2) { System.out.println("Usuário não fornecido"); return; } - user = args[0]; - + 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. Map usuariosMap = new HashMap<>(); try { @@ -65,13 +69,18 @@ public static void main(String[] args) { String userListed = parts[0]; String dir = parts[1]; String dirPermission = parts[2]; - - /* A FAZER: + + /* + * 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 - usuariosMap.put(userListed, new Usuario(userListed, dirPermission)); + * 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 + Usuario usuario = usuariosMap.getOrDefault(userListed, new Usuario(userListed)); + usuario.adicionarPermissao(dir, dirPermission); + usuariosMap.put(userListed, usuario); } else { System.out.println("Formato ruim no arquivo de usuários. Linha: " + line); @@ -84,17 +93,19 @@ 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(usuariosMap); - // // DESCOMENTE O BLOCO ABAIXO PARA CRIAR O DIRETÓRIO RAIZ ANTES DE RODAR O MENU + // // 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) { + fileSystem.mkdir("/home", ROOT_USER); + } catch (CaminhoJaExistenteException | PermissaoException | CaminhoNaoEncontradoException e) { System.out.println(e.getMessage()); } @@ -156,7 +167,7 @@ public static void menu() { return; default: System.out.println("Comando inválido!"); - } + } } catch (CaminhoNaoEncontradoException | CaminhoJaExistenteException | PermissaoException e) { System.out.println("Erro: " + e.getMessage()); } @@ -175,14 +186,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 { + public static void mkdir() throws CaminhoJaExistenteException, PermissaoException, CaminhoNaoEncontradoException { System.out.println("Insira o caminho do diretório a ser criado:"); String caminho = scanner.nextLine(); - + fileSystem.mkdir(caminho, user); } @@ -191,14 +202,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); } @@ -210,16 +221,17 @@ 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 { @@ -227,7 +239,7 @@ public static void mv() throws CaminhoNaoEncontradoException, PermissaoException String caminhoAntigo = scanner.nextLine(); System.out.println("Insira o novo caminho do arquivo:"); String caminhoNovo = scanner.nextLine(); - + fileSystem.mv(caminhoAntigo, caminhoNovo, user); } @@ -236,7 +248,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); } @@ -247,7 +259,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); } } diff --git a/Makefile b/Makefile index 52b1d2d..fb358c4 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ clean: # Run the application with a username run: compile - $(JAVA) -cp $(BIN_DIR) $(MAIN_CLASS) $(USERNAME) + $(JAVA) -cp $(BIN_DIR) $(MAIN_CLASS) -u $(USERNAME) # Help target help: diff --git a/filesys/FileSystem.java b/filesys/FileSystem.java index 809e781..e7cfcb7 100644 --- a/filesys/FileSystem.java +++ b/filesys/FileSystem.java @@ -22,7 +22,7 @@ public void chmod(String caminho, String usuario, String usuarioAlvo, String per } @Override - public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException { + public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException , CaminhoNaoEncontradoException{ fileSystemImpl.mkdir(caminho, usuario); } diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 6b7e533..5bf3bd7 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -21,7 +21,7 @@ public FileSystemImpl(Map usuarios) { } @Override - public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException { + public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException ,CaminhoNaoEncontradoException { if (!usuarios.containsKey(usuario)) { throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); } @@ -37,11 +37,19 @@ public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteExcep throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); } + StringBuilder caminhoAtual = new StringBuilder("/"); for (int i = 1; i < partes.length - 1; i++) { String nome = partes[i]; + if (nome.isEmpty()) + continue; Diretorio encontrado = atual.buscarSubdiretorio(nome); - + if (encontrado == null) { + throw new CaminhoNaoEncontradoException("Diretório '" + nome + "' não encontrado."); + } atual = encontrado; + if (caminhoAtual.length() > 1) + caminhoAtual.append("/"); + caminhoAtual.append(nome); } String nomeNovo = partes[partes.length - 1]; @@ -50,9 +58,10 @@ public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteExcep throw new CaminhoJaExistenteException("O diretório '" + nomeNovo + "' já existe."); } - if (!temPermissao(atual, usuario, 'w')) { + + if (!temPermissao(caminhoAtual.toString(), usuario, 'w')) { throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de escrita em '" - + atual.getMetaDados().getNome() + "'"); + + caminhoAtual + "'"); } Diretorio novo = new Diretorio(nomeNovo, usuario); @@ -127,7 +136,7 @@ public void ls(String caminho, String usuario, boolean recursivo) } } - if (!temPermissao(dir, usuario, 'r')) { + if (!temPermissao(caminho, usuario, 'r')) { throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de leitura em '" + caminho + "'"); } @@ -162,19 +171,15 @@ public void addUser(String user) { throw new UnsupportedOperationException("Método não implementado 'addUser'"); } - private boolean temPermissao(Diretorio dir, String usuario, char tipo) { - if (usuario.equals("root")) - return true; // root sempre tem permissao - - String perm = dir.getMetaDados().getPermissao(usuario); + private boolean temPermissao(String caminho, String usuario, char tipo) { + if (usuario.equals(ROOT_USER)) + return true; // root sempre tem permissão - if (perm.equals("---")) { - Usuario u = usuarios.get(usuario); - if (u != null) { - perm = u.getPermissao(); // rwx, rw-, r-- - } - } + Usuario u = usuarios.get(usuario); + if (u == null) + return false; + String perm = u.getPermissaoParaCaminho(caminho); return perm.indexOf(tipo) != -1; } diff --git a/filesys/IFileSystem.java b/filesys/IFileSystem.java index a0f0ce0..f3f29d2 100644 --- a/filesys/IFileSystem.java +++ b/filesys/IFileSystem.java @@ -14,7 +14,7 @@ public interface IFileSystem { // Cria um novo diretório. Se o diretório já existir, será lançada uma exceção. // Se o usuario não tiver permissão para criar o diretório, será lançada uma exceção. - void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException; + void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException, CaminhoNaoEncontradoException; // Remove um arquivo ou diretório. Se o diretório não existir, será lançada uma exceção. // Caso recursivo seja true, o diretório será removido recursivamente. diff --git a/filesys/Usuario.java b/filesys/Usuario.java index b3e9d9b..6b8e1af 100644 --- a/filesys/Usuario.java +++ b/filesys/Usuario.java @@ -1,12 +1,55 @@ package filesys; +import java.util.HashMap; +import java.util.Map; + public class Usuario { private final String nome; - private final String permissao; // ex: "rwx", "rw-", "r--" + private final Map permissoesPorCaminho; // ex: "/**" -> "rwx" public Usuario(String nome, String permissao) { this.nome = nome; - this.permissao = permissao; + this.permissoesPorCaminho = new HashMap<>(); + this.permissoesPorCaminho.put("**", permissao); + } + + public Usuario(String nome) { + this.nome = nome; + this.permissoesPorCaminho = new HashMap<>(); + } + + public void adicionarPermissao(String caminho, String permissao) { + permissoesPorCaminho.put(caminho, permissao); + } + + public String getPermissaoParaCaminho(String caminho) { + String melhorPermissao = "---"; + int melhorTamanho = -1; + for (Map.Entry entry : permissoesPorCaminho.entrySet()) { + String padrao = entry.getKey(); + if (caminhoMatches(padrao, caminho) && padrao.length() > melhorTamanho) { + melhorPermissao = entry.getValue(); + melhorTamanho = padrao.length(); + } + } + return melhorPermissao; + } + + private boolean caminhoMatches(String padrao, String caminho) { + // Aceita qualquer subcaminho + if (padrao.endsWith("/**")) { + String base = padrao.substring(0, padrao.length() - 3); + return caminho.startsWith(base); + } + // Aceita apenas filhos diretos + if (padrao.endsWith("/*")) { + String base = padrao.substring(0, padrao.length() - 2); + if (!caminho.startsWith(base + "/")) + return false; + String resto = caminho.substring(base.length() + 1); + return !resto.isEmpty() && !resto.contains("/"); + } + return padrao.equals(caminho); } public String getNome() { @@ -14,18 +57,21 @@ public String getNome() { } public boolean podeLer() { - return permissao.contains("r"); + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("r"); } public boolean podeEscrever() { - return permissao.contains("w"); + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("w"); } public boolean podeExecutar() { - return permissao.contains("x"); + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("x"); } public String getPermissao() { - return permissao; + return permissoesPorCaminho.get("**"); } } diff --git a/users/users b/users/users index 58c2992..db2c3a9 100644 --- a/users/users +++ b/users/users @@ -4,4 +4,5 @@ joao /** rw- pedro /** rw- tiago /** rw- luzia /** rwx -carla /** r-- \ No newline at end of file +carla /** r-- +athos /home/** rwx \ No newline at end of file From 4d9e8994a1d97770eb3e2c561ef809374dc76558 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Sat, 7 Jun 2025 22:46:13 -0300 Subject: [PATCH 04/14] =?UTF-8?q?feat:=20Criando=20touch,=20modularizando?= =?UTF-8?q?=20m=C3=A9todos=20touch,mkdir=20e=20ls?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Main.java | 4 +- filesys/FileSystem.java | 2 +- filesys/FileSystemImpl.java | 172 ++++++++++++++++++++++-------------- filesys/IFileSystem.java | 2 +- 4 files changed, 112 insertions(+), 68 deletions(-) diff --git a/Main.java b/Main.java index 5d9dd8b..995c873 100644 --- a/Main.java +++ b/Main.java @@ -74,7 +74,7 @@ public static void main(String[] args) { * 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. + * users. --- FEITO */ System.out.println(userListed + " " + dir + " " + dirPermission); // Somente imprime o usuário, // diretório e permissão @@ -206,7 +206,7 @@ public static void rm() throws CaminhoNaoEncontradoException, PermissaoException fileSystem.rm(caminho, user, recursivo); } - public static void touch() throws CaminhoJaExistenteException, PermissaoException { + public static void touch() throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { System.out.println("Insira o caminho do arquivo a ser criado:"); String caminho = scanner.nextLine(); diff --git a/filesys/FileSystem.java b/filesys/FileSystem.java index e7cfcb7..afbec2c 100644 --- a/filesys/FileSystem.java +++ b/filesys/FileSystem.java @@ -33,7 +33,7 @@ public void rm(String caminho, String usuario, boolean recursivo) } @Override - public void touch(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException { + public void touch(String caminho, String usuario) throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { fileSystemImpl.touch(caminho, usuario); } diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 5bf3bd7..3029b05 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -21,55 +21,28 @@ public FileSystemImpl(Map usuarios) { } @Override - public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException ,CaminhoNaoEncontradoException { - if (!usuarios.containsKey(usuario)) { - throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); - } + public void mkdir(String caminho, String usuario) + throws CaminhoJaExistenteException, PermissaoException, CaminhoNaoEncontradoException { + verificaUsuarioValido(usuario); - if (caminho.equals("/")) { + if (caminho.equals("/")) return; - } - String[] partes = caminho.split("/"); - Diretorio atual = fileSys.getRaiz(); + Diretorio pai = navegarParaDiretorioPai(caminho); + String nomeNovo = extrairNomeFinal(caminho); - if (!partes[0].isEmpty()) { - throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + if (pai.buscarSubdiretorio(nomeNovo) != null) { + throw new CaminhoJaExistenteException("O diretório '" + nomeNovo + "' já existe em '" + caminho + "'"); } - StringBuilder caminhoAtual = new StringBuilder("/"); - for (int i = 1; i < partes.length - 1; i++) { - String nome = partes[i]; - if (nome.isEmpty()) - continue; - Diretorio encontrado = atual.buscarSubdiretorio(nome); - if (encontrado == null) { - throw new CaminhoNaoEncontradoException("Diretório '" + nome + "' não encontrado."); - } - atual = encontrado; - if (caminhoAtual.length() > 1) - caminhoAtual.append("/"); - caminhoAtual.append(nome); - } - - String nomeNovo = partes[partes.length - 1]; - - if (atual.buscarSubdiretorio(nomeNovo) != null) { - throw new CaminhoJaExistenteException("O diretório '" + nomeNovo + "' já existe."); - } - - - if (!temPermissao(caminhoAtual.toString(), usuario, 'w')) { - throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de escrita em '" - + caminhoAtual + "'"); - } + verificarPermissao(obterCaminhoPai(caminho), usuario, 'w'); Diretorio novo = new Diretorio(nomeNovo, usuario); - atual.adicionarSubdiretorio(novo); + pai.adicionarSubdiretorio(novo); // Debug pra testes: Imprime os subdiretorios do diretorio atual - System.out.print("Subdiretorios de '" + atual.getMetaDados().getNome() + "': "); - for (Diretorio d : atual.getSubdiretorios()) { + System.out.print("Subdiretorios de '" + pai.getMetaDados().getNome() + "': "); + for (Diretorio d : pai.getSubdiretorios()) { System.out.print(d.getMetaDados().getNome() + " "); } System.out.println(); @@ -88,8 +61,25 @@ public void rm(String caminho, String usuario, boolean recursivo) } @Override - public void touch(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'touch'"); + public void touch(String caminho, String usuario) + throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { + verificaUsuarioValido(usuario); + + if (caminho.equals("/") || caminho.endsWith("/")) { + throw new CaminhoNaoEncontradoException("Caminho inválido para arquivo: " + caminho); + } + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nomeArquivo = extrairNomeFinal(caminho); + + if (pai.buscarArquivo(nomeArquivo) != null) { + throw new CaminhoJaExistenteException("O arquivo '" + nomeArquivo + "' já existe."); + } + + verificarPermissao(obterCaminhoPai(caminho), usuario, 'w'); + + Arquivo novoArquivo = new Arquivo(nomeArquivo, usuario); + pai.adicionarArquivo(novoArquivo); } @Override @@ -113,33 +103,16 @@ public void mv(String caminhoAntigo, String caminhoNovo, String usuario) @Override public void ls(String caminho, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException { - if (!usuarios.containsKey(usuario)) { - throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); - } + verificaUsuarioValido(usuario); - Diretorio dir = fileSys.getRaiz(); - if (!caminho.equals("/")) { - String[] partes = caminho.split("/"); - if (!partes[0].isEmpty()) { - throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); - } - for (int i = 1; i < partes.length; i++) { - String nome = partes[i]; - if (nome.isEmpty()) - continue; - Diretorio encontrado = dir.buscarSubdiretorio(nome); - if (encontrado == null) { - throw new CaminhoNaoEncontradoException( - "Diretório '" + nome + "' não encontrado em '" + caminho + "'"); - } - dir = encontrado; - } + // Verifica se o caminho é válido + if (caminho == null || caminho.isEmpty() || !caminho.startsWith("/")) { + throw new CaminhoNaoEncontradoException("Caminho inválido: " + caminho); } - if (!temPermissao(caminho, usuario, 'r')) { - throw new PermissaoException("Usuário '" + usuario + "' não tem permissão de leitura em '" + caminho + "'"); - } + Diretorio dir = caminho.equals("/") ? fileSys.getRaiz() : navegarParaDiretorioCompleto(caminho); + verificarPermissao(caminho, usuario, 'r'); lsDiretorio(dir, caminho.equals("/") ? "/" : dir.getMetaDados().getNome(), recursivo, ""); } @@ -171,6 +144,77 @@ public void addUser(String user) { throw new UnsupportedOperationException("Método não implementado 'addUser'"); } + // Navega para o diretorio pai do caminho passado como parametro + // Ex: "/home/user/docs" retorna "/home/user" + private Diretorio navegarParaDiretorioPai(String caminho) throws CaminhoNaoEncontradoException { + String[] partes = caminho.split("/"); + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + } + + Diretorio atual = fileSys.getRaiz(); + for (int i = 1; i < partes.length - 1; i++) { + if (partes[i].isEmpty()) + continue; + Diretorio encontrado = atual.buscarSubdiretorio(partes[i]); + if (encontrado == null) { + throw new CaminhoNaoEncontradoException("Diretório '" + partes[i] + "' não encontrado."); + } + atual = encontrado; + } + return atual; + } + + // Navega para o diretorio completo do caminho passado como parametro + // Ex: "/home/user/docs" retorna o diretorio "docs" + private Diretorio navegarParaDiretorioCompleto(String caminho) throws CaminhoNaoEncontradoException { + String[] partes = caminho.split("/"); + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + } + + Diretorio atual = fileSys.getRaiz(); + for (int i = 1; i < partes.length; i++) { + if (partes[i].isEmpty()) + continue; + Diretorio encontrado = atual.buscarSubdiretorio(partes[i]); + if (encontrado == null) { + throw new CaminhoNaoEncontradoException("Diretório '" + partes[i] + "' não encontrado."); + } + atual = encontrado; + } + return atual; + } + + // Extrai o nome final do caminho, que pode ser um arquivo ou diretório + // Ex: "/home/user/docs" retorna "docs" + private String extrairNomeFinal(String caminho) { + String[] partes = caminho.split("/"); + return partes[partes.length - 1]; + } + + // Obtém o caminho pai do caminho fornecido + // Ex: "/home/user/docs" retorna "/home/user" + private String obterCaminhoPai(String caminho) { + int ultimoSlash = caminho.lastIndexOf('/'); + if (ultimoSlash == 0) + return "/"; + return caminho.substring(0, ultimoSlash); + } + + private void verificaUsuarioValido(String usuario) throws PermissaoException { + if (!usuarios.containsKey(usuario)) { + throw new PermissaoException("Usuário '" + usuario + "' não encontrado."); + } + } + + private void verificarPermissao(String caminho, String usuario, char tipo) throws PermissaoException { + if (!temPermissao(caminho, usuario, tipo)) { + throw new PermissaoException( + "Usuário '" + usuario + "' não tem permissão '" + tipo + "' em '" + caminho + "'"); + } + } + private boolean temPermissao(String caminho, String usuario, char tipo) { if (usuario.equals(ROOT_USER)) return true; // root sempre tem permissão diff --git a/filesys/IFileSystem.java b/filesys/IFileSystem.java index f3f29d2..9642cad 100644 --- a/filesys/IFileSystem.java +++ b/filesys/IFileSystem.java @@ -21,7 +21,7 @@ public interface IFileSystem { void rm(String caminho, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException; // Cria um novo arquivo. Atenção: Se o arquivo já existir, será lançada uma exceção. - void touch(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException; + void touch(String caminho, String usuario) throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException; // Escreve dados em um arquivo. Se o diretório não existir, será lançada uma exceção. // Caso o diretório exista, o arquivo será criado ou sobrescrito. From fc63097ee42dfe04bb60e4dd196fa7f050bc5cd4 Mon Sep 17 00:00:00 2001 From: jOaON3ri Date: Sun, 8 Jun 2025 12:05:53 -0300 Subject: [PATCH 05/14] Codigo mv e rm --- filesys/Diretorio.java | 9 ++++ filesys/FileSystemImpl.java | 94 +++++++++++++++++++++++++++++++++++-- filesys/IFileSystem.java | 2 +- filesys/MetaDados.java | 5 ++ 4 files changed, 106 insertions(+), 4 deletions(-) diff --git a/filesys/Diretorio.java b/filesys/Diretorio.java index 0d9e8ad..77ac1b6 100644 --- a/filesys/Diretorio.java +++ b/filesys/Diretorio.java @@ -45,4 +45,13 @@ public Arquivo buscarArquivo(String nome) { .filter(a -> a.getMetaDados().getNome().equals(nome)) .findFirst().orElse(null); } + + public void removerArquivo(String nome) { + arquivos.removeIf(a -> a.getMetaDados().getNome().equals(nome)); + } + + public void removerSubdiretorio(String nome) { + subdiretorios.removeIf(d -> d.getMetaDados().getNome().equals(nome)); + } + } diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 3029b05..f06efaf 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -1,5 +1,6 @@ package filesys; +import java.util.ArrayList; import java.util.Map; import exception.CaminhoJaExistenteException; @@ -51,13 +52,46 @@ public void mkdir(String caminho, String usuario) @Override public void chmod(String caminho, String usuario, String usuarioAlvo, String permissao) throws CaminhoNaoEncontradoException, PermissaoException { + verificaUsuarioValido(usuario); + verificaUsuarioValido(usuarioAlvo); throw new UnsupportedOperationException("Método não implementado 'chmod'"); } @Override public void rm(String caminho, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'rm'"); + verificaUsuarioValido(usuario); + + if (caminho.equals("/")) { + throw new PermissaoException("Não é permitido remover o diretório raiz."); + } + + verificarPermissao(caminho, usuario, 'r'); + verificarPermissao(obterCaminhoPai(caminho), usuario, 'w'); + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nome = extrairNomeFinal(caminho); + + Arquivo arq = pai.buscarArquivo(nome); + if (arq != null) { + pai.removerArquivo(nome); + return; + } + + Diretorio dir = pai.buscarSubdiretorio(nome); + if (dir == null) { + throw new CaminhoNaoEncontradoException("Caminho '" + caminho + "' não encontrado."); + } + + if (!recursivo && (!dir.getArquivos().isEmpty() || !dir.getSubdiretorios().isEmpty())) { + throw new PermissaoException("Diretório não vazio. Use o modo recursivo."); + } + + if (recursivo) { + removerDiretorioRecursivamente(dir); + } + + pai.removerSubdiretorio(nome); } @Override @@ -96,8 +130,49 @@ public void read(String caminho, String usuario, byte[] buffer) @Override public void mv(String caminhoAntigo, String caminhoNovo, String usuario) - throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'mv'"); + throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException { + verificaUsuarioValido(usuario); + + // Verifica se os caminhos são válidos + if (caminhoAntigo.equals("/") || caminhoNovo.equals("/")) { + throw new CaminhoNaoEncontradoException("Não é possível mover o diretório raiz."); + } + + verificarPermissao(caminhoAntigo, usuario, 'r'); + verificarPermissao(obterCaminhoPai(caminhoNovo), usuario, 'w'); + verificarPermissao(obterCaminhoPai(caminhoAntigo), usuario, 'w'); + + // Extrai nomes e diretórios pai + Diretorio dirOrigemPai = navegarParaDiretorioPai(caminhoAntigo); + Diretorio dirDestinoPai = navegarParaDiretorioPai(caminhoNovo); + String nomeOrigem = extrairNomeFinal(caminhoAntigo); + String nomeDestino = extrairNomeFinal(caminhoNovo); + + // Verifica se já existe algo no destino + if (dirDestinoPai.buscarArquivo(nomeDestino) != null || dirDestinoPai.buscarSubdiretorio(nomeDestino) != null) { + throw new CaminhoJaExistenteException("O destino '" + caminhoNovo + "' já existe."); + } + + // Verifica se é arquivo + Arquivo arquivo = dirOrigemPai.buscarArquivo(nomeOrigem); + if (arquivo != null) { + dirOrigemPai.removerArquivo(nomeOrigem); + arquivo.getMetaDados().setNome(nomeDestino); + dirDestinoPai.adicionarArquivo(arquivo); + return; + } + + // Verifica se é diretório + Diretorio subdir = dirOrigemPai.buscarSubdiretorio(nomeOrigem); + if (subdir != null) { + dirOrigemPai.removerSubdiretorio(nomeOrigem); + subdir.getMetaDados().setNome(nomeDestino); + dirDestinoPai.adicionarSubdiretorio(subdir); + return; + } + + // Se não encontrou nada + throw new CaminhoNaoEncontradoException("Caminho de origem '" + caminhoAntigo + "' não encontrado."); } @Override @@ -227,4 +302,17 @@ private boolean temPermissao(String caminho, String usuario, char tipo) { return perm.indexOf(tipo) != -1; } + private void removerDiretorioRecursivamente(Diretorio dir) { + // Remove subdiretórios recursivamente + for (Diretorio sub : new ArrayList<>(dir.getSubdiretorios())) { + removerDiretorioRecursivamente(sub); + dir.removerSubdiretorio(sub.getMetaDados().getNome()); + } + + // Remove todos os arquivos + for (Arquivo arq : new ArrayList<>(dir.getArquivos())) { + dir.removerArquivo(arq.getMetaDados().getNome()); + } + } + } diff --git a/filesys/IFileSystem.java b/filesys/IFileSystem.java index 9642cad..2f6eada 100644 --- a/filesys/IFileSystem.java +++ b/filesys/IFileSystem.java @@ -36,7 +36,7 @@ public interface IFileSystem { // Move ou renomeia um arquivo ou diretório. Se o diretório não existir, será lançada uma exceção. // Se o diretório já existir, será sobrescrito. // mv é naturalmente recursivo. - void mv(String caminhoAntigo, String caminhoNovo, String usuario) throws CaminhoNaoEncontradoException, PermissaoException; + void mv(String caminhoAntigo, String caminhoNovo, String usuario) throws CaminhoNaoEncontradoException, PermissaoException,CaminhoJaExistenteException; // Lista o conteúdo de um diretório. Se o diretório não existir, será lançada uma exceção. // Caso recursivo seja true, todo o conteúdo do diretório será listado recursivamente. diff --git a/filesys/MetaDados.java b/filesys/MetaDados.java index e5fea09..b0ea338 100644 --- a/filesys/MetaDados.java +++ b/filesys/MetaDados.java @@ -43,4 +43,9 @@ public String getPermissao(String usuario) { public boolean temPermissao(String usuario, char tipo) { return getPermissao(usuario).indexOf(tipo) != -1; } + + public void setNome(String nomeDestino) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'setNome'"); + } } From b176e976600575790cd3030e4b696c81a9a45e86 Mon Sep 17 00:00:00 2001 From: jOaON3ri Date: Sun, 8 Jun 2025 12:07:34 -0300 Subject: [PATCH 06/14] pequena alteracao --- filesys/FileSystem.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filesys/FileSystem.java b/filesys/FileSystem.java index afbec2c..692d44b 100644 --- a/filesys/FileSystem.java +++ b/filesys/FileSystem.java @@ -51,7 +51,7 @@ public void read(String caminho, String usuario, byte[] buffer) @Override public void mv(String caminhoAntigo, String caminhoNovo, String usuario) - throws CaminhoNaoEncontradoException, PermissaoException { + throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException{ fileSystemImpl.mv(caminhoAntigo, caminhoNovo, usuario); } From 1a3b2978c8b343a3b3e2b5a19c42fef8b17ef446 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Sun, 8 Jun 2025 13:11:02 -0300 Subject: [PATCH 07/14] feat: Implementado write e read, leitura de arquivos com offset e adicionado classe Offset --- Main.java | 23 +++++++-- filesys/Arquivo.java | 1 + filesys/FileSystem.java | 12 +++-- filesys/FileSystemImpl.java | 96 +++++++++++++++++++++++++++++++++++-- filesys/IFileSystem.java | 4 +- filesys/MetaDados.java | 5 +- filesys/Offset.java | 17 +++++++ 7 files changed, 141 insertions(+), 17 deletions(-) create mode 100644 filesys/Offset.java diff --git a/Main.java b/Main.java index 995c873..bcb2766 100644 --- a/Main.java +++ b/Main.java @@ -1,4 +1,5 @@ import filesys.IFileSystem; +import filesys.Offset; import filesys.Usuario; import java.util.HashMap; @@ -228,13 +229,27 @@ public static void write() throws CaminhoNaoEncontradoException, PermissaoExcept 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? + byte[] buffer = new byte[READ_BUFFER_SIZE]; - fileSystem.read(caminho, user, buffer); // Lógica para ler arquivos maiores que o buffer deve ser implementada. + Offset offset = new Offset(0); + int offsetAnterior; + int bytesLidos; + + System.out.println("Conteúdo lido:"); + do { + offsetAnterior = offset.getValue(); + fileSystem.read(caminho, user, buffer, offset); + bytesLidos = offset.getValue() - offsetAnterior; + + if (bytesLidos > 0) + System.out.write(buffer, 0, bytesLidos); + } while (bytesLidos > 0); + + System.out.flush(); + System.out.println(); } - public static void mv() throws CaminhoNaoEncontradoException, PermissaoException { + public static void mv() throws CaminhoNaoEncontradoException, CaminhoJaExistenteException, 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:"); diff --git a/filesys/Arquivo.java b/filesys/Arquivo.java index 7c73fb8..3acb55a 100644 --- a/filesys/Arquivo.java +++ b/filesys/Arquivo.java @@ -6,6 +6,7 @@ public class Arquivo { private MetaDados metaDados; private List blocos; + public static int TAMANHO_BLOCO = 64; public Arquivo(String nome, String dono) { this.metaDados = new MetaDados(nome, dono); diff --git a/filesys/FileSystem.java b/filesys/FileSystem.java index 692d44b..e8a8398 100644 --- a/filesys/FileSystem.java +++ b/filesys/FileSystem.java @@ -22,7 +22,8 @@ public void chmod(String caminho, String usuario, String usuarioAlvo, String per } @Override - public void mkdir(String caminho, String usuario) throws CaminhoJaExistenteException, PermissaoException , CaminhoNaoEncontradoException{ + public void mkdir(String caminho, String usuario) + throws CaminhoJaExistenteException, PermissaoException, CaminhoNaoEncontradoException { fileSystemImpl.mkdir(caminho, usuario); } @@ -33,7 +34,8 @@ public void rm(String caminho, String usuario, boolean recursivo) } @Override - public void touch(String caminho, String usuario) throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { + public void touch(String caminho, String usuario) + throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { fileSystemImpl.touch(caminho, usuario); } @@ -44,14 +46,14 @@ public void write(String caminho, String usuario, boolean anexar, byte[] buffer) } @Override - public void read(String caminho, String usuario, byte[] buffer) + public void read(String caminho, String usuario, byte[] buffer, Offset offset) throws CaminhoNaoEncontradoException, PermissaoException { - fileSystemImpl.read(caminho, usuario, buffer); + fileSystemImpl.read(caminho, usuario, buffer, offset); } @Override public void mv(String caminhoAntigo, String caminhoNovo, String usuario) - throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException{ + throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException { fileSystemImpl.mv(caminhoAntigo, caminhoNovo, usuario); } diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index f06efaf..83e5030 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -119,13 +119,44 @@ public void touch(String caminho, String usuario) @Override public void write(String caminho, String usuario, boolean anexar, byte[] buffer) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'write'"); + verificaUsuarioValido(usuario); + verificarPermissao(caminho, usuario, 'w'); + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nomeArquivo = extrairNomeFinal(caminho); + Arquivo arquivo = pai.buscarArquivo(nomeArquivo); + + if (arquivo == null) { + if (anexar) { + throw new CaminhoNaoEncontradoException("Arquivo '" + nomeArquivo + "' não encontrado para anexar."); + } + arquivo = new Arquivo(nomeArquivo, usuario); + pai.adicionarArquivo(arquivo); + } + + if (!anexar) { + arquivo.getBlocos().clear(); + arquivo.getMetaDados().setTamanho(0); + } + + escreverBufferEmBlocos(arquivo, buffer); } @Override - public void read(String caminho, String usuario, byte[] buffer) + public void read(String caminho, String usuario, byte[] buffer, Offset offset) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'read'"); + verificaUsuarioValido(usuario); + verificarPermissao(caminho, usuario, 'r'); + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nomeArquivo = extrairNomeFinal(caminho); + Arquivo arquivo = pai.buscarArquivo(nomeArquivo); + + if (arquivo == null) { + throw new CaminhoNaoEncontradoException("Arquivo '" + nomeArquivo + "' não encontrado."); + } + + lerArquivoComOffset(arquivo, buffer, offset); } @Override @@ -133,7 +164,6 @@ public void mv(String caminhoAntigo, String caminhoNovo, String usuario) throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException { verificaUsuarioValido(usuario); - // Verifica se os caminhos são válidos if (caminhoAntigo.equals("/") || caminhoNovo.equals("/")) { throw new CaminhoNaoEncontradoException("Não é possível mover o diretório raiz."); } @@ -315,4 +345,62 @@ private void removerDiretorioRecursivamente(Diretorio dir) { } } + /* + * Escreve o conteúdo do buffer em blocos do arquivo + * Se o buffer for maior que o tamanho do bloco, + * ele será dividido em blocos de tamanho fixo. + */ + private void escreverBufferEmBlocos(Arquivo arquivo, byte[] buffer) { + int blocoTamanho = Arquivo.TAMANHO_BLOCO; + int offset = 0; + while (offset < buffer.length) { + int len = Math.min(blocoTamanho, buffer.length - offset); + byte[] dados = new byte[len]; + System.arraycopy(buffer, offset, dados, 0, len); + Bloco bloco = new Bloco(len); + bloco.setDados(dados); + arquivo.adicionarBloco(bloco); + offset += len; + } + } + + /* + * Lê o conteúdo do arquivo a partir de um offset mutável. + * O método deve atualizar o offset conforme lê bytes. + * Se o offset for maior que o tamanho do arquivo, retorna 0. + */ + private int lerArquivoComOffset(Arquivo arquivo, byte[] buffer, Offset offset) { + int arquivoTamanho = arquivo.getMetaDados().getTamanho(); + int posicao = offset.getValue(); + + // Zera o buffer antes de preencher + for (int i = 0; i < buffer.length; i++) + buffer[i] = 0; + + if (posicao >= arquivoTamanho) + return 0; + + int bytesParaLer = Math.min(buffer.length, arquivoTamanho - posicao); + + int blocoTamanho = Arquivo.TAMANHO_BLOCO; + int blocoInicial = posicao / blocoTamanho; + int posNoBloco = posicao % blocoTamanho; + + int bufferPos = 0; + int bytesRestantes = bytesParaLer; + + for (int i = blocoInicial; i < arquivo.getBlocos().size() && bytesRestantes > 0; i++) { + Bloco bloco = arquivo.getBlocos().get(i); + byte[] dados = bloco.getDados(); + int start = (i == blocoInicial) ? posNoBloco : 0; + int len = Math.min(dados.length - start, bytesRestantes); + System.arraycopy(dados, start, buffer, bufferPos, len); + bufferPos += len; + bytesRestantes -= len; + } + + offset.add(bytesParaLer); // atualiza o offset para a proxima leitura + return bytesParaLer; + } + } diff --git a/filesys/IFileSystem.java b/filesys/IFileSystem.java index 2f6eada..e1cfdeb 100644 --- a/filesys/IFileSystem.java +++ b/filesys/IFileSystem.java @@ -31,7 +31,9 @@ public interface IFileSystem { // Lê dados de um arquivo. Se o arquivo não existir, será lançada uma exceção. // Leitura sequencial - todo o conteudo do arquivo sera lido e armazenado no buffer. - void read(String caminho, String usuario, byte[] buffer) throws CaminhoNaoEncontradoException, PermissaoException; + // Lê dados de um arquivo a partir de um offset mutável. + // O método deve atualizar o offset conforme lê bytes. + void read(String caminho, String usuario, byte[] buffer, Offset offset) throws CaminhoNaoEncontradoException, PermissaoException; // Move ou renomeia um arquivo ou diretório. Se o diretório não existir, será lançada uma exceção. // Se o diretório já existir, será sobrescrito. diff --git a/filesys/MetaDados.java b/filesys/MetaDados.java index b0ea338..6e02f3e 100644 --- a/filesys/MetaDados.java +++ b/filesys/MetaDados.java @@ -44,8 +44,7 @@ public boolean temPermissao(String usuario, char tipo) { return getPermissao(usuario).indexOf(tipo) != -1; } - public void setNome(String nomeDestino) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'setNome'"); + public void setNome(String nomeDestino) { + this.nome = nomeDestino; } } diff --git a/filesys/Offset.java b/filesys/Offset.java new file mode 100644 index 0000000..2abe224 --- /dev/null +++ b/filesys/Offset.java @@ -0,0 +1,17 @@ +package filesys; + +public class Offset { + private int value; + + public Offset(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public void add(int delta) { + value += delta; + } +} \ No newline at end of file From 80b0b45b4e46225f323a896d4f74e6767ae36c92 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Sun, 8 Jun 2025 22:30:02 -0300 Subject: [PATCH 08/14] =?UTF-8?q?come=C3=A7ando=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/PermissionTest.java | 54 +++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/tests/PermissionTest.java b/tests/PermissionTest.java index 6026e31..c689385 100644 --- a/tests/PermissionTest.java +++ b/tests/PermissionTest.java @@ -2,25 +2,69 @@ import static org.junit.Assert.assertTrue; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; +import java.io.File; + import org.junit.jupiter.api.Test; + +import exception.PermissaoException; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + import org.junit.jupiter.api.Assertions.*; import org.junit.jupiter.api.BeforeAll; +import filesys.FileSystem; import filesys.FileSystemImpl; import filesys.IFileSystem; +import filesys.Usuario; // Essa classe testa cenários de permissão public class PermissionTest { private static IFileSystem fileSystem; + private static final String ROOT_USER = "root"; + private static final String ROOT_DIR = "/"; + private static final int READ_BUFFER_SIZE = 256; @BeforeAll - public static void setUp() { - fileSystem = new FileSystemImpl(/*args...*/); + public static void setUp() throws Exception { + Map usuariosMap = new HashMap<>(); + try (Scanner userScanner = new Scanner(new 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]; + Usuario usuario = usuariosMap.getOrDefault(userListed, new Usuario(userListed)); + usuario.adicionarPermissao(dir, dirPermission); + usuariosMap.put(userListed, usuario); + } + } + } + } + fileSystem = new FileSystem(usuariosMap); + fileSystem.mkdir(ROOT_DIR, ROOT_USER); + fileSystem.mkdir("/home", ROOT_USER); } @Test - public void testPermission() { - // Teste de permissão - assertTrue(true); + public void testPermission() throws Exception { + // Usuário com permissão de escrita + assertDoesNotThrow(() -> fileSystem.mkdir("/testMaria", "maria")); + + // Usuário athos não tem permissão para criar no diretório raiz + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/testAthos", "athos")); + + // Usuário athos pode criar no /home + assertDoesNotThrow(() -> fileSystem.mkdir("/home/testAthos", "athos")); + + // Usuário root sempre pode + assertDoesNotThrow(() -> fileSystem.mkdir("/testRoot", ROOT_USER)); } } From d920dfce7e42fdd9ef4062c750a3d934fced96a6 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Mon, 9 Jun 2025 14:05:53 -0300 Subject: [PATCH 09/14] feat: Implementado metodo chmod e addUser, removeUser --- filesys/FileSystemImpl.java | 58 ++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 8 deletions(-) diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 83e5030..f5cd2b3 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -54,7 +54,28 @@ public void chmod(String caminho, String usuario, String usuarioAlvo, String per throws CaminhoNaoEncontradoException, PermissaoException { verificaUsuarioValido(usuario); verificaUsuarioValido(usuarioAlvo); - throw new UnsupportedOperationException("Método não implementado 'chmod'"); + + // Só root ou quem tem permissão rw pode alterar permissoes + if (!usuario.equals(ROOT_USER) + && !(temPermissao(caminho, usuario, 'r') && temPermissao(caminho, usuario, 'w'))) { + throw new PermissaoException( + "Usuário '" + usuario + "' não tem permissão para alterar permissões em '" + caminho + "'"); + } + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nome = extrairNomeFinal(caminho); + + Arquivo arq = pai.buscarArquivo(nome); + if (arq != null) { + arq.getMetaDados().setPermissao(usuarioAlvo, permissao); + return; + } + Diretorio dir = pai.buscarSubdiretorio(nome); + if (dir != null) { + dir.getMetaDados().setPermissao(usuarioAlvo, permissao); + return; + } + throw new CaminhoNaoEncontradoException("Caminho '" + caminho + "' não encontrado."); } @Override @@ -245,8 +266,15 @@ public void cp(String caminhoOrigem, String caminhoDestino, String usuario, bool throw new UnsupportedOperationException("Método não implementado 'cp'"); } - public void addUser(String user) { - throw new UnsupportedOperationException("Método não implementado 'addUser'"); + public void addUser(String nome, String permissao) { + if (!usuarios.containsKey(nome)) { + Usuario novo = new Usuario(nome, permissao); + usuarios.put(nome, novo); + } + } + + public void removeUser(String nome) { + usuarios.remove(nome); } // Navega para o diretorio pai do caminho passado como parametro @@ -324,12 +352,26 @@ private boolean temPermissao(String caminho, String usuario, char tipo) { if (usuario.equals(ROOT_USER)) return true; // root sempre tem permissão - Usuario u = usuarios.get(usuario); - if (u == null) - return false; + try { + Diretorio pai = navegarParaDiretorioPai(caminho); + String nome = extrairNomeFinal(caminho); - String perm = u.getPermissaoParaCaminho(caminho); - return perm.indexOf(tipo) != -1; + Arquivo arq = pai.buscarArquivo(nome); + if (arq != null) { + return arq.getMetaDados().temPermissao(usuario, tipo); + } + Diretorio dir = pai.buscarSubdiretorio(nome); + if (dir != null) { + return dir.getMetaDados().temPermissao(usuario, tipo); + } + // Se for o diretório raiz + if (caminho.equals("/")) { + return fileSys.getRaiz().getMetaDados().temPermissao(usuario, tipo); + } + } catch (Exception e) { + return false; + } + return false; } private void removerDiretorioRecursivamente(Diretorio dir) { From 6c9723a951c240df888e00bb16ff76cfa5dc7ebd Mon Sep 17 00:00:00 2001 From: Athoosz Date: Mon, 9 Jun 2025 21:07:21 -0300 Subject: [PATCH 10/14] =?UTF-8?q?feat:=20Adicionadas=20verifica=C3=A7?= =?UTF-8?q?=C3=B5es=20de=20permiss=C3=A3o=20de=20execu=C3=A7=C3=A3o=20e=20?= =?UTF-8?q?testes=20para=20mkdir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- filesys/FileSystemImpl.java | 61 ++++++++++++++++++++++++++++++++++--- tests/PermissionTest.java | 27 +++++++++++++++- users/users | 5 ++- 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index f5cd2b3..aba3dee 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -29,6 +29,8 @@ public void mkdir(String caminho, String usuario) if (caminho.equals("/")) return; + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + Diretorio pai = navegarParaDiretorioPai(caminho); String nomeNovo = extrairNomeFinal(caminho); @@ -87,6 +89,7 @@ public void rm(String caminho, String usuario, boolean recursivo) throw new PermissaoException("Não é permitido remover o diretório raiz."); } + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); verificarPermissao(caminho, usuario, 'r'); verificarPermissao(obterCaminhoPai(caminho), usuario, 'w'); @@ -124,6 +127,8 @@ public void touch(String caminho, String usuario) throw new CaminhoNaoEncontradoException("Caminho inválido para arquivo: " + caminho); } + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + Diretorio pai = navegarParaDiretorioPai(caminho); String nomeArquivo = extrairNomeFinal(caminho); @@ -142,6 +147,7 @@ public void write(String caminho, String usuario, boolean anexar, byte[] buffer) throws CaminhoNaoEncontradoException, PermissaoException { verificaUsuarioValido(usuario); verificarPermissao(caminho, usuario, 'w'); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); Diretorio pai = navegarParaDiretorioPai(caminho); String nomeArquivo = extrairNomeFinal(caminho); @@ -168,6 +174,7 @@ public void read(String caminho, String usuario, byte[] buffer, Offset offset) throws CaminhoNaoEncontradoException, PermissaoException { verificaUsuarioValido(usuario); verificarPermissao(caminho, usuario, 'r'); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); Diretorio pai = navegarParaDiretorioPai(caminho); String nomeArquivo = extrairNomeFinal(caminho); @@ -189,6 +196,9 @@ public void mv(String caminhoAntigo, String caminhoNovo, String usuario) throw new CaminhoNaoEncontradoException("Não é possível mover o diretório raiz."); } + verificarPermissaoExecucaoNoCaminho(caminhoAntigo, usuario); + verificarPermissaoExecucaoNoCaminho(caminhoNovo, usuario); + verificarPermissao(caminhoAntigo, usuario, 'r'); verificarPermissao(obterCaminhoPai(caminhoNovo), usuario, 'w'); verificarPermissao(obterCaminhoPai(caminhoAntigo), usuario, 'w'); @@ -236,6 +246,8 @@ public void ls(String caminho, String usuario, boolean recursivo) throw new CaminhoNaoEncontradoException("Caminho inválido: " + caminho); } + verificarPermissaoExecucaoNoCaminho(caminho, usuario); + Diretorio dir = caminho.equals("/") ? fileSys.getRaiz() : navegarParaDiretorioCompleto(caminho); verificarPermissao(caminho, usuario, 'r'); @@ -341,6 +353,34 @@ private void verificaUsuarioValido(String usuario) throws PermissaoException { } } + private void verificarPermissaoExecucaoNoCaminho(String caminho, String usuario) + throws PermissaoException, CaminhoNaoEncontradoException { + if (usuario.equals(ROOT_USER)) + return; + + String[] partes = caminho.split("/"); + Diretorio atual = fileSys.getRaiz(); + StringBuilder pathBuilder = new StringBuilder(); + for (int i = 1; i < partes.length; i++) { + if (partes[i].isEmpty()) + continue; + pathBuilder.append("/").append(partes[i]); + if (!temPermissao(pathBuilder.toString(), usuario, 'x')) { + throw new PermissaoException( + "Usuário '" + usuario + "' não tem permissão 'x' em '" + pathBuilder + "'"); + } + Diretorio encontrado = atual.buscarSubdiretorio(partes[i]); + if (encontrado == null) + break; + atual = encontrado; + } + // Sempre checa permissão 'x' em '/' se o caminho for exatamente "/" + if (caminho.equals("/") && !temPermissao("/", usuario, 'x')) { + throw new PermissaoException( + "Usuário '" + usuario + "' não tem permissão 'x' em '/'"); + } + } + private void verificarPermissao(String caminho, String usuario, char tipo) throws PermissaoException { if (!temPermissao(caminho, usuario, tipo)) { throw new PermissaoException( @@ -358,18 +398,31 @@ private boolean temPermissao(String caminho, String usuario, char tipo) { Arquivo arq = pai.buscarArquivo(nome); if (arq != null) { - return arq.getMetaDados().temPermissao(usuario, tipo); + if (arq.getMetaDados().temPermissao(usuario, tipo)) { + return true; + } } Diretorio dir = pai.buscarSubdiretorio(nome); if (dir != null) { - return dir.getMetaDados().temPermissao(usuario, tipo); + if (dir.getMetaDados().temPermissao(usuario, tipo)) { + return true; + } } // Se for o diretório raiz if (caminho.equals("/")) { - return fileSys.getRaiz().getMetaDados().temPermissao(usuario, tipo); + if (fileSys.getRaiz().getMetaDados().temPermissao(usuario, tipo)) { + return true; + } } } catch (Exception e) { - return false; + // ignora, vai checar permissao global do usuario + } + + // Checa permissao global do usuario (definida no arquivo users) + Usuario userObj = usuarios.get(usuario); + if (userObj != null) { + String perm = userObj.getPermissaoParaCaminho(caminho); + return perm.indexOf(tipo) != -1; } return false; } diff --git a/tests/PermissionTest.java b/tests/PermissionTest.java index c689385..d0f8dcd 100644 --- a/tests/PermissionTest.java +++ b/tests/PermissionTest.java @@ -50,7 +50,32 @@ public static void setUp() throws Exception { } fileSystem = new FileSystem(usuariosMap); fileSystem.mkdir(ROOT_DIR, ROOT_USER); - fileSystem.mkdir("/home", ROOT_USER); + fileSystem.mkdir("/users", ROOT_USER); + fileSystem.mkdir("/users/athos", ROOT_USER); + fileSystem.mkdir("/users/joao", ROOT_USER); + } + + @Test + public void testMkdirUsersPermissions() throws Exception { + // root: rwx em /** (pode tudo) + assertDoesNotThrow(() -> fileSystem.mkdir("/rootTest", "root")); + + // maria: rw- em /** (pode criar, mas não pode executar) + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/mariaTest", "maria")); + + // luzia: rwx em /** (possui permissão root) + assertDoesNotThrow(() -> fileSystem.mkdir("/luziaTest", "luzia")); + + // carla: r-- em /** (não pode criar em lugar nenhum) + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/carlaTest", "carla")); + + // athos: rwx apenas em /users/athos/** + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/athosTest", "athos")); + assertDoesNotThrow(() -> fileSystem.mkdir("/users/athos/teste", "athos")); + + // joao: rwx apenas em em /users/joao/** + assertDoesNotThrow(() -> fileSystem.mkdir("/users/joao/teste", "joao")); + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/users/athos/joaoTest", "joao")); } @Test diff --git a/users/users b/users/users index db2c3a9..e4a0278 100644 --- a/users/users +++ b/users/users @@ -5,4 +5,7 @@ pedro /** rw- tiago /** rw- luzia /** rwx carla /** r-- -athos /home/** rwx \ No newline at end of file +athos /users x +athos /users/athos/** rwx +joao /users x +joao /users/joao/** rwx From b6154c832bf42589efecdf85daaf6f035032c465 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Tue, 10 Jun 2025 18:34:13 -0300 Subject: [PATCH 11/14] =?UTF-8?q?feat:=20Consertando=20erro=20e=20adiciona?= =?UTF-8?q?ndo=20testes=20para=20permiss=C3=B5es=20de=20chmod=20e=20mkdir?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- filesys/FileSystemImpl.java | 14 ++++++++ filesys/Usuario.java | 5 +-- tests/ChmodTest.java | 48 ++++++++++++++++++++++++++++ tests/FileSystemTestBase.java | 45 ++++++++++++++++++++++++++ tests/MkdirTest.java | 34 ++++++++++++++++++++ tests/PermissionTest.java | 60 ++++++++--------------------------- 6 files changed, 158 insertions(+), 48 deletions(-) create mode 100644 tests/ChmodTest.java create mode 100644 tests/FileSystemTestBase.java create mode 100644 tests/MkdirTest.java diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index aba3dee..6aba8e1 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -64,6 +64,11 @@ public void chmod(String caminho, String usuario, String usuarioAlvo, String per "Usuário '" + usuario + "' não tem permissão para alterar permissões em '" + caminho + "'"); } + if( caminho.equals("/")) { + fileSys.getRaiz().getMetaDados().setPermissao(usuarioAlvo, permissao); + return; + } + Diretorio pai = navegarParaDiretorioPai(caminho); String nome = extrairNomeFinal(caminho); @@ -292,6 +297,9 @@ public void removeUser(String nome) { // Navega para o diretorio pai do caminho passado como parametro // Ex: "/home/user/docs" retorna "/home/user" private Diretorio navegarParaDiretorioPai(String caminho) throws CaminhoNaoEncontradoException { + if (caminho.equals("/")) { + return fileSys.getRaiz(); + } String[] partes = caminho.split("/"); if (!partes[0].isEmpty()) { throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); @@ -334,6 +342,12 @@ private Diretorio navegarParaDiretorioCompleto(String caminho) throws CaminhoNao // Extrai o nome final do caminho, que pode ser um arquivo ou diretório // Ex: "/home/user/docs" retorna "docs" private String extrairNomeFinal(String caminho) { + if (caminho == null || caminho.isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: não pode ser nulo ou vazio."); + } + if (caminho.equals("/")) { + return "/"; + } String[] partes = caminho.split("/"); return partes[partes.length - 1]; } diff --git a/filesys/Usuario.java b/filesys/Usuario.java index 6b8e1af..e19af02 100644 --- a/filesys/Usuario.java +++ b/filesys/Usuario.java @@ -37,9 +37,10 @@ public String getPermissaoParaCaminho(String caminho) { private boolean caminhoMatches(String padrao, String caminho) { // Aceita qualquer subcaminho - if (padrao.endsWith("/**")) { + if (padrao.endsWith("/**")) { String base = padrao.substring(0, padrao.length() - 3); - return caminho.startsWith(base); + // Só casa se for um subcaminho, não o próprio diretório base + return !caminho.equals(base) && caminho.startsWith(base + "/"); } // Aceita apenas filhos diretos if (padrao.endsWith("/*")) { diff --git a/tests/ChmodTest.java b/tests/ChmodTest.java new file mode 100644 index 0000000..39f9c22 --- /dev/null +++ b/tests/ChmodTest.java @@ -0,0 +1,48 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +import exception.CaminhoNaoEncontradoException; +import exception.PermissaoException; + +public class ChmodTest extends FileSystemTestBase { + + @Test + public void testRootPodeAlterarPermissao() throws Exception { + fileSystem.mkdir("/dirChmod", ROOT_USER); + // root altera permissão de maria para rwx no diretório /dirChmod + assertDoesNotThrow(() -> fileSystem.chmod("/dirChmod", ROOT_USER, "maria", "rwx")); + } + + @Test + public void testUsuarioComRWXAlteraPermissao() throws Exception { + fileSystem.mkdir("/dirluzia", "luzia"); + // luzia tem rwx em /dirluzia, pode alterar permissão para joao + assertDoesNotThrow(() -> fileSystem.chmod("/dirluzia", "luzia", "joao", "r--")); + } + + @Test + public void testUsuarioSemPermissaoNaoAltera() throws Exception { + fileSystem.mkdir("/dirLuzia", ROOT_USER); + // carla não tem permissão rw em /dirLuzia + assertThrows(PermissaoException.class, () -> fileSystem.chmod("/dirLuzia", "carla", "joao", "rwx")); + } + + @Test + public void testChmodCaminhoInexistente() { + // root tenta alterar permissão de caminho inexistente + assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.chmod("/naoexiste", ROOT_USER, "maria", "rwx")); + } + + @Test + public void testRootConcedePermissaoRWXParaUsuarioNoDiretorioRaiz() throws Exception { + fileSystem.mkdir("/dirChmodRoot", ROOT_USER); + // root altera permissão de maria para rwx no diretório raiz + assertDoesNotThrow(() -> fileSystem.chmod(ROOT_DIR, ROOT_USER, "maria", "rwx")); + // maria agora pode criar no diretório raiz + assertDoesNotThrow(() -> fileSystem.mkdir("/dirMaria", "maria")); + } +} diff --git a/tests/FileSystemTestBase.java b/tests/FileSystemTestBase.java new file mode 100644 index 0000000..5078692 --- /dev/null +++ b/tests/FileSystemTestBase.java @@ -0,0 +1,45 @@ +package tests; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Scanner; + +import org.junit.jupiter.api.BeforeAll; + +import filesys.FileSystem; +import filesys.IFileSystem; +import filesys.Usuario; + +public abstract class FileSystemTestBase { + protected static IFileSystem fileSystem; + protected static final String ROOT_USER = "root"; + protected static final String ROOT_DIR = "/"; + protected static final int READ_BUFFER_SIZE = 256; + + @BeforeAll + public static void setUp() throws Exception { + Map usuariosMap = new HashMap<>(); + try (Scanner userScanner = new Scanner(new 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]; + Usuario usuario = usuariosMap.getOrDefault(userListed, new Usuario(userListed)); + usuario.adicionarPermissao(dir, dirPermission); + usuariosMap.put(userListed, usuario); + } + } + } + } + fileSystem = new FileSystem(usuariosMap); + fileSystem.mkdir(ROOT_DIR, ROOT_USER); + fileSystem.mkdir("/users", ROOT_USER); + fileSystem.mkdir("/users/athos", ROOT_USER); + fileSystem.mkdir("/users/joao", ROOT_USER); + } +} diff --git a/tests/MkdirTest.java b/tests/MkdirTest.java new file mode 100644 index 0000000..17a454c --- /dev/null +++ b/tests/MkdirTest.java @@ -0,0 +1,34 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.junit.jupiter.api.Test; + +import exception.CaminhoJaExistenteException; +import exception.CaminhoNaoEncontradoException; + +public class MkdirTest extends FileSystemTestBase { + + @Test + public void testCriarDiretorio() throws Exception { + fileSystem.mkdir("/rootTest", ROOT_USER); + } + + @Test + public void testCriarDiretorioJaExistente() throws Exception { + fileSystem.mkdir("/home", "root"); + assertThrows(CaminhoJaExistenteException.class, () -> fileSystem.mkdir("/home", "root")); + } + + @Test + public void testCriarDiretorioSemPai() { + assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.mkdir("/naoexiste/filho", "root")); + } + + @Test + public void testCriarDiretorioComPai() throws Exception { + fileSystem.mkdir("/pai", "root"); + assertDoesNotThrow(() -> fileSystem.mkdir("/pai/filho", "root")); + } +} diff --git a/tests/PermissionTest.java b/tests/PermissionTest.java index d0f8dcd..4ab94e8 100644 --- a/tests/PermissionTest.java +++ b/tests/PermissionTest.java @@ -1,12 +1,5 @@ package tests; -import static org.junit.Assert.assertTrue; - -import java.util.HashMap; -import java.util.Map; -import java.util.Scanner; -import java.io.File; - import org.junit.jupiter.api.Test; import exception.PermissaoException; @@ -14,46 +7,8 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -import org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.BeforeAll; - -import filesys.FileSystem; -import filesys.FileSystemImpl; -import filesys.IFileSystem; -import filesys.Usuario; - // Essa classe testa cenários de permissão -public class PermissionTest { - private static IFileSystem fileSystem; - private static final String ROOT_USER = "root"; - private static final String ROOT_DIR = "/"; - private static final int READ_BUFFER_SIZE = 256; - - @BeforeAll - public static void setUp() throws Exception { - Map usuariosMap = new HashMap<>(); - try (Scanner userScanner = new Scanner(new 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]; - Usuario usuario = usuariosMap.getOrDefault(userListed, new Usuario(userListed)); - usuario.adicionarPermissao(dir, dirPermission); - usuariosMap.put(userListed, usuario); - } - } - } - } - fileSystem = new FileSystem(usuariosMap); - fileSystem.mkdir(ROOT_DIR, ROOT_USER); - fileSystem.mkdir("/users", ROOT_USER); - fileSystem.mkdir("/users/athos", ROOT_USER); - fileSystem.mkdir("/users/joao", ROOT_USER); - } +public class PermissionTest extends FileSystemTestBase { @Test public void testMkdirUsersPermissions() throws Exception { @@ -78,6 +33,18 @@ public void testMkdirUsersPermissions() throws Exception { assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/users/athos/joaoTest", "joao")); } + @Test + public void testChmodPermissions() throws Exception { + // root: rwx em /** (pode tudo) + assertDoesNotThrow(() -> fileSystem.chmod("/users/athos", "root", "maria", "rwx")); + + // luzia agora pode criar no /users/athos + assertDoesNotThrow(() -> fileSystem.mkdir("/users/athos/testeLuzia", "luzia")); + + // athos não pode alterar permissão de maria + assertThrows(PermissaoException.class, () -> fileSystem.chmod("/users/athos", "athos", "maria", "rwx")); + } + @Test public void testPermission() throws Exception { // Usuário com permissão de escrita @@ -92,4 +59,5 @@ public void testPermission() throws Exception { // Usuário root sempre pode assertDoesNotThrow(() -> fileSystem.mkdir("/testRoot", ROOT_USER)); } + } From 57a598cc6c562ccacd8e81b3b6fcf3154b2fef9b Mon Sep 17 00:00:00 2001 From: jOaON3ri Date: Wed, 11 Jun 2025 08:05:42 -0300 Subject: [PATCH 12/14] Metodo cp e testes cp e mv --- filesys/FileSystemImpl.java | 91 +++++++++++++++++++++++--- filesys/Offset.java | 4 ++ tests/CpTest.java | 116 +++++++++++++++++++++++++++++++++ tests/MvTest.java | 125 ++++++++++++++++++++++++++++++++++++ 4 files changed, 326 insertions(+), 10 deletions(-) create mode 100644 tests/CpTest.java create mode 100644 tests/MvTest.java diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 6aba8e1..29de8f9 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -64,7 +64,7 @@ public void chmod(String caminho, String usuario, String usuarioAlvo, String per "Usuário '" + usuario + "' não tem permissão para alterar permissões em '" + caminho + "'"); } - if( caminho.equals("/")) { + if (caminho.equals("/")) { fileSys.getRaiz().getMetaDados().setPermissao(usuarioAlvo, permissao); return; } @@ -280,7 +280,50 @@ private void lsDiretorio(Diretorio dir, String nome, boolean recursivo, String p @Override public void cp(String caminhoOrigem, String caminhoDestino, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'cp'"); + + verificaUsuarioValido(usuario); + // Localiza origem e destino + Diretorio dirOrigemPai = navegarParaDiretorioPai(caminhoOrigem); + Diretorio dirDestino = navegarParaDiretorioPai(caminhoDestino); + + String nomeOrigem = extrairNomeFinal(caminhoOrigem); + String nomeDestino = extrairNomeFinal(caminhoDestino); + + // Verifica se é arquivo + Arquivo arquivoOrigem = dirOrigemPai.buscarArquivo(nomeOrigem); + if (arquivoOrigem != null) { + if (!arquivoOrigem.getMetaDados().temPermissao(usuario, 'r')) { + throw new PermissaoException("Sem permissão de leitura para o arquivo."); + } + + Arquivo copia = new Arquivo(nomeDestino, usuario); + for (Bloco bloco : arquivoOrigem.getBlocos()) { + Bloco novoBloco = new Bloco(bloco.getDados().length); + novoBloco.setDados(bloco.getDados().clone()); + copia.adicionarBloco(novoBloco); + } + + dirDestino.adicionarArquivo(copia); + return; + } + + // Verifica se é diretório + Diretorio diretorioOrigem = dirOrigemPai.buscarSubdiretorio(nomeOrigem); + if (diretorioOrigem != null) { + if (!diretorioOrigem.getMetaDados().temPermissao(usuario, 'r')) { + throw new PermissaoException("Sem permissão de leitura para o diretório."); + } + if (!recursivo) { + throw new PermissaoException("Cópia de diretório requer flag recursiva."); + } + + Diretorio copia = copiarDiretorioRecursivo(diretorioOrigem, usuario); + copia.getMetaDados().setNome(nomeDestino); + dirDestino.adicionarSubdiretorio(copia); + return; + } + + throw new CaminhoNaoEncontradoException("Origem não encontrada."); } public void addUser(String nome, String permissao) { @@ -346,7 +389,7 @@ private String extrairNomeFinal(String caminho) { throw new IllegalArgumentException("Caminho inválido: não pode ser nulo ou vazio."); } if (caminho.equals("/")) { - return "/"; + return "/"; } String[] partes = caminho.split("/"); return partes[partes.length - 1]; @@ -442,15 +485,15 @@ private boolean temPermissao(String caminho, String usuario, char tipo) { } private void removerDiretorioRecursivamente(Diretorio dir) { - // Remove subdiretórios recursivamente - for (Diretorio sub : new ArrayList<>(dir.getSubdiretorios())) { - removerDiretorioRecursivamente(sub); - dir.removerSubdiretorio(sub.getMetaDados().getNome()); + // Remove arquivos do diretório + for (Arquivo arquivo : new ArrayList<>(dir.getArquivos())) { + dir.removerArquivo(arquivo.getMetaDados().getNome()); } - // Remove todos os arquivos - for (Arquivo arq : new ArrayList<>(dir.getArquivos())) { - dir.removerArquivo(arq.getMetaDados().getNome()); + // Remove subdiretórios recursivamente + for (Diretorio subdir : new ArrayList<>(dir.getSubdiretorios())) { + removerDiretorioRecursivamente(subdir); + dir.removerSubdiretorio(subdir.getMetaDados().getNome()); } } @@ -512,4 +555,32 @@ private int lerArquivoComOffset(Arquivo arquivo, byte[] buffer, Offset offset) { return bytesParaLer; } + private Diretorio copiarDiretorioRecursivo(Diretorio original, String usuario) throws PermissaoException { + if (!original.getMetaDados().temPermissao(usuario, 'r')) { + throw new PermissaoException("Sem permissão para copiar diretório " + original.getMetaDados().getNome()); + } + + Diretorio copia = new Diretorio(original.getMetaDados().getNome(), usuario); + + for (Arquivo a : original.getArquivos()) { + if (!a.getMetaDados().temPermissao(usuario, 'r')) { + throw new PermissaoException("Sem permissão para copiar arquivo " + a.getMetaDados().getNome()); + } + + Arquivo novo = new Arquivo(a.getMetaDados().getNome(), usuario); + for (Bloco bloco : a.getBlocos()) { + Bloco b = new Bloco(bloco.getDados().length); + b.setDados(bloco.getDados().clone()); + novo.adicionarBloco(b); + } + copia.adicionarArquivo(novo); + } + + for (Diretorio sub : original.getSubdiretorios()) { + Diretorio subCopia = copiarDiretorioRecursivo(sub, usuario); + copia.adicionarSubdiretorio(subCopia); + } + + return copia; + } } diff --git a/filesys/Offset.java b/filesys/Offset.java index 2abe224..cd315f4 100644 --- a/filesys/Offset.java +++ b/filesys/Offset.java @@ -11,6 +11,10 @@ public int getValue() { return value; } + public void setValue(int value) { + this.value = value; + } + public void add(int delta) { value += delta; } diff --git a/tests/CpTest.java b/tests/CpTest.java new file mode 100644 index 0000000..3feed70 --- /dev/null +++ b/tests/CpTest.java @@ -0,0 +1,116 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import exception.*; +import filesys.Offset; + +public class CpTest extends FileSystemTestBase { + + @BeforeEach + public void prepararAmbienteTeste() { + // Usando blocos try-catch para cada operação + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + // Ignora se não existir + } + + try { + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.mkdir("/testes/origem", ROOT_USER); + fileSystem.mkdir("/testes/destino", ROOT_USER); + + fileSystem.touch("/testes/origem/arquivo1.txt", ROOT_USER); + fileSystem.touch("/testes/origem/arquivo2.txt", ROOT_USER); + + fileSystem.mkdir("/testes/origem/subpasta", ROOT_USER); + fileSystem.touch("/testes/origem/subpasta/arquivo3.txt", ROOT_USER); + + } catch (Exception e) { + fail("Falha ao preparar ambiente de teste: " + e.getMessage()); + } + } + @AfterEach + public void limparAmbienteTeste() { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + // Ignora erros na limpeza + } + } + + @Test + public void copiarArquivoParaNovoLocal() { + assertDoesNotThrow(() -> fileSystem.cp("/testes/origem/arquivo1.txt", "/testes/destino/copia_arquivo1.txt", + ROOT_USER, false)); + } + + @Test + public void copiarPastaSemFlagRecursivo() { + assertThrows(PermissaoException.class, + () -> fileSystem.cp("/testes/origem/subpasta", "/testes/destino/copia_subpasta", ROOT_USER, false)); + } + + @Test + public void copiarPastaComFlagRecursivo() { + assertDoesNotThrow( + () -> fileSystem.cp("/testes/origem/subpasta", "/testes/destino/copia_subpasta", ROOT_USER, true)); + } + + @Test + public void copiarOrigemInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, + () -> fileSystem.cp("/inexistente", "/testes/destino/copia", ROOT_USER, false)); + } + + @Test + public void copiarParaDestinoInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, + () -> fileSystem.cp("/testes/origem/arquivo1.txt", "/inexistente/copia.txt", ROOT_USER, false)); + } + + @Test + public void copiarArquivoSemPermissaoLeitura() { + assertThrows(PermissaoException.class, + () -> fileSystem.cp("/testes/origem/arquivo1.txt", "/testes/destino/copia.txt", "joao", false)); + } + + @Test + public void copiarArquivoSemPermissaoEscrita() { + assertThrows(PermissaoException.class, + () -> fileSystem.cp("/testes/origem/arquivo1.txt", "/users/athos/copia.txt", "athos", false)); + } + + @Test + public void copiarArquivoParaPasta() { + assertDoesNotThrow(() -> fileSystem.cp("/testes/origem/arquivo1.txt", "/testes/destino/", ROOT_USER, false)); + } + + @Test + public void copiarPastaComConteudo() throws Exception { + fileSystem.cp("/testes/origem/subpasta", "/testes/destino/copia_subpasta", ROOT_USER, true); + assertDoesNotThrow(() -> fileSystem.read("/testes/destino/copia_subpasta/arquivo3.txt", ROOT_USER, + new byte[256], new Offset(0))); + } + + @Test + public void copiarPastaVazia() throws Exception { + fileSystem.mkdir("/testes/origem/pastavazia", ROOT_USER); + assertDoesNotThrow( + () -> fileSystem.cp("/testes/origem/pastavazia", "/testes/destino/copia_pastavazia", ROOT_USER, true)); + } + + @Test + public void copiarArquivoGrande() throws Exception { + byte[] dadosGrandes = new byte[1024]; // 1KB de dados + fileSystem.write("/testes/origem/arquivogrande.txt", ROOT_USER, false, dadosGrandes); + + assertDoesNotThrow(() -> fileSystem.cp("/testes/origem/arquivogrande.txt", "/testes/destino/copia_grande.txt", + ROOT_USER, false)); + } +} \ No newline at end of file diff --git a/tests/MvTest.java b/tests/MvTest.java new file mode 100644 index 0000000..fe9b7ee --- /dev/null +++ b/tests/MvTest.java @@ -0,0 +1,125 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; +import filesys.Offset; + +public class MvTest extends FileSystemTestBase { + + @BeforeEach + public void prepararAmbienteTeste() { + try { + // Tenta remover se existir (ignora erros) + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + // Ignora se não existir + } + + // Cria estrutura básica + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.mkdir("/testes/origem", ROOT_USER); + fileSystem.mkdir("/testes/destino", ROOT_USER); + + // Cria arquivos e subpastas + fileSystem.touch("/testes/origem/arquivo1.txt", ROOT_USER); + fileSystem.mkdir("/testes/origem/subpasta", ROOT_USER); + fileSystem.touch("/testes/origem/subpasta/arquivo2.txt", ROOT_USER); + + } catch (Exception e) { + // Se falhar, marca o teste como falho com mensagem clara + fail("FALHA CRÍTICA no preparo do ambiente: " + e.getMessage(), e); + } + } + + @AfterEach + public void limparAmbienteTeste() { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + System.err.println("Aviso: Falha ao limpar ambiente: " + e.getMessage()); + } + } + + @Test + public void moverArquivoParaNovoLocal() { + assertDoesNotThrow(() -> + fileSystem.mv("/testes/origem/arquivo1.txt", + "/testes/destino/arquivo1_movido.txt", + ROOT_USER)); + } + + @Test + public void moverPastaParaNovoLocal() { + assertDoesNotThrow(() -> + fileSystem.mv("/testes/origem/subpasta", + "/testes/destino/subpasta_movida", + ROOT_USER)); + } + + + @Test + public void moverOrigemInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, () -> + fileSystem.mv("/testes/naoexiste", + "/testes/destino/movido", + ROOT_USER)); + } + + @Test + public void moverSemPermissaoLeitura() { + assertThrows(PermissaoException.class, () -> + fileSystem.mv("/testes/origem/arquivo1.txt", + "/testes/destino/arquivo_movido.txt", + "joao")); + } + + @Test + public void moverSemPermissaoEscritaDestino() { + assertThrows(PermissaoException.class, () -> + fileSystem.mv("/testes/origem/arquivo1.txt", + "/users/athos/arquivo_movido.txt", + "athos")); + } + + @Test + public void moverParaSubpasta() { + assertDoesNotThrow(() -> { + fileSystem.mv("/testes/origem/arquivo1.txt", + "/testes/origem/subpasta/arquivo1_movido.txt", + ROOT_USER); + // Verifica se o arquivo foi movido + assertDoesNotThrow(() -> + fileSystem.read("/testes/origem/subpasta/arquivo1_movido.txt", + ROOT_USER, new byte[256], new Offset(0))); + }); + } + + @Test + public void moverPastaComConteudo() { + assertDoesNotThrow(() -> { + fileSystem.mv("/testes/origem/subpasta", + "/testes/destino/subpasta_movida", + ROOT_USER); + // Verifica se o conteúdo foi preservado + assertDoesNotThrow(() -> + fileSystem.read("/testes/destino/subpasta_movida/arquivo2.txt", + ROOT_USER, new byte[256], new Offset(0))); + }); + } + + @Test + public void moverParaMesmoLocal() { + assertThrows(CaminhoJaExistenteException.class, () -> + fileSystem.mv("/testes/origem/arquivo1.txt", + "/testes/origem/arquivo1.txt", + ROOT_USER)); + } + + @Test + public void moverRaiz() { + assertThrows(CaminhoNaoEncontradoException.class, () -> + fileSystem.mv("/", "/novaraiz", ROOT_USER)); + } +} \ No newline at end of file From 4ca6a875b05b6295207c504691324d8320a1e766 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Wed, 11 Jun 2025 11:41:05 -0300 Subject: [PATCH 13/14] feat: adicionando todos os tests faltantes --- filesys/FileSystemImpl.java | 8 +- tests/FileSystemTestBase.java | 3 + tests/LsTest.java | 44 +++++++ tests/PermissionTest.java | 218 +++++++++++++++++++++++++++++----- tests/ReadTest.java | 47 ++++++++ tests/RmTest.java | 50 ++++++++ tests/TouchTest.java | 41 +++++++ tests/WriteTest.java | 44 +++++++ users/users | 2 + 9 files changed, 424 insertions(+), 33 deletions(-) create mode 100644 tests/LsTest.java create mode 100644 tests/ReadTest.java create mode 100644 tests/RmTest.java create mode 100644 tests/TouchTest.java create mode 100644 tests/WriteTest.java diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 29de8f9..1487656 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -159,11 +159,7 @@ public void write(String caminho, String usuario, boolean anexar, byte[] buffer) Arquivo arquivo = pai.buscarArquivo(nomeArquivo); if (arquivo == null) { - if (anexar) { - throw new CaminhoNaoEncontradoException("Arquivo '" + nomeArquivo + "' não encontrado para anexar."); - } - arquivo = new Arquivo(nomeArquivo, usuario); - pai.adicionarArquivo(arquivo); + throw new CaminhoNaoEncontradoException("Arquivo '" + nomeArquivo + "' não encontrado."); } if (!anexar) { @@ -281,7 +277,7 @@ private void lsDiretorio(Diretorio dir, String nome, boolean recursivo, String p public void cp(String caminhoOrigem, String caminhoDestino, String usuario, boolean recursivo) throws CaminhoNaoEncontradoException, PermissaoException { - verificaUsuarioValido(usuario); + verificaUsuarioValido(usuario); // Localiza origem e destino Diretorio dirOrigemPai = navegarParaDiretorioPai(caminhoOrigem); Diretorio dirDestino = navegarParaDiretorioPai(caminhoDestino); diff --git a/tests/FileSystemTestBase.java b/tests/FileSystemTestBase.java index 5078692..45ca2fb 100644 --- a/tests/FileSystemTestBase.java +++ b/tests/FileSystemTestBase.java @@ -9,6 +9,7 @@ import filesys.FileSystem; import filesys.IFileSystem; +import filesys.Offset; import filesys.Usuario; public abstract class FileSystemTestBase { @@ -16,6 +17,8 @@ public abstract class FileSystemTestBase { protected static final String ROOT_USER = "root"; protected static final String ROOT_DIR = "/"; protected static final int READ_BUFFER_SIZE = 256; + protected static final Offset offset = new Offset(0); + protected static final byte[] buffer = new byte[READ_BUFFER_SIZE]; @BeforeAll public static void setUp() throws Exception { diff --git a/tests/LsTest.java b/tests/LsTest.java new file mode 100644 index 0000000..fa04a92 --- /dev/null +++ b/tests/LsTest.java @@ -0,0 +1,44 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; + +public class LsTest extends FileSystemTestBase { + @BeforeEach + public void prepararAmbienteTeste() throws Exception { + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.mkdir("/testes/dir1", ROOT_USER); + fileSystem.touch("/testes/dir1/arquivo1.txt", ROOT_USER); + fileSystem.mkdir("/testes/dir1/subdir", ROOT_USER); + fileSystem.touch("/testes/dir1/subdir/arquivo2.txt", ROOT_USER); + } + + @AfterEach + public void limparAmbienteTeste() throws Exception { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + } + } + + @Test + public void listarDiretorioSimples() { + assertDoesNotThrow(() -> fileSystem.ls("/testes/dir1", ROOT_USER, false)); + } + + @Test + public void listarDiretorioRecursivo() { + assertDoesNotThrow(() -> fileSystem.ls("/testes/dir1", ROOT_USER, true)); + } + + @Test + public void listarDiretorioSemPermissao() { + assertThrows(PermissaoException.class, () -> fileSystem.ls("/testes/dir1", "joao", false)); + } + + @Test + public void listarDiretorioInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.ls("/inexistente", ROOT_USER, false)); + } +} diff --git a/tests/PermissionTest.java b/tests/PermissionTest.java index 4ab94e8..7c3343a 100644 --- a/tests/PermissionTest.java +++ b/tests/PermissionTest.java @@ -1,63 +1,227 @@ package tests; import org.junit.jupiter.api.Test; - import exception.PermissaoException; - -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; // Essa classe testa cenários de permissão public class PermissionTest extends FileSystemTestBase { @Test - public void testMkdirUsersPermissions() throws Exception { - // root: rwx em /** (pode tudo) + public void testMkdirPermissions() throws Exception { + // root pode tudo assertDoesNotThrow(() -> fileSystem.mkdir("/rootTest", "root")); - // maria: rw- em /** (pode criar, mas não pode executar) + // maria rw- em /** (não pode criar diretório, falta x) assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/mariaTest", "maria")); - // luzia: rwx em /** (possui permissão root) + // luzia rwx em /** assertDoesNotThrow(() -> fileSystem.mkdir("/luziaTest", "luzia")); - // carla: r-- em /** (não pode criar em lugar nenhum) + // carla r-- em /** assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/carlaTest", "carla")); - // athos: rwx apenas em /users/athos/** + // athos rwx apenas em /users/athos/** assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/athosTest", "athos")); assertDoesNotThrow(() -> fileSystem.mkdir("/users/athos/teste", "athos")); - // joao: rwx apenas em em /users/joao/** + // joao rwx apenas em /users/joao/** assertDoesNotThrow(() -> fileSystem.mkdir("/users/joao/teste", "joao")); assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/users/athos/joaoTest", "joao")); } @Test - public void testChmodPermissions() throws Exception { - // root: rwx em /** (pode tudo) - assertDoesNotThrow(() -> fileSystem.chmod("/users/athos", "root", "maria", "rwx")); + public void testTouchPermissions() throws Exception { + // root pode tudo + assertDoesNotThrow(() -> fileSystem.touch("/users/athos/teste.txt", "root")); - // luzia agora pode criar no /users/athos - assertDoesNotThrow(() -> fileSystem.mkdir("/users/athos/testeLuzia", "luzia")); + // maria rw- em /** (não pode criar arquivo, falta x) + assertThrows(PermissaoException.class, () -> fileSystem.touch("/users/athos/arquivoMaria.txt", "maria")); + + // luzia rwx em /** + assertDoesNotThrow(() -> fileSystem.touch("/users/athos/arquivoLuzia.txt", "luzia")); + + // carla r-- em /** + // não pode criar arquivo, falta x + assertThrows(PermissaoException.class, () -> fileSystem.touch("/users/athos/arquivoCarla.txt", "carla")); + + // athos rwx apenas em /users/athos/** + assertDoesNotThrow(() -> fileSystem.touch("/users/athos/arquivoAthos.txt", "athos")); + assertThrows(PermissaoException.class, () -> fileSystem.touch("/users/joao/arquivoAthos.txt", "athos")); + + // joao rwx apenas em /users/joao/** + assertDoesNotThrow(() -> fileSystem.touch("/users/joao/arquivoJoao.txt", "joao")); + } + + @Test + public void testLsPermissions() throws Exception { + // root pode listar tudo + assertDoesNotThrow(() -> fileSystem.ls("/users/athos", "root", false)); + + // maria rw- em /** (não pode listar, falta x) + assertThrows(PermissaoException.class, () -> fileSystem.ls("/users/athos", "maria", false)); + + // luzia rwx em /** + assertDoesNotThrow(() -> fileSystem.ls("/users/athos", "luzia", false)); + + // carla r-- em /** + assertThrows(PermissaoException.class, () -> fileSystem.ls("/users/athos", "carla", false)); - // athos não pode alterar permissão de maria - assertThrows(PermissaoException.class, () -> fileSystem.chmod("/users/athos", "athos", "maria", "rwx")); + // athos rwx apenas em /users/athos/** + assertDoesNotThrow(() -> fileSystem.ls("/users/athos", "athos", false)); + assertThrows(PermissaoException.class, () -> fileSystem.ls("/users/joao", "athos", false)); + + // joao rwx apenas em /users/joao/** + assertDoesNotThrow(() -> fileSystem.ls("/users/joao", "joao", false)); } @Test - public void testPermission() throws Exception { - // Usuário com permissão de escrita - assertDoesNotThrow(() -> fileSystem.mkdir("/testMaria", "maria")); + public void testCpPermissions() throws Exception { + fileSystem.mkdir("/testeCopiaRoot", ROOT_USER); + fileSystem.touch("/users/athos/arquivo.txt", ROOT_USER); + fileSystem.chmod("/users/athos/arquivo.txt", ROOT_USER, "athos", "rwx"); + // root pode tudo + assertDoesNotThrow( + () -> fileSystem.cp("/users/athos/arquivo.txt", "/testeCopiaRoot/arquivo.txt", "root", false)); + // athos tem permissão de escrita/leitura + assertDoesNotThrow( + () -> fileSystem.cp("/users/athos/arquivo.txt", "/users/athos/arquivo2.txt", "athos", false)); + // maria não tem permissão + assertThrows(PermissaoException.class, + () -> fileSystem.cp("/users/athos/arquivo.txt", "/testeCopiaRoot/arquivo2.txt", "maria", false)); + } - // Usuário athos não tem permissão para criar no diretório raiz - assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/testAthos", "athos")); + @Test + public void testMvPermissions() throws Exception { + try { + fileSystem.mkdir("/testeMovimentoRoot", ROOT_USER); + fileSystem.touch("/users/athos/arquivo.txt", ROOT_USER); + fileSystem.chmod("/users/athos/arquivo.txt", ROOT_USER, "athos", "rwx"); + } catch (Exception e) { + } + + // root pode tudo + assertDoesNotThrow(() -> fileSystem.mv("/users/athos/arquivo.txt", "/testeMovimentoRoot/arquivo.txt", "root")); + + // maria não pode mover + try { + fileSystem.touch("/users/athos/arquivo.txt", ROOT_USER); + } catch (Exception e) { + } + assertThrows(PermissaoException.class, + () -> fileSystem.mv("/users/athos/arquivo.txt", "/testeMovimentoRoot/arquivo2.txt", "maria")); + } - // Usuário athos pode criar no /home - assertDoesNotThrow(() -> fileSystem.mkdir("/home/testAthos", "athos")); + @Test + public void testWritePermissions() throws Exception { + // Garante que o arquivo existe antes dos testes + try { + fileSystem.touch("/users/athos/arquivo.txt", ROOT_USER); + } catch (Exception e) { + } + + // root pode escrever + assertDoesNotThrow(() -> fileSystem.write("/users/athos/arquivo.txt", "root", false, "abc".getBytes())); + + // maria não pode escrever + assertThrows(PermissaoException.class, + () -> fileSystem.write("/users/athos/arquivo.txt", "maria", false, "abc".getBytes())); + + // luzia pode escrever + assertDoesNotThrow( + () -> fileSystem.write("/users/athos/arquivo.txt", "luzia", false, "abc".getBytes())); + + // carla não pode escrever + assertThrows(PermissaoException.class, + () -> fileSystem.write("/users/athos/arquivo.txt", "carla", false, "abc".getBytes())); + + // athos pode escrever apenas em sua pasta + assertDoesNotThrow(() -> fileSystem.write("/users/athos/arquivo.txt", "athos", false, "abc".getBytes())); + try { + fileSystem.touch("/users/joao/arquivo.txt", "joao"); + } catch (Exception e) { + } + assertThrows(PermissaoException.class, + () -> fileSystem.write("/users/joao/arquivo.txt", "athos", false, "abc".getBytes())); + } - // Usuário root sempre pode - assertDoesNotThrow(() -> fileSystem.mkdir("/testRoot", ROOT_USER)); + @Test + public void testReadPermissions() throws Exception { + fileSystem.touch("/users/athos/texto.txt", ROOT_USER); + fileSystem.write("/users/athos/texto.txt", ROOT_USER, false, "abc".getBytes()); + fileSystem.chmod("/users/athos/texto.txt", ROOT_USER, "athos", "rwx"); + fileSystem.chmod("/users/athos/texto.txt", ROOT_USER, "luzia", "rwx"); + fileSystem.chmod("/users/athos/texto.txt", ROOT_USER, "maria", "rw-"); + fileSystem.chmod("/users/athos/texto.txt", ROOT_USER, "carla", "r--"); + + // root pode ler + assertDoesNotThrow(() -> fileSystem.read("/users/athos/texto.txt", "root", buffer, offset)); + + // maria não pode ler (falta x) + assertThrows(PermissaoException.class, + () -> fileSystem.read("/users/athos/texto.txt", "maria", buffer, offset)); + + // luzia pode ler + assertDoesNotThrow(() -> fileSystem.read("/users/athos/texto.txt", "luzia", buffer, offset)); + + // athos pode ler + assertDoesNotThrow(() -> fileSystem.read("/users/athos/texto.txt", "athos", buffer, offset)); + + // athos não pode ler arquivo de joao + assertThrows(PermissaoException.class, () -> fileSystem.read("/users/joao/texto.txt", "athos", buffer, offset)); + + // joao pode ler seu próprio arquivo + fileSystem.touch("/users/joao/texto.txt", "joao"); + fileSystem.write("/users/joao/texto.txt", "joao", false, "abc".getBytes()); + assertDoesNotThrow(() -> fileSystem.read("/users/joao/texto.txt", "joao", buffer, offset)); } + @Test + public void testRmPermissions() throws Exception { + String path = "/users/athos/rmtest.txt"; + // Garante que o arquivo existe antes dos testes + Runnable setup = () -> { + try { + fileSystem.touch(path, ROOT_USER); + } catch (Exception ignored) { + } + }; + + // root pode remover + setup.run(); + fileSystem.chmod(path, ROOT_USER, "athos", "rwx"); + fileSystem.chmod(path, ROOT_USER, "luzia", "rwx"); + fileSystem.chmod(path, ROOT_USER, "maria", "rw-"); + fileSystem.chmod(path, ROOT_USER, "carla", "r--"); + assertDoesNotThrow(() -> fileSystem.rm(path, "root", false)); + + // athos pode remover + setup.run(); + fileSystem.chmod(path, ROOT_USER, "athos", "rwx"); + assertDoesNotThrow(() -> fileSystem.rm(path, "athos", false)); + + // luzia pode remover + setup.run(); + fileSystem.chmod(path, ROOT_USER, "luzia", "rwx"); + assertDoesNotThrow(() -> fileSystem.rm(path, "luzia", false)); + + // maria não pode remover + setup.run(); + fileSystem.chmod(path, ROOT_USER, "maria", "rw-"); + assertThrows(PermissaoException.class, () -> fileSystem.rm(path, "maria", false)); + + // carla não pode remover + setup.run(); + fileSystem.chmod(path, ROOT_USER, "carla", "r--"); + assertThrows(PermissaoException.class, () -> fileSystem.rm(path, "carla", false)); + } + + @Test + public void testChmodPermissions() throws Exception { + // root pode mudar permissões de qualquer arquivo + assertDoesNotThrow(() -> fileSystem.chmod("/users/athos", "root", "maria", "rwx")); + + // maria não pode mudar permissões de /users/athos + assertDoesNotThrow(() -> fileSystem.mkdir("/users/athos/testeLuzia", "luzia")); + } } diff --git a/tests/ReadTest.java b/tests/ReadTest.java new file mode 100644 index 0000000..7fb8718 --- /dev/null +++ b/tests/ReadTest.java @@ -0,0 +1,47 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; + +public class ReadTest extends FileSystemTestBase { + @BeforeEach + public void prepararAmbienteTeste() throws Exception { + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.touch("/testes/arquivo1.txt", ROOT_USER); + fileSystem.write("/testes/arquivo1.txt", ROOT_USER, false, "abcde".getBytes()); + } + + @AfterEach + public void limparAmbienteTeste() throws Exception { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + } + } + + @Test + public void lerArquivoSimples() { + offset.setValue(0); + assertDoesNotThrow(() -> fileSystem.read("/testes/arquivo1.txt", ROOT_USER, buffer, offset)); + } + + @Test + public void lerArquivoSemPermissao() { + offset.setValue(0); + assertThrows(PermissaoException.class, () -> fileSystem.read("/testes/arquivo1.txt", "joao", buffer, offset)); + } + + @Test + public void lerArquivoInexistente() { + offset.setValue(0); + assertThrows(CaminhoNaoEncontradoException.class, + () -> fileSystem.read("/testes/jooj.txt", ROOT_USER, buffer, offset)); + } + + @Test + public void lerComOffset() throws Exception { + offset.setValue(2); + assertDoesNotThrow(() -> fileSystem.read("/testes/arquivo1.txt", ROOT_USER, buffer, offset)); + } +} diff --git a/tests/RmTest.java b/tests/RmTest.java new file mode 100644 index 0000000..d2fcd28 --- /dev/null +++ b/tests/RmTest.java @@ -0,0 +1,50 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; + +public class RmTest extends FileSystemTestBase { + @BeforeEach + public void prepararAmbienteTeste() throws Exception { + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.mkdir("/testes/origem", ROOT_USER); + fileSystem.touch("/testes/origem/arquivo1.txt", ROOT_USER); + fileSystem.mkdir("/testes/origem/subpasta", ROOT_USER); + fileSystem.touch("/testes/origem/subpasta/arquivo2.txt", ROOT_USER); + } + + @AfterEach + public void limparAmbienteTeste() throws Exception { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + } + } + + @Test + public void removerArquivoSimples() { + assertDoesNotThrow(() -> fileSystem.rm("/testes/origem/arquivo1.txt", ROOT_USER, false)); + } + + @Test + public void removerDiretorioRecursivo() { + assertDoesNotThrow(() -> fileSystem.rm("/testes/origem", ROOT_USER, true)); + } + + @Test + public void removerDiretorioSemRecursivo() { + assertThrows(PermissaoException.class, () -> fileSystem.rm("/testes/origem", ROOT_USER, false)); + } + + @Test + public void removerArquivoInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, + () -> fileSystem.rm("/testes/origem/jooj.txt", ROOT_USER, false)); + } + + @Test + public void removerSemPermissao() { + assertThrows(PermissaoException.class, () -> fileSystem.rm("/testes/origem/arquivo1.txt", "joao", false)); + } +} diff --git a/tests/TouchTest.java b/tests/TouchTest.java new file mode 100644 index 0000000..c013f68 --- /dev/null +++ b/tests/TouchTest.java @@ -0,0 +1,41 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; + +public class TouchTest extends FileSystemTestBase { + @BeforeEach + public void prepararAmbienteTeste() throws Exception { + fileSystem.mkdir("/testes", ROOT_USER); + } + + @AfterEach + public void limparAmbienteTeste() throws Exception { + try { + fileSystem.rm("/testes", ROOT_USER, true); + } catch (Exception e) { + } + } + + @Test + public void criarArquivoSimples() { + assertDoesNotThrow(() -> fileSystem.touch("/testes/arquivo1.txt", ROOT_USER)); + } + + @Test + public void criarArquivoExistente() throws Exception { + fileSystem.touch("/testes/arquivo1.txt", ROOT_USER); + assertThrows(CaminhoJaExistenteException.class, () -> fileSystem.touch("/testes/arquivo1.txt", ROOT_USER)); + } + + @Test + public void criarArquivoSemPermissao() { + assertThrows(PermissaoException.class, () -> fileSystem.touch("/testes/arquivo2.txt", "joao")); + } + + @Test + public void criarArquivoEmDiretorioInexistente() { + assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.touch("/jooj/arquivo.txt", ROOT_USER)); + } +} diff --git a/tests/WriteTest.java b/tests/WriteTest.java new file mode 100644 index 0000000..b6327db --- /dev/null +++ b/tests/WriteTest.java @@ -0,0 +1,44 @@ +package tests; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.*; +import exception.*; + +public class WriteTest extends FileSystemTestBase { + @BeforeEach + public void prepararAmbienteTeste() throws Exception { + fileSystem.mkdir("/testes", ROOT_USER); + fileSystem.touch("/testes/arquivo1.txt", ROOT_USER); + } + + @AfterEach + public void limparAmbienteTeste() throws Exception { + try { fileSystem.rm("/testes", ROOT_USER, true); } catch (Exception e) {} + } + + @Test + public void escreverArquivoSimples() { + byte[] dados = "conteudo hahahahahah".getBytes(); + assertDoesNotThrow(() -> fileSystem.write("/testes/arquivo1.txt", ROOT_USER, false, dados)); + } + + @Test + public void escreverArquivoSemPermissao() { + byte[] dados = "conteudo hahahahahah".getBytes(); + assertThrows(PermissaoException.class, () -> fileSystem.write("/testes/arquivo1.txt", "joao", false, dados)); + } + + @Test + public void escreverArquivoInexistente() { + byte[] dados = "conteudo hahahahahah".getBytes(); + assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.write("/testes/pedrin.txt", ROOT_USER, false, dados)); + } + + @Test + public void anexarArquivo() throws Exception { + byte[] dados1 = "abc".getBytes(); + byte[] dados2 = "def".getBytes(); + fileSystem.write("/testes/arquivo1.txt", ROOT_USER, false, dados1); + assertDoesNotThrow(() -> fileSystem.write("/testes/arquivo1.txt", ROOT_USER, true, dados2)); + } +} diff --git a/users/users b/users/users index e4a0278..a544529 100644 --- a/users/users +++ b/users/users @@ -6,6 +6,8 @@ tiago /** rw- luzia /** rwx carla /** r-- athos /users x +athos /users/athos rwx athos /users/athos/** rwx joao /users x +joao /users/joao rwx joao /users/joao/** rwx From ddbbfc288f3b3cb328a9542c65b2e3990d2fbf17 Mon Sep 17 00:00:00 2001 From: Athoosz Date: Sat, 14 Jun 2025 22:35:13 -0300 Subject: [PATCH 14/14] =?UTF-8?q?feat:=20corrigindo=20bugs=20e=20alterando?= =?UTF-8?q?=20mkdir=20para=20criar=20caminhos=20intermedi=C3=A1rios=20com?= =?UTF-8?q?=20a=20flag=20-p=20por=20padr=C3=A3o?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- filesys/FileSystemImpl.java | 70 +++++++++++++++++++++++-------------- tests/CpTest.java | 1 + tests/MkdirTest.java | 6 ---- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 1487656..cb9cf0d 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -29,26 +29,39 @@ public void mkdir(String caminho, String usuario) if (caminho.equals("/")) return; - verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); - - Diretorio pai = navegarParaDiretorioPai(caminho); - String nomeNovo = extrairNomeFinal(caminho); - - if (pai.buscarSubdiretorio(nomeNovo) != null) { - throw new CaminhoJaExistenteException("O diretório '" + nomeNovo + "' já existe em '" + caminho + "'"); + String[] partes = caminho.split("/"); + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); } - verificarPermissao(obterCaminhoPai(caminho), usuario, 'w'); - - Diretorio novo = new Diretorio(nomeNovo, usuario); - pai.adicionarSubdiretorio(novo); - - // Debug pra testes: Imprime os subdiretorios do diretorio atual - System.out.print("Subdiretorios de '" + pai.getMetaDados().getNome() + "': "); - for (Diretorio d : pai.getSubdiretorios()) { - System.out.print(d.getMetaDados().getNome() + " "); + Diretorio atual = fileSys.getRaiz(); + StringBuilder pathBuilder = new StringBuilder(); + for (int i = 1; i < partes.length; i++) { + if (partes[i].isEmpty()) + continue; + pathBuilder.append("/").append(partes[i]); + String nomeDir = partes[i]; + + Diretorio proximo = atual.buscarSubdiretorio(nomeDir); + boolean ultimo = (i == partes.length - 1); + + if (proximo == null) { + String paiPath = pathBuilder.substring(0, pathBuilder.lastIndexOf("/")); + if (paiPath.isEmpty()) + paiPath = "/"; + verificarPermissaoExecucaoNoCaminho(paiPath, usuario); + verificarPermissao(paiPath, usuario, 'w'); + Diretorio novo = new Diretorio(nomeDir, usuario); + atual.adicionarSubdiretorio(novo); + atual = novo; + } else { + if (ultimo) { + throw new CaminhoJaExistenteException( + "O diretório '" + nomeDir + "' já existe em '" + caminho + "'"); + } + atual = proximo; + } } - System.out.println(); } @Override @@ -278,6 +291,10 @@ public void cp(String caminhoOrigem, String caminhoDestino, String usuario, bool throws CaminhoNaoEncontradoException, PermissaoException { verificaUsuarioValido(usuario); + + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminhoOrigem), usuario); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminhoDestino), usuario); + // Localiza origem e destino Diretorio dirOrigemPai = navegarParaDiretorioPai(caminhoOrigem); Diretorio dirDestino = navegarParaDiretorioPai(caminhoDestino); @@ -411,8 +428,16 @@ private void verificarPermissaoExecucaoNoCaminho(String caminho, String usuario) if (usuario.equals(ROOT_USER)) return; + // Trata casos especiais de caminho vazio ou "/" + if (caminho == null || caminho.isEmpty() || caminho.equals("/")) { + if (!temPermissao("/", usuario, 'x')) { + throw new PermissaoException( + "Usuário '" + usuario + "' não tem permissão 'x' em '/'"); + } + return; + } + String[] partes = caminho.split("/"); - Diretorio atual = fileSys.getRaiz(); StringBuilder pathBuilder = new StringBuilder(); for (int i = 1; i < partes.length; i++) { if (partes[i].isEmpty()) @@ -422,15 +447,6 @@ private void verificarPermissaoExecucaoNoCaminho(String caminho, String usuario) throw new PermissaoException( "Usuário '" + usuario + "' não tem permissão 'x' em '" + pathBuilder + "'"); } - Diretorio encontrado = atual.buscarSubdiretorio(partes[i]); - if (encontrado == null) - break; - atual = encontrado; - } - // Sempre checa permissão 'x' em '/' se o caminho for exatamente "/" - if (caminho.equals("/") && !temPermissao("/", usuario, 'x')) { - throw new PermissaoException( - "Usuário '" + usuario + "' não tem permissão 'x' em '/'"); } } diff --git a/tests/CpTest.java b/tests/CpTest.java index 3feed70..92992f3 100644 --- a/tests/CpTest.java +++ b/tests/CpTest.java @@ -108,6 +108,7 @@ public void copiarPastaVazia() throws Exception { @Test public void copiarArquivoGrande() throws Exception { byte[] dadosGrandes = new byte[1024]; // 1KB de dados + fileSystem.touch("/testes/origem/arquivogrande.txt", ROOT_USER); fileSystem.write("/testes/origem/arquivogrande.txt", ROOT_USER, false, dadosGrandes); assertDoesNotThrow(() -> fileSystem.cp("/testes/origem/arquivogrande.txt", "/testes/destino/copia_grande.txt", diff --git a/tests/MkdirTest.java b/tests/MkdirTest.java index 17a454c..fe02c30 100644 --- a/tests/MkdirTest.java +++ b/tests/MkdirTest.java @@ -6,7 +6,6 @@ import org.junit.jupiter.api.Test; import exception.CaminhoJaExistenteException; -import exception.CaminhoNaoEncontradoException; public class MkdirTest extends FileSystemTestBase { @@ -21,11 +20,6 @@ public void testCriarDiretorioJaExistente() throws Exception { assertThrows(CaminhoJaExistenteException.class, () -> fileSystem.mkdir("/home", "root")); } - @Test - public void testCriarDiretorioSemPai() { - assertThrows(CaminhoNaoEncontradoException.class, () -> fileSystem.mkdir("/naoexiste/filho", "root")); - } - @Test public void testCriarDiretorioComPai() throws Exception { fileSystem.mkdir("/pai", "root");