I am reading the book The Linux Programming Interface and I have reached the exercise in which the implementation of the chattr
command in C is required.
I would like to receive feedback on the implementation, to criticize my solution
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
static inline void
do_ioctl(int fd, unsigned long req, int *attr)
{
if (ioctl(fd, req, attr) == -1) {
fprintf(stderr, "ERROR: ioctl error - %s\n",
strerror(errno));
exit(EXIT_FAILURE);
}
return;
}
int
main(int argc, char *argv[])
{
int i;
int fd;
int attr;
int flag_count;
if (argc < 3) {
fprintf(stderr, "Usage: %s <flags> <file_name>\n", argv[0]);
exit(EXIT_FAILURE);
}
if ((fd = open(argv[2], O_RDONLY | O_WRONLY)) == -1) {
fprintf(stderr, "ERROR: Unable to open %s -- %s\n",
argv[2], strerror(errno));
exit(EXIT_FAILURE);
}
do_ioctl(fd, FS_IOC_GETFLAGS, &attr);
flag_count = strlen(argv[1]);
for (i = 1; i < flag_count; i++) {
switch (argv[1][i]) {
case 'a':
attr |= FS_APPEND_FL;
break;
case 'c':
attr |= FS_COMPR_FL;
break;
case 'D':
attr |= FS_DIRSYNC_FL;
break;
case 'i':
attr |= FS_IMMUTABLE_FL;
break;
case 'j':
attr |= FS_JOURNAL_DATA_FL;
break;
case 'A':
attr |= FS_NOATIME_FL;
break;
case 'd':
attr |= FS_NODUMP_FL;
break;
case 't':
attr |= FS_NOTAIL_FL;
break;
case 's':
attr |= FS_SECRM_FL;
break;
case 'S':
attr |= FS_SYNC_FL;
break;
case 'T':
attr |= FS_TOPDIR_FL;
break;
case 'u':
attr |= FS_UNRM_FL;
break;
default:
fprintf(stderr, "ERROR: unknown flag %c\n", argv[1][i]);
exit(EXIT_FAILURE);
}
}
do_ioctl(fd, FS_IOC_SETFLAGS, &attr);
exit(EXIT_SUCCESS);
}
This implementation of the chattr command is a more simplified option
Also, as the book states (studying system calls) I would like some suggestions for replacing standard functions with POSIX system calls, what suggestions would you have here? I have implemented with classic functions for the moment. I would use system calls from the book APUE, being very popular and very good for learning system calls rather than those in this book.
if (argc < 3) { fprintf(stderr, "Usage: %s <flags> <file_name>\n", argv[0]);
. consider what happens whenargc == 0
. (Due to pathologicexecv()
call.) \$\endgroup\$