diff --git a/Main.java b/Main.java index 3b8673a..bcb2766 100644 --- a/Main.java +++ b/Main.java @@ -1,5 +1,9 @@ import filesys.IFileSystem; +import filesys.Offset; +import filesys.Usuario; +import java.util.HashMap; +import java.util.Map; import java.util.Scanner; import java.io.FileNotFoundException; @@ -13,8 +17,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 = "/"; @@ -29,28 +33,33 @@ public class Main { // Usuário que está executando o programa private static String user; - // O sistema de arquivos é inteiramente virtual, ou seja, será reiniciado a cada execução do programa. - // Logo, não é necessário salvar os arquivos em disco. O sistema será uma simulação em memória. + // O sistema de arquivos é inteiramente virtual, ou seja, será reiniciado a cada + // execução do programa. + // Logo, não é necessário salvar os arquivos em disco. O sistema será uma + // simulação em memória. public static void main(String[] args) { // Usuário que está executando o programa. - // Para quaisquer operações que serão feitas por esse usuário em um caminho /path/**, + // Para quaisquer operações que serão feitas por esse usuário em um caminho + // /path/**, // deve-se checar se o usuário tem permissão de escrita (r) neste caminho. if (args.length < 2) { System.out.println("Usuário não fornecido"); return; } user = args[1]; - + // Carrega a lista de usuários do sistema a partir de arquivo // Formato do arquivo users: - // username dir permission + // username dir permission // Exemplo: - // maria /** rw- - // luzia /** rwx + // maria /** rw- + // luzia /** rwx // Essa permissão vale para o diretório raiz e sub diretórios. - // A partir do momento que um usuário cria outro diretório ou arquivo, - // a permissão desse usuário é de leitura, escrita e execução nesse novo diretório/arquivo, + // A partir do momento que um usuário cria outro diretório ou arquivo, + // a permissão desse usuário é de leitura, escrita e execução nesse novo + // diretório/arquivo, // e sempre será rwx para o usuário root. + Map usuariosMap = new HashMap<>(); try { Scanner userScanner = new Scanner(new java.io.File("users/users")); while (userScanner.hasNextLine()) { @@ -61,13 +70,18 @@ public static void main(String[] args) { String userListed = parts[0]; String dir = parts[1]; String dirPermission = parts[2]; - - /* A FAZER: - * Processar a permissão de todos os usuários existentes por diretório. - * Por enquanto esse código somente imprime as permissões contidas no arquivo users. - */ - System.out.println(userListed + " " + dir + " " + dirPermission); // Somente imprime o usuário, diretório e permissão + /* + * A FAZER: + * Processar a permissão de todos os usuários existentes por diretório. + * Por enquanto esse código somente imprime as permissões contidas no arquivo + * users. --- FEITO + */ + 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); @@ -80,19 +94,21 @@ public static void main(String[] args) { return; } - + // Finalmente cria o Sistema de Arquivos // Lista de usuários é imutável durante a execução do programa // Obs: Como passar a lista de usuários para o FileSystem? - fileSystem = new FileSystem(/*usuários?*/); + fileSystem = new FileSystem(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) { - // System.out.println(e.getMessage()); - // } + try { + fileSystem.mkdir(ROOT_DIR, ROOT_USER); + fileSystem.mkdir("/home", ROOT_USER); + } catch (CaminhoJaExistenteException | PermissaoException | CaminhoNaoEncontradoException e) { + System.out.println(e.getMessage()); + } // Menu interativo. menu(); @@ -152,7 +168,7 @@ public static void menu() { return; default: System.out.println("Comando inválido!"); - } + } } catch (CaminhoNaoEncontradoException | CaminhoJaExistenteException | PermissaoException e) { System.out.println("Erro: " + e.getMessage()); } @@ -171,14 +187,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); } @@ -187,14 +203,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 { + public static void touch() throws CaminhoJaExistenteException, CaminhoNaoEncontradoException, PermissaoException { System.out.println("Insira o caminho do arquivo a ser criado:"); String caminho = scanner.nextLine(); - + fileSystem.touch(caminho, user); } @@ -206,24 +222,39 @@ 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]; + + 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:"); String caminhoNovo = scanner.nextLine(); - + fileSystem.mv(caminhoAntigo, caminhoNovo, user); } @@ -232,7 +263,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); } @@ -243,7 +274,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/filesys/Arquivo.java b/filesys/Arquivo.java new file mode 100644 index 0000000..3acb55a --- /dev/null +++ b/filesys/Arquivo.java @@ -0,0 +1,28 @@ +package filesys; + +import java.util.ArrayList; +import java.util.List; + +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); + 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..77ac1b6 --- /dev/null +++ b/filesys/Diretorio.java @@ -0,0 +1,57 @@ +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); + } + + 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/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/FileSystem.java b/filesys/FileSystem.java index 8d7a83b..e8a8398 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 @@ -20,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 { + public void mkdir(String caminho, String usuario) + throws CaminhoJaExistenteException, PermissaoException, CaminhoNaoEncontradoException { fileSystemImpl.mkdir(caminho, usuario); } @@ -31,7 +34,8 @@ 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); } @@ -42,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 { + throws CaminhoNaoEncontradoException, PermissaoException, CaminhoJaExistenteException { fileSystemImpl.mv(caminhoAntigo, caminhoNovo, usuario); } diff --git a/filesys/FileSystemImpl.java b/filesys/FileSystemImpl.java index 45fa05d..cb9cf0d 100644 --- a/filesys/FileSystemImpl.java +++ b/filesys/FileSystemImpl.java @@ -1,5 +1,8 @@ package filesys; +import java.util.ArrayList; +import java.util.Map; + import exception.CaminhoJaExistenteException; import exception.CaminhoNaoEncontradoException; import exception.PermissaoException; @@ -10,61 +13,586 @@ // 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, CaminhoNaoEncontradoException { + verificaUsuarioValido(usuario); + + if (caminho.equals("/")) + return; + + String[] partes = caminho.split("/"); + if (!partes[0].isEmpty()) { + throw new IllegalArgumentException("Caminho inválido: deve começar com '/'"); + } + + 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; + } + } } @Override public void chmod(String caminho, String usuario, String usuarioAlvo, String permissao) throws CaminhoNaoEncontradoException, PermissaoException { - throw new UnsupportedOperationException("Método não implementado 'chmod'"); + verificaUsuarioValido(usuario); + verificaUsuarioValido(usuarioAlvo); + + // 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 + "'"); + } + + if (caminho.equals("/")) { + fileSys.getRaiz().getMetaDados().setPermissao(usuarioAlvo, permissao); + return; + } + + 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 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."); + } + + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + 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 - 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); + } + + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + + 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 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'); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + + Diretorio pai = navegarParaDiretorioPai(caminho); + String nomeArquivo = extrairNomeFinal(caminho); + Arquivo arquivo = pai.buscarArquivo(nomeArquivo); + + if (arquivo == null) { + throw new CaminhoNaoEncontradoException("Arquivo '" + nomeArquivo + "' não encontrado."); + } + + 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'); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminho), usuario); + + 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 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); + + if (caminhoAntigo.equals("/") || caminhoNovo.equals("/")) { + 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'); + + // 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 - 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 { + verificaUsuarioValido(usuario); + + // Verifica se o caminho é válido + if (caminho == null || caminho.isEmpty() || !caminho.startsWith("/")) { + throw new CaminhoNaoEncontradoException("Caminho inválido: " + caminho); + } + + verificarPermissaoExecucaoNoCaminho(caminho, usuario); + + Diretorio dir = caminho.equals("/") ? fileSys.getRaiz() : navegarParaDiretorioCompleto(caminho); + + verificarPermissao(caminho, usuario, 'r'); + 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 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); + + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminhoOrigem), usuario); + verificarPermissaoExecucaoNoCaminho(obterCaminhoPai(caminhoDestino), 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) { + 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 + // 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 '/'"); + } + + 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) { + 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]; + } + + // 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 verificarPermissaoExecucaoNoCaminho(String caminho, String usuario) + throws PermissaoException, CaminhoNaoEncontradoException { + 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("/"); + 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 + "'"); + } + } } - public void addUser(String user) { - throw new UnsupportedOperationException("Método não implementado 'addUser'"); + 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 + + try { + Diretorio pai = navegarParaDiretorioPai(caminho); + String nome = extrairNomeFinal(caminho); + + Arquivo arq = pai.buscarArquivo(nome); + if (arq != null) { + if (arq.getMetaDados().temPermissao(usuario, tipo)) { + return true; + } + } + Diretorio dir = pai.buscarSubdiretorio(nome); + if (dir != null) { + if (dir.getMetaDados().temPermissao(usuario, tipo)) { + return true; + } + } + // Se for o diretório raiz + if (caminho.equals("/")) { + if (fileSys.getRaiz().getMetaDados().temPermissao(usuario, tipo)) { + return true; + } + } + } catch (Exception e) { + // 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; + } + + private void removerDiretorioRecursivamente(Diretorio dir) { + // Remove arquivos do diretório + for (Arquivo arquivo : new ArrayList<>(dir.getArquivos())) { + dir.removerArquivo(arquivo.getMetaDados().getNome()); + } + + // Remove subdiretórios recursivamente + for (Diretorio subdir : new ArrayList<>(dir.getSubdiretorios())) { + removerDiretorioRecursivamente(subdir); + dir.removerSubdiretorio(subdir.getMetaDados().getNome()); + } + } + + /* + * 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; + } + + 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/IFileSystem.java b/filesys/IFileSystem.java index a0f0ce0..e1cfdeb 100644 --- a/filesys/IFileSystem.java +++ b/filesys/IFileSystem.java @@ -14,14 +14,14 @@ 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. 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. @@ -31,12 +31,14 @@ 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. // 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 new file mode 100644 index 0000000..6e02f3e --- /dev/null +++ b/filesys/MetaDados.java @@ -0,0 +1,50 @@ +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; + } + + public void setNome(String nomeDestino) { + this.nome = nomeDestino; + } +} diff --git a/filesys/Offset.java b/filesys/Offset.java new file mode 100644 index 0000000..cd315f4 --- /dev/null +++ b/filesys/Offset.java @@ -0,0 +1,21 @@ +package filesys; + +public class Offset { + private int value; + + public Offset(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public void add(int delta) { + value += delta; + } +} \ No newline at end of file diff --git a/filesys/Usuario.java b/filesys/Usuario.java new file mode 100644 index 0000000..e19af02 --- /dev/null +++ b/filesys/Usuario.java @@ -0,0 +1,78 @@ +package filesys; + +import java.util.HashMap; +import java.util.Map; + +public class Usuario { + private final String nome; + private final Map permissoesPorCaminho; // ex: "/**" -> "rwx" + + public Usuario(String nome, String permissao) { + this.nome = nome; + 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); + // 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("/*")) { + 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() { + return nome; + } + + public boolean podeLer() { + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("r"); + } + + public boolean podeEscrever() { + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("w"); + } + + public boolean podeExecutar() { + String permissao = permissoesPorCaminho.get("**"); + return permissao != null && permissao.contains("x"); + } + + public String getPermissao() { + return permissoesPorCaminho.get("**"); + } +} 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/CpTest.java b/tests/CpTest.java new file mode 100644 index 0000000..92992f3 --- /dev/null +++ b/tests/CpTest.java @@ -0,0 +1,117 @@ +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.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", + ROOT_USER, false)); + } +} \ No newline at end of file diff --git a/tests/FileSystemTestBase.java b/tests/FileSystemTestBase.java new file mode 100644 index 0000000..45ca2fb --- /dev/null +++ b/tests/FileSystemTestBase.java @@ -0,0 +1,48 @@ +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.Offset; +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; + 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 { + 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/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/MkdirTest.java b/tests/MkdirTest.java new file mode 100644 index 0000000..fe02c30 --- /dev/null +++ b/tests/MkdirTest.java @@ -0,0 +1,28 @@ +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; + +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 testCriarDiretorioComPai() throws Exception { + fileSystem.mkdir("/pai", "root"); + assertDoesNotThrow(() -> fileSystem.mkdir("/pai/filho", "root")); + } +} 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 diff --git a/tests/PermissionTest.java b/tests/PermissionTest.java index 6026e31..7c3343a 100644 --- a/tests/PermissionTest.java +++ b/tests/PermissionTest.java @@ -1,26 +1,227 @@ package tests; -import static org.junit.Assert.assertTrue; - import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.Assertions.*; -import org.junit.jupiter.api.BeforeAll; - -import filesys.FileSystemImpl; -import filesys.IFileSystem; +import exception.PermissaoException; +import static org.junit.jupiter.api.Assertions.*; // Essa classe testa cenários de permissão -public class PermissionTest { - private static IFileSystem fileSystem; +public class PermissionTest extends FileSystemTestBase { + + @Test + public void testMkdirPermissions() throws Exception { + // root pode tudo + assertDoesNotThrow(() -> fileSystem.mkdir("/rootTest", "root")); + + // maria rw- em /** (não pode criar diretório, falta x) + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/mariaTest", "maria")); + + // luzia rwx em /** + assertDoesNotThrow(() -> fileSystem.mkdir("/luziaTest", "luzia")); + + // carla r-- em /** + 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 /users/joao/** + assertDoesNotThrow(() -> fileSystem.mkdir("/users/joao/teste", "joao")); + assertThrows(PermissaoException.class, () -> fileSystem.mkdir("/users/athos/joaoTest", "joao")); + } + + @Test + public void testTouchPermissions() throws Exception { + // root pode tudo + assertDoesNotThrow(() -> fileSystem.touch("/users/athos/teste.txt", "root")); + + // 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 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 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)); + } + + @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")); + } + + @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())); + } + + @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)); - @BeforeAll - public static void setUp() { - fileSystem = new FileSystemImpl(/*args...*/); + // 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 testPermission() { - // Teste de permissão - assertTrue(true); + 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 58c2992..a544529 100644 --- a/users/users +++ b/users/users @@ -4,4 +4,10 @@ joao /** rw- pedro /** rw- tiago /** rw- luzia /** rwx -carla /** r-- \ No newline at end of file +carla /** r-- +athos /users x +athos /users/athos rwx +athos /users/athos/** rwx +joao /users x +joao /users/joao rwx +joao /users/joao/** rwx