Skip to content

Commit 5cb8a7e

Browse files
authored
Merge pull request #88 from Electrostat-Lab/unix-res
File Memory Model API Enhancements
2 parents 427d45a + 7d5c96c commit 5cb8a7e

File tree

10 files changed

+165
-76
lines changed

10 files changed

+165
-76
lines changed

electrostatic-sandbox-framework/electrostatic-core/src/include/electrostatic/electronetsoft/util/filesystem/file_operations.h

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,13 @@ extern "C" {
2929
#include <stdint.h>
3030
#include <electrostatic/electronetsoft/util/utilities.h>
3131

32-
struct read_op_processor {
32+
struct op_processor {
33+
void (*op_preprocessor)(file_mem *, void *);
34+
void (*op_postprocessor)(file_mem *, void *);
3335
void (*on_bytes_processed)(file_mem *, ssize_t, void *); /* Executed on each successful read operation. */
34-
void (*on_eof_reached)(file_mem *); /* Executed when EOF is reached. Could be used to chain calls to memory deallocators. */
35-
void (*on_last_char_sampled)(file_mem *, void *caller);
36-
void (*on_error_encountered)(file_mem *, int, void *caller);
37-
};
38-
39-
struct write_op_processor {
40-
void (*on_bytes_processed)(file_mem *, ssize_t, void *); /* Executed on each successful read operation. */
41-
void (*on_eob_reached)(file_mem *);
42-
void (*on_last_char_sampled)(file_mem *, void *caller);
43-
void (*on_error_encountered)(file_mem *, int, void *caller);
36+
void (*on_last_byte_sampled)(file_mem *, void *); // uses count
37+
void (*on_trailing_char_sampled)(file_mem *, void *); // uses predicate check
38+
void (*on_error_encountered)(file_mem *, int, void *);
4439
};
4540

4641
struct update_op_processor {
@@ -95,7 +90,7 @@ struct pipe_serializer {
9590
* @param _processor a pointer to the file read operations processor; that links the API to the user application.
9691
* @param __processor a pointer to the file attrs update processors.
9792
*/
98-
status_code read_into_mem(file_mem *, read_op_processor *, update_op_processor *);
93+
status_code read_into_mem(file_mem *, op_processor *, update_op_processor *);
9994

10095
status_code update_file_attrs(file_mem *, update_op_processor *);
10196

@@ -107,7 +102,7 @@ status_code update_file_attrs(file_mem *, update_op_processor *);
107102
* @param mem a pointer to the file memory model struct.
108103
* @param processor a pointer to the file operations processor; that links the API to the user application.
109104
*/
110-
status_code write_from_mem(file_mem *, write_op_processor *, update_op_processor *);
105+
status_code write_from_mem(file_mem *, op_processor *, update_op_processor *);
111106

112107
status_code init_serializer(pipe_serializer *, serializer_op_processor *, update_op_processor *);
113108

electrostatic-sandbox-framework/electrostatic-core/src/include/electrostatic/electronetsoft/util/filesystem/file_verify.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,23 @@ extern "C" {
1010
#include <sys/stat.h>
1111
#include <stdio.h>
1212
#include <stdint.h>
13+
#include <unistd.h>
14+
#include <string.h>
15+
#include <electrostatic/electronetsoft/util/filesystem/file_operations.h>
16+
17+
static inline int get_path_from_fd(int fd, char *buf, ssize_t len) {
18+
if (fd < 0 || NULL == buf) {
19+
return -1;
20+
}
21+
22+
pid_t pid = getpid();
23+
24+
char path[255];
25+
memset(path, '\0', sizeof (path));
26+
sprintf(path, "/proc/%d/fd/%d", pid, fd);
27+
28+
return readlink(path, buf, len) > 0;
29+
}
1330

1431
static inline int is_existential(const char *file) {
1532
if (file == NULL) {
@@ -19,7 +36,23 @@ static inline int is_existential(const char *file) {
1936
return stat(file, &statbuf) == 0;
2037
}
2138

39+
static inline int is_fd_existential(int fd) {
40+
if (fd < 0) {
41+
return -1;
42+
}
43+
char path[255];
44+
memset(path, '\0', sizeof (path));
45+
int __status = get_path_from_fd(fd, path, sizeof (path));
46+
if (!__status) {
47+
return -1;
48+
}
49+
return is_existential(path);
50+
}
51+
2252
static inline int is_fexistential(int fd) {
53+
if (fd < 0) {
54+
return -1;
55+
}
2356
struct stat statbuf;
2457
return fstat(fd, &statbuf) == 0;
2558
}

electrostatic-sandbox-framework/electrostatic-core/src/include/electrostatic/electronetsoft/util/types.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,7 @@ typedef struct routine_data (routine_data);
8181
typedef struct dll_function_table (dll_function_table);
8282
typedef struct routine_callbacks (routine_callbacks);
8383

84-
typedef struct write_op_processor (write_op_processor);
85-
typedef struct read_op_processor (read_op_processor);
84+
typedef struct op_processor (op_processor);
8685
typedef struct update_op_processor (update_op_processor);
8786

8887
typedef struct serializer_op_processor (serializer_op_processor);

electrostatic-sandbox-framework/electrostatic-core/src/libs/electrostatic-primer/electronetsoft/util/filesystem/file_read.c

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
#include <electrostatic/electronetsoft/util/filesystem/file_verify.h>
44

55
status_code read_into_mem(file_mem *mem,
6-
read_op_processor *_processor,
6+
op_processor *_processor,
77
update_op_processor *__processor) {
88
// pre-processing automata -- Input validation
99
if (rvalue(mem) == NULL) {
1010
return EUNDEFINEDBUFFER;
1111
}
1212

13-
if (NULL != __processor && NULL != __processor->update_model_preprocessor) {
14-
__processor->update_model_preprocessor(mem, &read_into_mem);
13+
if (NULL != _processor && NULL != _processor->op_preprocessor) {
14+
_processor->op_preprocessor(mem, &read_into_mem);
1515
}
1616

1717
// pre-processing automata -- Calculating the file size, current position,
@@ -23,11 +23,6 @@ status_code read_into_mem(file_mem *mem,
2323
}
2424
}
2525

26-
// postprocessing automata -- Invoke the update file postprocessor
27-
if (NULL != __processor && NULL != __processor->update_model_postprocessor) {
28-
__processor->update_model_postprocessor(mem, &read_into_mem);
29-
}
30-
3126
if (NULL == mem->buffer) {
3227
return EUNDEFINEDBUFFER;
3328
}
@@ -37,6 +32,13 @@ status_code read_into_mem(file_mem *mem,
3732
ssize_t read_bytes = 0;
3833
ssize_t total_bytes = 0;
3934
while (1) {
35+
// sanity check the file
36+
if (!is_fd_existential(mem->fd)) {
37+
if (NULL != _processor && NULL != _processor->on_error_encountered) {
38+
_processor->on_error_encountered(mem, errno, &read_into_mem);
39+
}
40+
return errno;
41+
}
4042
read_bytes = read(mem->fd, (mem->buffer + total_bytes), /* Advance linearly over the File Mem model buffer
4143
* with the read bytes */
4244
(mem->n_bytes - 1) - total_bytes); /* Retro-advance on the number of available bytes
@@ -55,14 +57,14 @@ status_code read_into_mem(file_mem *mem,
5557
} else if (0 == read_bytes) {
5658
// EOF terminate!
5759
mem->buffer[total_bytes] = mem->trailing; /* add a null-terminating character */
58-
if (NULL != _processor && NULL != _processor->on_eof_reached) {
59-
_processor->on_eof_reached(mem);
60+
if (NULL != _processor && NULL != _processor->on_trailing_char_sampled) {
61+
_processor->on_trailing_char_sampled(mem, &read_into_mem);
6062
}
6163
// post-processing sub-state (HACK!)
6264
if (mem->__continue_after_eof) {
6365
continue;
6466
}
65-
return PASS;
67+
break;
6668
} else if (read_bytes > 0) {
6769
// execute on_read
6870
if (NULL != _processor && NULL != _processor->on_bytes_processed) {
@@ -73,14 +75,18 @@ status_code read_into_mem(file_mem *mem,
7375
// even though the EOF is not reached, yet.
7476
if ((mem->n_bytes - 1) == total_bytes) {
7577
mem->buffer[total_bytes] = mem->trailing; /* add a null-terminating character */
76-
if (NULL != _processor && NULL != _processor->on_last_char_sampled) {
77-
_processor->on_last_char_sampled(mem, &read_into_mem);
78+
if (NULL != _processor && NULL != _processor->on_last_byte_sampled) {
79+
_processor->on_last_byte_sampled(mem, &read_into_mem);
7880
}
7981
}
8082
} else {
8183
return UNEXPECTED_ERROR;
8284
}
8385
}
8486

85-
return ASSERTION_FAILURE;
87+
if (NULL != _processor && NULL != _processor->op_postprocessor) {
88+
_processor->op_postprocessor(mem, &read_into_mem);
89+
}
90+
91+
return PASS;
8692
}

electrostatic-sandbox-framework/electrostatic-core/src/libs/electrostatic-primer/electronetsoft/util/filesystem/file_update.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ status_code update_file_attrs(file_mem *mem,
99
return EUNDEFINEDBUFFER;
1010
}
1111

12+
if (!mem->__auto_update_attrs) {
13+
return PASS;
14+
}
15+
16+
if (NULL != _processor && NULL != _processor->update_model_preprocessor) {
17+
_processor->update_model_preprocessor(mem, &read_into_mem);
18+
}
19+
1220
if (mem->fd < 0 || !is_fexistential(mem->fd)) {
1321
return EUNDEFINEDBUFFER;
1422
}
@@ -50,5 +58,10 @@ status_code update_file_attrs(file_mem *mem,
5058
}
5159
}
5260

61+
// postprocessing automata -- Invoke the update file postprocessor
62+
if (NULL != _processor && NULL != _processor->update_model_postprocessor) {
63+
_processor->update_model_postprocessor(mem, &read_into_mem);
64+
}
65+
5366
return PASS;
5467
}

electrostatic-sandbox-framework/electrostatic-core/src/libs/electrostatic-primer/electronetsoft/util/filesystem/file_write.c

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
#include <electrostatic/electronetsoft/util/filesystem/file_verify.h>
44

55
status_code write_from_mem(file_mem *mem,
6-
write_op_processor *_processor,
6+
op_processor *_processor,
77
update_op_processor *__processor) {
88
// pre-processing automata -- Input validation
99
if (rvalue(mem) == NULL) {
1010
return EUNDEFINEDBUFFER;
1111
}
1212

13-
if (NULL != __processor && NULL != __processor->update_model_preprocessor) {
14-
__processor->update_model_preprocessor(mem, &write_from_mem);
13+
if (NULL != _processor && NULL != _processor->op_preprocessor) {
14+
_processor->op_preprocessor(mem, &write_from_mem);
1515
}
1616

1717
if (mem->fd < 0 || !is_fexistential(mem->fd)) {
@@ -31,9 +31,16 @@ status_code write_from_mem(file_mem *mem,
3131
ssize_t written_bytes = 0;
3232
ssize_t total_bytes = 0;
3333
while (1) {
34+
if (!is_fd_existential(mem->fd)) {
35+
if (NULL != _processor && NULL != _processor->on_error_encountered) {
36+
_processor->on_error_encountered(mem, errno, &read_into_mem);
37+
}
38+
return errno;
39+
}
40+
3441
if (*(mem->buffer + total_bytes) == mem->trailing) {
35-
if (NULL != _processor && NULL != _processor->on_eob_reached) {
36-
_processor->on_eob_reached(mem);
42+
if (NULL != _processor && NULL != _processor->on_trailing_char_sampled) {
43+
_processor->on_trailing_char_sampled(mem, &write_from_mem);
3744
}
3845
break;
3946
}
@@ -58,8 +65,8 @@ status_code write_from_mem(file_mem *mem,
5865
} else if (total_bytes == (mem->n_bytes - 1)) {
5966
// All bytes are written? -> terminate
6067
// Equivalent to EOF.
61-
if (NULL != _processor && NULL != _processor->on_eob_reached) {
62-
_processor->on_eob_reached(mem);
68+
if (NULL != _processor && NULL != _processor->on_last_byte_sampled) {
69+
_processor->on_last_byte_sampled(mem, &write_from_mem);
6370
}
6471
break;
6572
} else {
@@ -73,9 +80,10 @@ status_code write_from_mem(file_mem *mem,
7380
return ___status;
7481
}
7582

76-
// postprocessing automata -- Invoke the update file postprocessor
77-
if (NULL != __processor && NULL != __processor->update_model_postprocessor) {
78-
__processor->update_model_postprocessor(mem, &write_from_mem);
83+
// to avoid premature closure of files; use the postprocessor at the end of the
84+
// write routine
85+
if (NULL != _processor && NULL != _processor->op_postprocessor) {
86+
_processor->op_postprocessor(mem, &write_from_mem);
7987
}
8088

8189
return PASS;

electrostatic-sandbox-framework/electrostatic-examples/src/linux/hello_file_read.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,12 @@ static inline void on_bytes_processed(file_mem *mem,
4949
if (caller != &read_into_mem) {
5050
return;
5151
}
52-
fprintf(stdout, "Read bytes = %s\n", mem->buffer);
5352
}
5453

55-
static inline void on_eof_reached(file_mem *mem) {
54+
static inline void on_eof_reached(file_mem *mem, void *caller) {
55+
if (caller != &read_into_mem) {
56+
return;
57+
}
5658
// support for stdin
5759
if (mem->fd == STDIN_FILENO && mem->n_bytes < 20) {
5860
mem->n_bytes += mem->n_bytes;
@@ -61,6 +63,13 @@ static inline void on_eof_reached(file_mem *mem) {
6163
}
6264
fprintf(stdout, "Read Bytes after EOF: %s\n", mem->buffer);
6365
fprintf(stdout, "EOF Reached!\n");
66+
}
67+
68+
static inline void op_postprocessor(file_mem *mem, void *caller) {
69+
if (&read_into_mem != caller) {
70+
return;
71+
}
72+
6473
// deallocates memory here!
6574
if (NULL != mem->buffer) {
6675
free(mem->buffer);
@@ -87,9 +96,10 @@ int main() {
8796
.__continue_after_eof = 0
8897
};
8998

90-
read_op_processor _processor = {
99+
op_processor _processor = {
91100
.on_bytes_processed = &on_bytes_processed,
92-
.on_eof_reached = &on_eof_reached
101+
.on_trailing_char_sampled = &on_eof_reached,
102+
.op_postprocessor = &op_postprocessor
93103
};
94104

95105
update_op_processor __processor = {

electrostatic-sandbox-framework/electrostatic-examples/src/linux/hello_file_write.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
#include <stdlib.h>
1212
#include <fcntl.h>
1313

14-
static inline void update_model_preprocessor(file_mem *mem,
15-
void *caller) {
14+
static inline void op_preprocessor(file_mem *mem, void *caller) {
1615
if (caller != &write_from_mem) {
1716
return;
1817
}
@@ -43,12 +42,14 @@ static inline void on_bytes_processed(file_mem *mem, ssize_t bytes,
4342
fprintf(stdout, "%s", mem->buffer);
4443
}
4544

46-
static inline void on_eob_reached(file_mem *mem) {
45+
static inline void on_eob_reached(file_mem *mem, void *caller) {
46+
if (caller != &write_from_mem) {
47+
return;
48+
}
4749
fprintf(stdout, "EOB Reached!\n");
4850
}
4951

50-
static inline void update_model_postprocessor(file_mem *mem,
51-
void *caller) {
52+
static inline void op_postprocessor(file_mem *mem, void *caller) {
5253
if (caller != &write_from_mem) {
5354
return;
5455
}
@@ -69,17 +70,14 @@ int main() {
6970
.__auto_update_attrs = 1,
7071
};
7172

72-
write_op_processor _processor = {
73+
op_processor _processor = {
7374
.on_bytes_processed = &on_bytes_processed,
74-
.on_eob_reached = &on_eob_reached,
75-
};
76-
77-
update_op_processor __processor = {
78-
.update_model_preprocessor = &update_model_preprocessor,
79-
.update_model_postprocessor = &update_model_postprocessor,
75+
.on_trailing_char_sampled = &on_eob_reached,
76+
.op_preprocessor = &op_preprocessor,
77+
.op_postprocessor = &op_postprocessor
8078
};
8179

82-
status_code __status = write_from_mem(&_file_mem, &_processor, &__processor);
80+
status_code __status = write_from_mem(&_file_mem, &_processor, NULL);
8381

8482
if (PASS != __status) {
8583
fprintf(stderr, "Error Encountered: %s\n", strerror(__status));
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <electrostatic/electronetsoft/util/filesystem/file_verify.h>
2+
#include <stdio.h>
3+
#include <unistd.h>
4+
#include <string.h>
5+
#include <fcntl.h>
6+
7+
int main() {
8+
char path[128];
9+
int __return = get_path_from_fd(STDOUT_FILENO, path, sizeof (path));
10+
if (!__return) {
11+
fprintf(stderr, "%s\n", strerror(errno));
12+
exit(errno);
13+
}
14+
fprintf(stdout, "The path of fd=%d is %s\n", STDOUT_FILENO, path);
15+
16+
return 0;
17+
}

0 commit comments

Comments
 (0)