-
-
Save limelier/5a7ba8ab166a1f586a3c4feec355b83b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdlib.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdbool.h> | |
#define E_PID fprintf(stderr, "[%d] ", pid); | |
#define PID printf("[%d] ", pid); | |
struct instr { | |
int code; | |
int qty; | |
}; | |
struct instr ReadInstruction(FILE* instr_file); | |
void ExecuteInstructions(int stocks_fd, FILE* instr_file); | |
pid_t pid; | |
int main(int argc, char* argv[]) { | |
pid = getpid(); | |
PID printf("Began execution.\n"); | |
// take args | |
if (argc != 3) { | |
E_PID fprintf(stderr, "Usage: ./mycritsec3.c <stocks_file> <instr_file> \n"); | |
exit(1); | |
} | |
char* stocks_path = argv[1]; | |
char* instr_path = argv[2]; | |
// open stocks file | |
int stocks_fd = open(stocks_path, O_RDWR); | |
if (stocks_fd == -1) { | |
E_PID perror("Error opening stocks file"); | |
exit(2); | |
} | |
// open instruction file | |
FILE* instr_file = fopen(instr_path, "r"); | |
if (instr_file == NULL) { | |
E_PID perror("Error opening instruction file"); | |
exit(3); | |
} | |
/// stuff happens | |
ExecuteInstructions(stocks_fd, instr_file); | |
close(stocks_fd); | |
fclose(instr_file); | |
PID printf("Finished execution succesfully.\n"); | |
return 0; | |
} | |
struct instr ReadInstruction(FILE* instr_file) { | |
struct instr instr; | |
fscanf(instr_file, "%d %d\n", &(instr.code), &(instr.qty)); | |
if (ferror(instr_file)) { | |
E_PID perror("Error reading instruction"); | |
exit(4); | |
} | |
return instr; | |
} | |
void ExecuteInstructions(int stocks_fd, FILE* instr_file) { | |
// write lock struct for the next 4B | |
struct flock qty_lock; | |
qty_lock.l_type = F_WRLCK; | |
qty_lock.l_whence = SEEK_CUR; | |
qty_lock.l_start = 0; | |
qty_lock.l_len = sizeof(int); | |
// unlock struct for the previous 4B | |
struct flock qty_unlock; | |
qty_unlock.l_type = F_UNLCK; | |
qty_unlock.l_type = SEEK_CUR; | |
qty_unlock.l_start = -sizeof(int); | |
qty_unlock.l_len = sizeof(int); | |
// lock struct for the next 8B | |
struct flock field_lock; | |
field_lock.l_type = F_WRLCK; | |
field_lock.l_whence = SEEK_END; | |
field_lock.l_start = 0; | |
field_lock.l_len = 2 * sizeof(int); | |
// unlock struct for the previous 8B | |
struct flock field_unlock; | |
field_lock.l_type = F_UNLCK; | |
field_lock.l_whence = SEEK_END; | |
field_lock.l_start = -2 * sizeof(int); | |
field_lock.l_len = 2 * sizeof(int); | |
struct instr instr; | |
int ret_code; | |
bool found_code; | |
int crt_code, crt_qty; | |
while (!feof(instr_file)) { | |
instr = ReadInstruction(instr_file); | |
PID printf("> Received instruction (%d, %d).\n", instr.code, instr.qty); | |
lseek(stocks_fd, 0, SEEK_SET); | |
found_code = false; | |
while (!found_code) { | |
// read current item code | |
ret_code = read(stocks_fd, &crt_code, sizeof(int)); | |
if (ret_code == -1) { | |
E_PID perror("Error on item code read"); | |
exit(5); | |
} | |
else if (ret_code == 0) break; // reached EOF | |
if (crt_code != instr.code) { | |
lseek(stocks_fd, sizeof(int), SEEK_CUR); // skip the quantity | |
continue; | |
} | |
// lock quantity bytes | |
PID printf("Placing lock upon quantity of item with code %d.\n", instr.code); | |
ret_code = fcntl(stocks_fd, F_SETLKW, &qty_lock); | |
if (ret_code == -1) { | |
E_PID perror("Error on placing lock upon quantity"); | |
exit(8); | |
} | |
// read current stock quantity | |
ret_code = read(stocks_fd, &crt_qty, sizeof(int)); | |
if (ret_code == -1) { | |
E_PID perror("Error on stock quantity read"); | |
exit(6); | |
} | |
else if (ret_code == 0) { | |
E_PID fprintf(stderr, "Error: read stock code, but no quantity.\n"); | |
exit(7); | |
} | |
// DEBUG: output read info | |
//printf("Found stock code %d, of quantity %d.\n", crt_code, crt_qty); | |
if (instr.qty >= 0) { | |
PID printf("Adding %d quantity to item with code %d...\n", instr.qty, instr.code); | |
} | |
else { | |
PID printf("Subtracting %d quantity from item with code %d...\n", -instr.qty, instr.code); | |
} | |
sleep(1); // to pretend this part takes more time | |
crt_qty += instr.qty; | |
// write new data | |
if (crt_qty < 0) { | |
E_PID fprintf(stderr, "[!] Operation would lead to negative quantity; ignoring.\n"); | |
} | |
else { | |
ret_code = lseek(stocks_fd, -sizeof(int), SEEK_CUR); | |
if (ret_code == -1) { | |
E_PID perror("Error jumping back before quantity"); | |
exit(8); | |
} | |
ret_code = write(stocks_fd, &crt_qty, sizeof(int)); | |
if (ret_code == -1) { | |
E_PID perror("Error writing new quantity"); | |
exit(9); | |
} | |
} | |
// release lock | |
PID printf("Releasing lock.\n"); | |
ret_code = fcntl(stocks_fd, F_SETLK, &qty_unlock); | |
if (ret_code == -1) { | |
E_PID perror("Error releasing write lock"); | |
exit(10); | |
} | |
found_code = true; | |
} | |
if (!found_code) { | |
PID printf("Did not find code %d, adding it to the stocks file...\n", instr.code); | |
if (instr.qty < 0) { | |
E_PID fprintf(stderr, "[!] Cannot add negative quantity item to stocks file. Ignoring...\n"); | |
continue; | |
} | |
ret_code = fcntl(stocks_fd, F_SETLKW, &field_lock); | |
if (ret_code == -1) { | |
E_PID perror("Error on placing lock at EOF"); | |
exit(11); | |
} | |
ret_code = lseek(stocks_fd, 0, SEEK_END); | |
if (ret_code == -1) { | |
E_PID perror("Error on moving cursor to EOF"); | |
exit(12); | |
} | |
write(stocks_fd, &(instr.code), sizeof(int)); | |
write(stocks_fd, &(instr.qty), sizeof(int)); | |
PID printf("Added item %d to stocks file, with quantity %d.\n", instr.code, instr.qty); | |
ret_code = fcntl(stocks_fd, F_SETLK, &field_unlock); | |
if (ret_code == -1) { | |
E_PID perror("Error on releasing lock from EOF"); | |
exit(13); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
limelier@limelier-K55VM:~/college/so/lab-8/mycritsec3$ ./mycritsec3.exec deposit.bin testinput.txt | |
[3938] Began execution. | |
[3938] > Received instruction (1, 1). | |
[3938] Did not find code 1, adding it to the stocks file... | |
[3938] Error on placing lock at EOF: Invalid argument |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
In your example, you declare
field_unlock
but re-assign the members offield_lock
. Simple copy/paste error. To avoid this kind of problem, you could use designated initializers, like this,