I wrote a program that implements the mkdir command with the -p parameter to create the parent directly if it does not exist.
My question is, is this implementation optimal? What else could I improve or what problems does implementation have?
code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <limits.h>
#include "lab.h"
bool vFlag = 0;
bool pFlag = 0;
int main(int argc, char* argv[])
{
bool err = false;
int option;
// check for optional arguments
while((option = getopt(argc,argv,"vp")) !=-1)
switch(option)
{
case 'v':
vFlag = 1;
break;
case 'p':
pFlag = 1;
break;
}
if(argc == 1)
{
err_msg("missing operand\nTry 'mkdir --help' for more information.");
exit(1);
}
for(int i=optind; i<argc; i++)
{
if(pFlag)
{
char* pStart = argv[optind];
char* pCurrent = argv[optind];
char* pLast = strrchr(argv[optind], '/');
while(*pCurrent != '\0')
{
if (*pCurrent == '/' || *pCurrent == '.')
{
char str[20] = {0};
strncpy(str, pStart, pCurrent - pStart);
if((access(str, X_OK) != 0) && (access(str, F_OK) == 0))
{
err_msg("cannot create directory '%s': Permission denied", str);
exit(1);
}
else
{
mkdir(str, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
if (chdir(str) < 0)
{
perror("chdir");
}
}
pStart = pCurrent+1;
}
++pCurrent;
}
mkdir(pLast+1, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
return 0;
}
if(access(argv[i],F_OK) == 0)
{
err_msg("cannot create directory ‘%s’: File exists",argv[i]);
err = true;
}
else
{
if(mkdir(argv[i], S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
{
err_ret("cannot create directory '%s'",argv[i]);
exit(1);
}
else
if (vFlag)
printf("mkdir: created directory '%s'\n", argv[i]);
}
}
if(err == false)
exit(0);
else
exit(1);
}
lab.h content:
/* Our own header, to be included *after* all standard system headers */
#ifndef __LAB_H__
#define __LAB_H__
#include <sys/types.h> /* required for some of our prototypes */
#include <stdio.h> /* for convenience */
#include <stdlib.h> /* for convenience */
#include <string.h> /* for convenience */
#include <unistd.h> /* for convenience */
#define MAXLINE 4096 /* max line length */
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/* default file access permissions for new files */
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
/* default permissions for new directories */
/* prototypes for our own functions */
char *path_alloc(int *); /* {Prog pathalloc} */
int open_max(void); /* {Prog openmax} */
void clr_fl(int, int); /* {Prog setfl} */
void set_fl(int, int); /* {Prog setfl} */
void err_dump(const char *, ...); /* {App misc_source} */
void err_msg(const char *, ...);
void err_quit(const char *, ...);
void err_ret(const char *, ...);
void err_sys(const char *, ...);
#endif /* __LAB_H__ */
char str[20]? \$\endgroup\$20to be large enough to store the directory name in the variable. But better modified withPATH_MAX. It's better this way? \$\endgroup\$lab.hdeserves improvements, yet I assume it it only here as a reference. \$\endgroup\$