int main(int argc, char **argv) { struct mbr_partition ppp; size_t bootsize; int c; int boot00[512/sizeof(int)]; int devfd = -1; char *bp; while ((c = getopt(argc, argv, "vn")) != EOF) { switch (c) { case 'n': nowrite = 1; break; case 'v': verbose = 1; break; default: usage(); break; } } if (argc - optind < 2) usage(); boot = argv[optind]; dev = argv[optind + 1]; if (verbose) { printf("boot: %s\n", boot); printf("dev: %s\n", dev); } if ((bp = load_boot(boot, &bootsize)) == NULL) return 1; if ((devfd = open(dev, O_RDONLY, 0)) < 0) { warn("open: %s", dev); goto out; } if (load_prep_partition(devfd, &ppp)) { warn("load_prep_partition"); goto out; } if (bootsize + dbtob(2) > dbtob(ppp.mbrp_size)) { warn("boot image is too big."); goto out; } close(devfd); if (nowrite) { free(bp); return 0; } if ((devfd = open(dev, O_RDWR, 0)) < 0) { warn("open: %s", dev); goto out; } /* * Write boot image. */ memset(boot00, 0, sizeof(boot00)); (void)lseek(devfd, (off_t)dbtob(ppp.mbrp_start), SEEK_SET); if (write(devfd, boot00, sizeof(boot00)) != sizeof(boot00)) { warn("write boot00(prep mbr)"); goto out; } (void)lseek(devfd, (off_t)dbtob(ppp.mbrp_start+1), SEEK_SET); boot00[0] = htole32(dbtob(2)); boot00[1] = htole32(bootsize); if (write(devfd, boot00, sizeof(boot00)) != sizeof(boot00)) { warn("write boot00(prep start/size)"); goto out; } if (devread(devfd, boot00, 1, DEV_BSIZE, "start/size") != 0) goto out; boot00[0] = htole32(dbtob(ppp.mbrp_start)); boot00[1] = htole32(bootsize + dbtob(2)); (void)lseek(devfd, (off_t)dbtob(1), SEEK_SET); if (write(devfd, boot00, sizeof(boot00)) != sizeof(boot00)) { warn("write boot00(master start/size)"); goto out; } (void)lseek(devfd, (off_t)dbtob(ppp.mbrp_start+2), SEEK_SET); if (write(devfd, bp, bootsize) != bootsize) { warn("write boot loader"); goto out; } close(devfd); free(bp); return 0; out: if (devfd >= 0) close(devfd); if (bp != NULL) free(bp); return 1; }
/* * Main program */ int main(int argc, char **argv) { int sock_fd, serv_len, n; struct sockaddr_in serv_addr; struct hostent *serv; struct { char message[BUFFER]; int uuid; } msg_in, msg_out; /* Generate a random UUID */ srand(time(NULL)); uuid = rand(); clearScreen(); char *input; command *cmd; size_t buffer = BUFFER; while (TRUE) { /* Display prompt */ printPrompt(); /* malloc input to memory */ input = (char *)malloc(sizeof(char) * BUFFER); /* Clear msg_in and msg_out */ bzero((char *)msg_in.message, sizeof(msg_in.message)); bzero((char *)msg_out.message, sizeof(msg_out.message)); msg_in.uuid = -1; msg_out.uuid = uuid; /* Get input */ getline(&input, &buffer, stdin); input[strcspn(input, "\n")] = '\0'; //Remove trailing '\n' /* Create command */ cmd = new_command(input); /* Output redirection */ int file_out, con_out; if (cmd->output_file) { file_out = open(cmd->output_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (file_out < 0) { perror("open"); break; } con_out = dup(STDOUT_FILENO); dup2(file_out, STDOUT_FILENO); close(file_out); } /* Execute user command if possible */ switch (check_command(cmd->name)) { case HELP: //help printHelp(); break; case FMOUNT: //fmount if (serv_uuid != -1) { printf("[ERROR] You are already connected to a server\n"); break; } if (cmd->argc != 2) { printf("[ERROR] Usage: fmount <server>\n"); break; } printf("Connecting to `%s`... ", cmd->argv[1]); fflush(stdout); //Safety precaution /* Parse server */ serv = gethostbyname(cmd->argv[1]); /* Open UDP socket */ sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock_fd < 0) { perror("socket"); break; } /* Write zero's to serv_addr */ bzero((char *)&serv_addr, sizeof(serv_addr)); /* Set up server */ serv_addr.sin_family = AF_INET; bcopy(serv->h_addr, (char *)&serv_addr.sin_addr, serv->h_length); serv_addr.sin_port = htons(PORT); serv_len = sizeof(serv_addr); /* Send CONNECT command to server */ sprintf(msg_out.message, "CONNECT"); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Get response from server */ n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("recvfrom"); break; } if (strcmp(msg_in.message, "CONNECT") != 0) { printf("[ERROR] Invalid response from server\n"); break; } /* Save server UUID */ serv_uuid = msg_in.uuid; /* Clear msg_in and msg_out */ bzero((char *)&msg_out.message, sizeof(msg_out.message)); bzero((char *)&msg_in.message, sizeof(msg_in.message)); msg_out.uuid = uuid; msg_in.uuid = -1; /* Get SECTOR 0 from server */ sprintf(msg_out.message, "GETSECTOR 0"); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Get response from server */ n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("recvfrom"); break; } /* Load bytes into Fat12Boot */ load_boot((unsigned char *)msg_in.message); /* malloc Fat12Entry */ entry = (Fat12Entry *)malloc(sizeof(Fat12Entry) * boot.MAX_ROOT_DIRS); /* Request all ROOT_DIRECTORY sector entries */ for (int i = 0; i < 14; i++) { /* Clear msg_in and msg_out */ bzero((char *)&msg_out.message, sizeof(msg_out.message)); bzero((char *)&msg_in.message, sizeof(msg_in.message)); msg_out.uuid = uuid; msg_in.uuid = -1; /* Get ROOT DIRECTORY sector from server */ sprintf(msg_out.message, "GETSECTOR %d", ((boot.NUM_OF_FATS * boot.SECTORS_PER_FAT) + 1) + i); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Get response from server */ n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("recvfrom"); break; } /* Load bytes into Fat12Entry */ load_entry(16 * i, (unsigned char *)msg_in.message); } printf("Connected!\n"); break; case FUMOUNT: //fumount if (serv_uuid == -1) { printf("[ERROR] You are not connected to any server\n"); break; } if (cmd->argc != 1) { printf("[ERROR] Usage: fumount\n"); break; } sprintf(msg_out.message, "DISCONNECT"); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Close and write zero's to server */ close(sock_fd); bzero((char *)&serv_addr, sizeof(serv_addr)); serv_uuid = -1; break; case STRUCTURE: //structure if (serv_uuid == -1) { printf("[ERROR] You are not connected to any server\n"); break; } if (cmd->argc > 2) { printf("[ERROR] Usage: structure [-l]\n"); break; } else if (cmd->argc == 2) { if (strcmp(cmd->argv[1], "-l") != 0) { printf("[ERROR] Usage: structure [-l]\n"); break; } } printf(" number of FAT: %d\n", boot.NUM_OF_FATS); printf(" number of sectors used by FAT: %d\n", boot.SECTORS_PER_FAT); printf(" number of sectors per cluster: %d\n", boot.SECTORS_PER_CLUSTER); printf(" number of ROOT Entries: %d\n", boot.MAX_ROOT_DIRS); printf(" number of bytes per sector %d\n", boot.BYTES_PER_SECTOR); if (cmd->argc == 2) { printf(" ---Sector #--- ---Sector Types---\n"); printf(" 0 BOOT\n"); for (int i = 0; i < boot.NUM_OF_FATS; i++) printf(" %02d -- %02d FAT%d\n", (boot.SECTORS_PER_FAT * i) + 1, boot.SECTORS_PER_FAT * (i + 1), i); printf(" %02d -- %02d ROOT DIRECTORY\n", boot.SECTORS_PER_FAT * boot.NUM_OF_FATS, (boot.MAX_ROOT_DIRS / 16) + (boot.SECTORS_PER_FAT * boot.NUM_OF_FATS)); } break; case TRAVERSE: //traverse if (serv_uuid == -1) { printf("[ERROR] You are not connected to any server\n"); break; } if (cmd->argc > 2) { printf("[ERROR] Usage: traverse [-l]\n"); break; } else if (cmd->argc == 2) { if (strcmp(cmd->argv[1], "-l") != 0) { printf("[ERROR] Usage: traverse [-l]\n"); break; } } if (cmd->argc == 2) { printf(" *****************************\n"); printf(" ** FILE ATTRIBUTE NOTATION **\n"); printf(" ** **\n"); printf(" ** R ------ READ ONLY FILE **\n"); printf(" ** S ------ SYSTEM FILE **\n"); printf(" ** H ------ HIDDEN FILE **\n"); printf(" ** A ------ ARCHIVE FILE **\n"); printf(" *****************************\n"); printf("\n"); for (int i = 0; i < boot.MAX_ROOT_DIRS; i++) { if (entry[i].FILENAME[0] != 0x00 && entry[i].START_CLUSTER != 0) { char attr[6] = {'-', '-', '-', '-', '-'}; unsigned char a = entry[i].ATTRIBUTES[0]; if (a == 0x01) attr[0] = 'R'; if (a == 0x02) attr[1] = 'H'; if (a == 0x04) attr[2] = 'S'; if (a == 0x20) attr[5] = 'A'; if (a == 0x10) { for (int j = 0; j < 6; j++) attr[j] = '-'; } if (entry[i].ATTRIBUTES[0] == 0x10) { printf("%.6s %d %d < DIR > /%.8s %d\n", attr, entry[i].CREATION_DATE, entry[i].CREATION_TIME, entry[i].FILENAME, entry[i].START_CLUSTER); printf("%.6s %d %d < DIR > /%.8s/. %d\n", attr, entry[i].CREATION_DATE, entry[i].CREATION_TIME, entry[i].FILENAME, entry[i].START_CLUSTER); printf("%.6s %d %d < DIR > /%.8s/.. %d\n", attr, entry[i].CREATION_DATE, entry[i].CREATION_TIME, entry[i].FILENAME, 0); } else { printf("%.6s %d %d %lu /%.8s.%.3s %d\n", attr, entry[i].CREATION_DATE, entry[i].CREATION_TIME, entry[i].FILE_SIZE, entry[i].FILENAME, entry[i].EXT, entry[i].START_CLUSTER); } } } } else { for (int i = 0; i < boot.MAX_ROOT_DIRS; i++) { if (entry[i].FILENAME[0] != 0x00 && entry[i].START_CLUSTER != 0) { if (entry[i].ATTRIBUTES[0] == 0x10) { printf("/%.8s < DIR >\n", entry[i].FILENAME); printf("/%.8s/. < DIR >\n", entry[i].FILENAME); printf("/%.8s/.. < DIR >\n", entry[i].FILENAME); } else { printf("/%.8s.%.3s\n", entry[i].FILENAME, entry[i].EXT); } } } } break; case SHOWFAT: //showfat if (serv_uuid == -1) { printf("[ERROR] You are not connected to any server\n"); break; } if (cmd->argc != 1) { printf("[ERROR] Usage: showfat\n"); break; } int sectors = (boot.NUM_OF_FATS * boot.SECTORS_PER_FAT); int count = 0; printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); /* Send GETSECTOR command to server */ for (int i = 1; i <= sectors; i++) { sprintf(msg_out.message, "GETSECTOR %d", i); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Get response from server */ n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("sendto"); break; } /* Check server UUID */ if (serv_uuid != msg_in.uuid) { printf("[ERROR] Invalid server UUID - Connection rejected\n"); break; } for (int j = 0; j < boot.BYTES_PER_SECTOR; j++) { if (count % 16 == 0 || count == 0) { printf("\n"); printf("%4x", count); } printf("%5x", (unsigned char)msg_in.message[j]); count++; } } printf("\n"); break; case SHOWSECTOR: //showsector if (serv_uuid == -1) { printf("[ERROR] You are not connected to any server\n"); break; } if (cmd->argc != 2) { printf("[ERROR] Usage: showsector <sector>\n"); break; } /* Parse sector */ int sector = atoi(cmd->argv[1]); /* Send GETSECTOR command to server */ sprintf(msg_out.message, "GETSECTOR %d", sector); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } /* Get response from server */ n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("recvfrom"); break; } /* Check for valid server UUID */ if (serv_uuid != msg_in.uuid) { printf("[ERROR] Invalid server UUID - Connection rejected\n"); break; } /* Read response */ printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); for (int i = 0; i < boot.BYTES_PER_SECTOR; i++) { if (i % 16 == 0 || i == 0) { printf("\n"); printf("%4x", i); } printf("%5x", (unsigned char)msg_in.message[i]); } printf("\n"); break; case SHOWFILE: //showfile if (serv_uuid == -1) { printf("[ERROR] You are not connected to a server\n"); break; } if (cmd->argc != 2) { printf("[ERROR] Usage: showfile <filename>\n"); break; } char filename[12] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' , '\0'}; int index = 0, k; for (k = 0; k < strlen(cmd->argv[1]) && k < 9; k++) { if (cmd->argv[1][k] == '.') { k++; break; } filename[index] = cmd->argv[1][k]; index++; } index = 8; for (int j = k; j < strlen(cmd->argv[1]) && j < 12; j++) { if (cmd->argv[1][j] == '\n' || cmd->argv[1][j] == '\0') { break; } filename[index] = cmd->argv[1][j]; index++; } for (int i = 0; i < boot.MAX_ROOT_DIRS; i++) { if (entry[i].FILENAME != 0x00 && entry[i].START_CLUSTER != 0) { if (compare_char(filename, (char *)entry[i].FILENAME)) { int sector = ((boot.MAX_ROOT_DIRS / 16) + (boot.SECTORS_PER_FAT * boot.NUM_OF_FATS) - 1) + entry[i].START_CLUSTER; int size = (entry[i].FILE_SIZE / 512) + 1; int count = 0; printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); for (int p = sector; p <= sector + size + 1; p++) { sprintf(msg_out.message, "GETSECTOR %d", p); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); break; } n = recvfrom(sock_fd, &msg_in, sizeof(msg_in), 0, (struct sockaddr *)&serv_addr, (socklen_t *)&serv_len); if (n < 0) { perror("recvfrom"); break; } if (serv_uuid != msg_in.uuid) { printf("[ERROR] Invalid server UUID - Connection reject\n"); break; } for (int j = 0; j < boot.BYTES_PER_SECTOR; j++) { if (j % 16 == 0 || j == 0) { printf("\n"); printf("%4x", count++); } printf("%5x", (unsigned char)msg_in.message[j]); } } printf("\n"); } } } break; case EXIT: //exit free(input); delete_command(cmd); if (serv_uuid != -1) { /* Send DISCONNECT command to server */ sprintf(msg_out.message, "DISCONNECT"); n = sendto(sock_fd, &msg_out, sizeof(msg_out), 0, (struct sockaddr *)&serv_addr, (socklen_t)serv_len); if (n < 0) { perror("sendto"); exit(EXIT_FAILURE); } close(sock_fd); bzero((char *)&serv_addr, sizeof(serv_addr)); serv_uuid = -1; } exit(EXIT_SUCCESS); case INVALID_CMD: //Invalid command (default) printf("[ERROR] %s: Command not found\n", cmd->name); break; } fflush(stdout); //Safety precaution /* Restore output */ if (cmd->output_file) { dup2(con_out, STDOUT_FILENO); close(con_out); } /* Free memory */ free(input); delete_command(cmd); } }