Système de fichiers / Exemples
Error
error.c
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
printf("Test perror vs strerror...\n");
char* filename = "./error.txt";
if (argc >= 2) filename = argv[1];
int fd = open(filename, O_RDWR);
printf("fd = %d, errno=%d\n", fd, errno);
printf("\ntest perror...\n");
perror("Error");
printf("\ntest strerror_r...\n");
char estr[100] = "";
strerror_r(errno, estr, sizeof(estr) - 1);
fprintf(stderr, "Error: %s\n", estr);
return 0;
}
File I/O
read.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// dd if=/dev/urandom of=./t.txt bs=4k count=4096
int main(int argc, char* argv[])
{
const char* fn = "test1.txt";
if (argc > 1) fn = argv[1];
int fd = open(fn, O_RDONLY);
if (fd == -1) {
printf("file not found!\n");
}
while (1) {
char buf[4096 + 1];
int ln = read(fd, buf, sizeof(buf) - 1);
if (ln == -1) {
if (errno == EINTR) continue;
break;
}
if (ln == 0) break;
buf[ln] = 0;
printf("%s\nread length --> %d\n", buf, ln);
};
close(fd);
return 0;
}
write.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static const char* msg1 = "1234567890abcdefghijklmnopqrstuvwxyz\n";
int main(int argc, char* argv[])
{
const char* fn = "test1.txt";
if (argc > 1) fn = argv[1];
int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0666);
if (fd == -1) {
printf("can't file!\n");
}
for (int i = 0; i < 100; i++) {
write(fd, msg1, strlen(msg1));
}
close(fd);
}
seek.c
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
static const struct {
off_t pos;
off_t offset;
int whence;
} tests[] = {
{0, 0, SEEK_SET},
{10, 10, SEEK_SET},
{21, 10, SEEK_CUR},
{12, -10, SEEK_CUR},
{1000, -1, SEEK_END},
};
static const char* i2w[] = {
[SEEK_SET] = "SEEK_SET",
[SEEK_CUR] = "SEEK_CUR",
[SEEK_END] = "SEEK_END",
};
int main(int argc, char* argv[])
{
const char* fn = "test2.txt";
if (argc > 1) fn = argv[1];
int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0664);
if (fd == -1) {
printf("can't file!\n");
}
// 1st create a file with 1001 entries 0000 - 1000
char entry[5 + 3];
for (int i = 0; i <= 1000; i++) {
snprintf(entry, sizeof(entry) - 1, "%04d\n", i);
write(fd, entry, strlen(entry));
}
for (unsigned i = 0; i < ARRAY_SIZE(tests); i++) {
off_t pos = lseek(fd, tests[i].offset * 5, tests[i].whence);
read(fd, entry, 5);
entry[4] = 0;
printf("%s: entry=%s, offset: %3ld, pos: %ld/%ld: \n",
i2w[tests[i].whence],
entry,
tests[i].offset,
tests[i].pos,
pos / 5);
}
close(fd);
}
truncate.c
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// echo "jslfjsdljslfjsdlfj" > t.txt
int main(int argc, char* argv[])
{
char* fname = "t.txt";
off_t len = 10;
if (argc > 1) fname = argv[1];
int fd = open(fname, O_RDWR, 0664);
if (fd == -1) {
printf("can't open file: %s\n", fname);
}
printf("argv1: %s, fd=%d, errno=%d\n", fname, fd, errno);
ftruncate(fd, len);
close(fd);
return 0;
}
stdio.c
#include <stdio.h>
int main(int argc, char* argv[])
{
(void)argc;
char buf[1];
int c = 0;
FILE* stream = fopen(argv[1], "r");
do {
c = fread(buf, sizeof(buf), 1, stream);
} while (c > 0);
fclose(stream);
return 0;
}
Directory
list.c
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
void scan_dir(const char* path)
{
printf("\n.%s/:\n", path);
DIR* dir = opendir(path);
if (dir == 0) return;
while (dir != 0) {
struct dirent* entry = readdir(dir);
if (entry == 0) break;
printf("%4d - %s\n", entry->d_type, entry->d_name);
}
closedir(dir);
}
int main(int argc, char* argv[])
{
char* path = ".";
if (argc > 1) path = argv[1];
scan_dir(path);
return 0;
}
recursive.c
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
/**
* convert filetype to character
*/
char mode2filetype(mode_t mode)
{
// process file type
if ((mode & S_IFMT) == S_IFSOCK) return 's';
if ((mode & S_IFMT) == S_IFLNK) return 'l';
if ((mode & S_IFMT) == S_IFREG) return '-';
if ((mode & S_IFMT) == S_IFBLK) return 'b';
if ((mode & S_IFMT) == S_IFDIR) return 'd';
if ((mode & S_IFMT) == S_IFCHR) return 'c';
if ((mode & S_IFMT) == S_IFIFO) return 'f';
return '-';
}
/**
* convert file permissions to string
*/
char* mode2str(mode_t mode)
{
static char buf[1 + 3 * 3 + 1 + 1];
buf[0] = mode2filetype(mode);
buf[1] = mode & S_IRUSR ? 'r' : '-';
buf[2] = mode & S_IWUSR ? 'w' : '-';
buf[3] = mode & S_IXUSR ? 'x' : '-';
buf[4] = mode & S_IRGRP ? 'r' : '-';
buf[5] = mode & S_IWGRP ? 'w' : '-';
buf[6] = mode & S_IXGRP ? 'x' : '-';
buf[7] = mode & S_IROTH ? 'r' : '-';
buf[8] = mode & S_IWOTH ? 'w' : '-';
buf[9] = mode & S_IXOTH ? 'x' : '-';
buf[10] = mode & S_ISVTX ? 't' : '-';
if (mode & S_ISGID) buf[6] = 's';
if (mode & S_ISUID) buf[3] = 's';
buf[11] = 0;
return buf;
}
/**
* convert file time to string
*/
char* time2str(time_t* time)
{
static char buf[50];
char* t = ctime_r(time, buf);
t[strlen(t) - 1] = 0;
return t;
}
/**
* print file information
*
*@param name file name
*@param stat file status
*/
void print_info(const char* name, struct stat* stat)
{
printf("%10lu", stat->st_ino); // print inode number
printf(" %s", mode2str(stat->st_mode)); // print file type & permissions
printf(" %3d", stat->st_nlink); // print number of links
printf(" %8lu", stat->st_size); // print file size
printf(" %s", time2str(&stat->st_mtime)); // print file modification time
printf(" %s\n", name); // print filename
}
/**
* scan directory for files and subdirectories
*
*@param recursively true to scan recursively the directories
*@param size of root path
*@param path directory path to scan
*/
void scan_dir(bool recursively, int rootsz, const char* path)
{
// print relative directory path
printf("\n.%s/:\n", path);
// count number of files entries in directory
DIR* dir = opendir(".");
if (dir == 0) return;
int count = 0;
while (dir != 0) {
struct dirent* entry = readdir(dir);
if (entry == 0) break;
count++;
}
closedir(dir);
// get all file names
char files[count * 256];
dir = opendir(".");
if (dir == 0) return;
int i = 0;
while (dir != 0) {
struct dirent* entry = readdir(dir);
if (entry == 0) break;
strcpy(files + i * 256, entry->d_name);
i++;
}
closedir(dir);
// sort alphabeticaly all files
qsort(files, count, 256, (int (*)(const void*, const void*))strcmp);
// print file information
for (int j = 0; j < count; j++) {
struct stat status;
int err = stat(files + j * 256, &status);
if (err < 0) continue;
print_info(files + j * 256, &status);
}
// process subdirectories if required...
if (recursively)
for (int j = 0; j < count; j++) {
char* file = files + j * 256;
if (strcmp(file, ".") == 0) continue;
if (strcmp(file, "..") == 0) continue;
struct stat status;
int err = stat(file, &status);
if (err < 0) continue;
if (!S_ISDIR(status.st_mode)) continue;
char p[strlen(path) + 1 + 256];
strcpy(p, path);
strcat(p, "/");
strcat(p, file);
chdir(file);
scan_dir(recursively, rootsz, p);
chdir("..");
}
}
/**
* print application usage
*/
static void print_usage()
{
printf(
"Usage: list [OPTIONs] [PATH]\n"
"List information about files in directories\n"
"Options:\n"
" -h this message\n"
" -r recursive to list subdirectories\n"
"Path:\n"
" by default current directory\n");
}
/**
* main program...
*/
int main(int argc, char* argv[])
{
printf("List files in directories...\n");
// parse fonction arguments
bool recursively = false;
const char* path = ".";
while (1) {
int op = getopt(argc, argv, "hr");
if (op == -1) break;
switch (op) {
case 'h':
print_usage();
return 0;
case 'r':
recursively = true;
break;
default:
fprintf(stderr, "ERROR: invalid option.\n");
exit(1);
}
}
int r = argc - optind;
if (r == 1)
path = argv[optind];
else if (r > 1) {
fprintf(stderr, "ERROR: too many arguments\n");
exit(1);
}
printf("options: r=%d, p=%s\n", recursively, path);
char* cwd = getcwd(0, 0);
chdir(path);
scan_dir(recursively, strlen(cwd), path);
free(cwd);
return 0;
}
Inotify
main.c
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
static void print_events(uint32_t mask)
{
if (mask & IN_ACCESS) printf(" access ");
if (mask & IN_ATTRIB) printf(" attribute ");
if (mask & IN_CLOSE_WRITE) printf(" close_write ");
if (mask & IN_CLOSE_NOWRITE) printf(" close_nowrite");
if (mask & IN_CREATE) printf(" create ");
if (mask & IN_DELETE) printf(" delete ");
if (mask & IN_DELETE_SELF) printf(" delete_self ");
if (mask & IN_MODIFY) printf(" modify ");
if (mask & IN_MOVE_SELF) printf(" move_self ");
if (mask & IN_MOVED_FROM) printf(" move_from ");
if (mask & IN_MOVED_TO) printf(" move_to ");
if (mask & IN_OPEN) printf(" open ");
if (mask & IN_DONT_FOLLOW) printf(" dont_follow ");
if (mask & IN_EXCL_UNLINK) printf(" excl_unlink ");
if (mask & IN_IGNORED) printf(" ignored ");
if (mask & IN_ISDIR) printf(" is_dir ");
if (mask & IN_Q_OVERFLOW) printf(" q_overflow ");
if (mask & IN_UNMOUNT) printf(" unmount ");
printf("\n");
}
static void process_inotify(int fd)
{
char buff[10 * (sizeof(struct inotify_event) + NAME_MAX + 1)];
ssize_t sz = read(fd, buff, sizeof(buff));
if (sz == -1) {
perror("ERROR while reading inotify fd");
if (errno == EINTR) return;
exit(1);
}
printf("inotify event:\n");
char* p = buff;
while (sz > 0) {
struct inotify_event* event = (struct inotify_event*)p;
printf(" wd:%d, cookie=%d, mask=0x%x",
event->wd,
event->cookie,
event->mask);
print_events(event->mask);
event->name[event->len] = 0;
printf(" name:%s\n\n", event->name);
p += sizeof(struct inotify_event) + event->len;
sz -= sizeof(struct inotify_event) + event->len;
}
}
int main(int argc, char* argv[])
{
char* path = ".";
if (argc > 1) path = argv[1];
int efd = epoll_create1(0);
if (efd == -1) {
perror("ERROR while create epoll");
exit(1);
}
int ifd = inotify_init1(0);
if (ifd == -1) {
perror("ERROR while creating inotify file descriptor");
exit(1);
}
struct epoll_event event = {
.events = EPOLLIN,
.data.fd = ifd,
};
epoll_ctl(efd, EPOLL_CTL_ADD, ifd, &event);
int wd1 = inotify_add_watch(ifd, path, IN_ALL_EVENTS);
if (wd1 == -1) {
perror("ERROR while adding directory to inotify fd");
exit(1);
}
while (1) {
struct epoll_event events[2];
int ret = epoll_wait(efd, events, 2, -1);
if (ret == -1) {
perror(" --> error...");
} else if (ret == 0) {
perror(" --> nothing received...");
} else {
for (int i = 0; i < ret; i++) {
int fd = events[i].data.fd;
if (fd == ifd)
process_inotify(fd);
else
printf("wrong fd..\n");
}
}
}
return 0;
}