mirror of
https://github.com/clearlinux/graphene.git
synced 2026-05-13 10:33:40 +00:00
Previously, /proc and /dev pseudo-filesystems were implemented in completely different ways. This commit introduces a set of generic functions for all pseudo-FSs (based on previous implementation of /proc) and refactors both /proc and /dev to use these functions. This commit also expands a LibOS test `proc` to cover more cases and pseudo-files, as well as introduces a new LibOS test `dev`. Several bugs in pseudo-FSs were detected and fixed in the process.
127 lines
2.8 KiB
C
127 lines
2.8 KiB
C
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <pthread.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
int main(int argc, char** argv) {
|
|
int ret;
|
|
FILE* f;
|
|
DIR* dir;
|
|
struct dirent* dirent;
|
|
char buf[64];
|
|
|
|
/* sanity checks that incorrect invocations return errors */
|
|
f = fopen("/dummy-pseudo-fs", "r");
|
|
if (f != NULL || errno != ENOENT) {
|
|
perror("(sanity check) fopen of dummy non-existing pseudo-FS did not fail with ENOENT");
|
|
return 1;
|
|
}
|
|
|
|
f = fopen("/dev", "r+");
|
|
if (f != NULL || errno != EISDIR) {
|
|
perror("(sanity check) fopen of /dev did not fail with EISDIR");
|
|
return 1;
|
|
}
|
|
|
|
f = fopen("/dev/dummy", "r");
|
|
if (f != NULL || errno != ENOENT) {
|
|
perror("(sanity check) fopen of /dev/dummy (non-existing file) did not fail with ENOENT");
|
|
return 1;
|
|
}
|
|
|
|
printf("===== Contents of /dev\n");
|
|
dir = opendir("/dev");
|
|
if (!dir) {
|
|
perror("opendir /dev");
|
|
return 1;
|
|
}
|
|
|
|
errno = 0;
|
|
while ((dirent = readdir(dir))) {
|
|
printf("/dev/%s\n", dirent->d_name);
|
|
}
|
|
if (errno) {
|
|
perror("readdir /dev");
|
|
return 1;
|
|
}
|
|
|
|
ret = closedir(dir);
|
|
if (ret < 0) {
|
|
perror("closedir /dev");
|
|
return 1;
|
|
}
|
|
|
|
printf("===== Read from /dev/urandom\n");
|
|
f = fopen("/dev/urandom", "r");
|
|
if (!f) {
|
|
perror("fopen /dev/urandom");
|
|
return 1;
|
|
}
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
ret = fread(buf, 1, sizeof(buf), f);
|
|
if (ferror(f)) {
|
|
perror("fread /dev/urandom");
|
|
return 1;
|
|
}
|
|
|
|
printf("Four bytes from /dev/urandom: %x:%x:%x:%x\n", buf[0], buf[1], buf[2], buf[3]);
|
|
|
|
ret = fclose(f);
|
|
if (ret) {
|
|
perror("fclose /dev/urandom");
|
|
return 1;
|
|
}
|
|
|
|
printf("===== Write to /dev/null\n");
|
|
f = fopen("/dev/null", "w");
|
|
if (!f) {
|
|
perror("fopen /dev/null");
|
|
return 1;
|
|
}
|
|
|
|
ret = fwrite(buf, 1, sizeof(buf), f);
|
|
if (ret < sizeof(buf)) {
|
|
perror("fwrite /dev/null");
|
|
return 1;
|
|
}
|
|
|
|
ret = fclose(f);
|
|
if (ret) {
|
|
perror("fclose /dev/null");
|
|
return 1;
|
|
}
|
|
|
|
#if 0
|
|
/* `/dev/stdout` is a link to `/proc/self/fd/1`; Graphene currently fails, see #1387 */
|
|
|
|
printf("===== Write to /dev/stdout\n");
|
|
f = fopen("/dev/stdout", "w");
|
|
if (!f) {
|
|
perror("fopen /dev/stdout");
|
|
return 1;
|
|
}
|
|
|
|
sprintf(buf, "%s\n", "Hello World written to stdout!");
|
|
size_t towrite = strlen(buf) + 1;
|
|
ret = fwrite(buf, 1, towrite, f);
|
|
if (ret < towrite) {
|
|
perror("fwrite /dev/stdout");
|
|
return 1;
|
|
}
|
|
|
|
ret = fclose(f);
|
|
if (ret) {
|
|
perror("fclose /dev/stdout");
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|