's' case with getopt dosent print out the active files - c

This certain getopt case is supposed to be used as an ls (the unix/linux command) alternative that returns the active files but once compiled and ran nothing is returned in the terminal.
Here is the full code:
#include <errno.h>
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#define DATA_SIZE 1000
void print_help(void)
{
printf("Help\n");
printf("> cast -d (deletes file)\n");
printf("> cast -r (renames file)\n");
printf("> cast -c (create new file)\n");
printf("> cast -s (searches contents of file)\n");
printf("________________________________________\n");
printf("Find an error or a bug? please submit it in the issues section on github\n");
}
case 's': {
int main(void)
{
DIR *directory;
struct dirent *entry;
directory = opendir(".");
if (directory == NULL)
{
printf("Error reading directory\n");
return 1;
}
while ((entry = readdir(directory)) != NULL)
if (entry->d_type == DT_REG)
{
printf("file: %s\n", entry->d_name);
}
}
if (closedir(directory) == -1)
{
printf("Error closing directory\n");
return 1;
}
return 0;
}
}
int main(int argc, char **argv)
{
int option_val = 0;
int opt_delete = 0;
int opt_help = 0;
int opt_rename = 0;
int opt_create = 0;
int opt_search = 0;
while ((option_val = getopt(argc, argv, "dhrcs")) != -1) {
switch (option_val) {
case 'd': {
char filename[65]; //Hope your filename isnt bigger than this
printf("Filename or path to file: ");
scanf("%s", filename); // checks to see if your filename isnt bigger than specified
if (remove(filename) != 0)
{
fprintf(stderr, "Errno: %d\n", errno);
perror("Error msg");
} else printf("%s, deleted.\n", filename);
opt_delete = 1;
break;
case 'r': {
char file[65], new[65];
printf("File: ");
scanf("%s", file);
printf("New name: ");
scanf("%s", new);
if (rename(file, new) != 0)
{
fprintf(stderr, "Errno: %d\n", errno);
perror("Error msg");
} else printf("%s --> %s", file, new);
opt_rename = 1;
break;
case 'c': {
FILE *f = fopen("Castdocument.txt", "w+");
fprintf(f, "Finished with maybe no errors? Rename this file to whatever you would like and change the filename extension with ""cast -r""");
printf("File created! (Check your home directory for ""Castdocument.txt"" file and modify that to fit your needs)");
fclose(f);
opt_create = 1;
case 'h': {
print_help();
opt_help = 1;
break;
default:; /* '?' */
//print_help();
}
if (opt_delete) {
printf("\n");
} if (opt_rename) {
printf("\n");
} if (opt_help) {
print_help();
} if (opt_search) {
printf("\n");
} if (opt_create) {
printf("\n");
}
}
}
}
}
}
}
and here is the 's' case:
case 's': {
int main(void)
{
DIR *directory;
struct dirent *entry;
directory = opendir(".");
if (directory == NULL)
{
printf("Error reading directory\n");
return 1;
}
while ((entry = readdir(directory)) != NULL)
if (entry->d_type == DT_REG)
{
printf("file: %s\n", entry->d_name);
}
}
if (closedir(directory) == -1)
{
printf("Error closing directory\n");
return 1;
}
return 0;
}
}
I attempted to move the case out of the switch statement but to no avail.

Related

Linux terminal tool dosent run one of the getopt commands

So I have a simple terminal tool here that makes use of getopt but when I run it everything runs smoothly except "cast -s" it returns "cast: invalid option -- 's'" but it fails silently without any error messages. Ive tried it on different hardware, operating systems and more but it dosent seem to work just right
#include <errno.h>
#include <getopt.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#define DATA_SIZE 1000
void print_help(void)
{
printf("Help\n");
printf("> cast -d (deletes file)\n");
printf("> cast -r (renames file)\n");
printf("> cast -c (create new file)\n");
printf("> cast -s (scans for file in directory)\n");
printf("________________________________________\n");
printf("Find an error or a bug? please submit it in the issues section on github\n");
}
int main(int argc, char **argv)
{
int option_val = 0;
int opt_delete = 0;
int opt_help = 0;
int opt_rename = 0;
int opt_create = 0;
int opt_scan = 0;
while ((option_val = getopt(argc, argv, "dhrc")) != -1) {
switch (option_val) {
case 'd':
char filename[65]; //Hope your filename isnt bigger than this
printf("Filename or path to file: ");
scanf("%s", filename); // checks to see if your filename isnt bigger than specified
if (remove(filename) != 0)
{
fprintf(stderr, "Errno: %d\n", errno);
perror("Error msg");
} else printf("%s, deleted.\n", filename);
opt_delete = 1;
break;
case 's':
{
DIR *dp;
struct dirent *dirp;
if (argc != 2) {
fprintf(stderr, "usage: s directory_name\n");
return 1;
}
if ((dp = opendir(argv[1])) == NULL) {
perror("cant copen");
return 2;
}
while((dirp = readdir(dp)) != NULL)
printf("%s\n", dirp->d_name);
closedir(dp);
return 0;
}
opt_scan = 1;
break;
case 'r':
char file[65], new[65];
printf("File: ");
scanf("%s", file);
printf("New name: ");
scanf("%s", new);
if (rename(file, new) != 0)
{
fprintf(stderr, "Errno: %d\n", errno);
perror("Error msg");
} else printf("%s --> %s", file, new);
opt_rename = 1;
break;
case 'c':
FILE *f = fopen("Castdocument.txt", "w+");
fprintf(f, "Finished with maybe no errors? Rename this file to whatever you would like and change the filename extension with ""cast -r""");
printf("File created! (Check your home directory for ""Castdocument.txt"" file and modify that to fit your needs)");
fclose(f);
opt_create = 1;
break;
case 'h':
opt_help = 1;
break;
default: /* '?' */
//print_help();
}
}
if (opt_delete) {
printf("\n");
} if (opt_rename) {
printf("\n");
} if (opt_help) {
print_help();
} if (opt_create) {
printf("\n");
}
}
Ive attempted to run this on a different system to no avail

A C program that copies all the content a directory including files and folders

The last Code I just posted now works. That is, it is able to copy all files from one directory to another. But now, I wanted to update it in such a way that it copies also directories including it contents be it files or folders.
Here is what I did so far, but this has been unable to accomplish my dream.
I really don't know what is wrong with the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#define Max 8192
int copy_files(char *src, char *dest);
int copy_dir(char *srcpath, char *destpath);
int copy_dir(char *srcpath, char *destpath)
{
DIR *sdp = NULL;
DIR *ddp = NULL;
struct dirent *entry;
struct stat sb;
char tempsrc[strlen(srcpath)+1];
char tempdest[strlen(destpath)+1];
strcat(srcpath, "/");
strcat(destpath, "/");
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
if( (sdp = opendir(srcpath)) == NULL )
{
printf ("%s is not an existing directory\n", srcpath);
return 0;
}
else
{
while( (entry = readdir(sdp)) )
{
stat(entry->d_name, &sb);
// printf("Cannot open directory\n");
// exit(EXIT_FAILURE);
switch (sb.st_mode & S_IFMT)
{
case S_IFREG:
{
strcat(tempdest, entry->d_name);
strcat(tempsrc, entry->d_name);
copy_files(tempsrc, tempdest);
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
break;
}
case S_IFDIR:
{
strcat(tempsrc, entry->d_name);
strcat(tempdest, entry->d_name);
mkdir(tempdest, 0777);
ddp = opendir(tempdest);
copy_dir(tempsrc, tempdest);
strcpy(tempdest, destpath);
strcpy(tempsrc, srcpath);
break;
}
}
}
closedir(sdp);
closedir(ddp);
return 1;
}
}
int copy_files(char *src, char *dest)
{
int sfd, dfd, ret_in, ret_out;
char buff[Max];
if ( (sfd = open(src, O_RDONLY)) == -1 )
{
printf("Error while reading %s\n", src);
perror(src);
exit(1);
}
if ( (dfd = creat(dest, 0644)) == -1 )
{
printf("Error while creating %s\n", dest);
perror(dest);
exit(1);
}
while( (ret_in = read(sfd, &buff, Max)) > 0 )
{
ret_out = write (dfd, &buff, ret_in);
if (ret_out != ret_in)
{
printf("write error to %s", dest);
perror(dest);
exit(1);
}
if (ret_in == -1)
{
printf("read error from %s", src);
perror(src);
exit(1);
}
}
close(sfd);
close(dfd);
return 1;
}
int main(int argc, char *argv[])
{
int i;
if (argc != 3)
{
printf ("Usage: Programme_name src dest\n e.g. ./cp src dest\n");
exit(1);
}
char *srcp = argv[1];
char *destp = argv[2];
if (srcp[0] == '/' && destp[0] == '/')
{
for (i = 1; i <= strlen(destp); i++)
destp[(i-1)] = destp[i];
for (i = 1; i <= strlen(srcp); i++)
srcp[(i-1)] = srcp[i];
copy_dir(srcp, destp);
}
else if (srcp[0] != '/' && destp[0] == '/') //./ass1 test /t2
{
for (i = 1; i <= strlen(destp); i++)
destp[i-1] = destp[i];
strcat(destp, "/");
strcat(destp, srcp);
copy_files(srcp, destp);
}
else
{
printf ("Usage: Programme_name src dest\n e.g. ./cp src dest\n");
exit(1);
}
}
You are indefinitely adding /. to the temporary source and destination paths when the directory entry . is read, which is present in all directories. Instead, you should skip the . and .. entries.
Another error is the dimensioning of the temporary paths:
char tempsrc[strlen(srcpath)+1];
char tempdest[strlen(destpath)+1];
The arrays are made just long enough to hold the original paths, though sub-directory names are then appended, overflowing the arrays. Better:
char tempsrc[PATH_MAX];
char tempdest[PATH_MAX];

how to get the source file's (the file which I want to copy) and the copied file's information in C

I want to get the source file information, when I want to copy the source file and then get the destination file information, when the source file has already being copied. The problem with the code is that I can't copy and get the source and destination file information.
How could you be able to fix my code to copy a file and get source and destination information?
Code:
#define BUFFER 100 // ** increased - file path can get pretty long
#define BUFFERSIZE 4096
#define COPYMODE 0644
void oops(char *, char *);
int file_exist(char *filename)
{
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
int main(int argc, char *argv[])
{
char ch, source_file[20], target_file[20];
FILE *source, *target;
// printf("Enter name of file to copy\n");
// fgets(source_file, 20, stdin);
source_file = argv[20];
source = fopen(source_file, "r");
if( source == NULL )
{
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
printf("Enter name of target file\n");
fgets(target_file, 20 , stdin);
target = fopen(target_file, "w");
if( target == NULL )
{
fclose(source);
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while( ( ch = fgetc(source) ) != EOF )
fputc(ch, target);
printf("File copied successfully.\n");
fclose(source);
fclose(target);
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_SUCCESS);
}
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
exit(EXIT_SUCCESS);
}
void oops(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit(1);
}
I am unsure where your difficulty lies, apart from errors mentioned in comment. I've simplified your code, removing the bitfield masks as I don't have their definitions.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
int ch; // <--- int not char
struct stat sb;
FILE *source, *target;
if (argc < 3) {
printf("Enter two args: source and destination file names\n");
exit(EXIT_FAILURE);
}
source = fopen(argv[1], "r");
if( source == NULL ) {
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
target = fopen(argv[2], "w");
if( target == NULL ) {
fclose(source);
printf("Press any key to exit...\n");
exit(EXIT_FAILURE);
}
while( ( ch = fgetc(source) ) != EOF )
fputc(ch, target);
fclose(source);
fclose(target);
printf("File copied successfully.\n");
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_SUCCESS);
}
printf("File %s type: 0x%04X Mode: 0x%04X\n", argv[1], (unsigned)sb.st_ino, (unsigned)sb.st_mode);
if (stat(argv[2], &sb) == -1) {
perror("stat");
exit(EXIT_SUCCESS);
}
printf("File %s type: 0x%04X Mode: 0x%04X\n", argv[2], (unsigned)sb.st_ino, (unsigned)sb.st_mode);
return 0;
}
Program output:
>test test.c test2.c
File copied successfully.
File test.c type: 0x0000 Mode: 0x81B6
File test2.c type: 0x0000 Mode: 0x81B6

tee command in C with option

I have command tee in C, and I should add option -a which :supports the -a option file, which results in adding the data being read to the end of the file, if available. Anyone could help?
I try put inside :
if ( (option = getopt(argc,argv,"a")) != -1 ){
switch (option){
case 'a':
But I don't know what next.
main(int argc, char *argv[]){
FILE *fp, *fp1;
char buffer;
if(argc != 4){
printf("\nError");
printf("\nSintaxis: tee [archivo1] [archivo2]\n");
exit(0);
}
if(strcmp(argv[1], "tee") == 0){
fp = fopen(argv[2], "r");
fp1 = fopen(argv[3], "w");
printf("\Content in %s:\n", argv[2]);
while(!feof(fp)){
buffer = fgetc(fp);
fputc(buffer, fp1);
printf("%c", buffer);
}
printf("\n\n%s received %s\n", argv[3], argv[2]);
fclose(fp);
fclose(fp1);
}
else
printf("\nThe first argument have to be tee\n");
}
Second version , I think better.
But if I run program without option -a else if (argc == 2) {
printf("Write to file: %s\n", argv[1]);
process_save_reading(argv[1],"w+") write some text in file argv[1] -file is empty
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void usage() {
fprintf(stderr, "Usage: [-a program]");
exit(1);
}
void err(char * s1, char * s2) {
fprintf(stderr, "Error: %s ", s1);
perror(s2);
exit(1);
}
void process_reading() {
int c = fgetc(stdin);
while (c != EOF) {
putchar(c);
c = getchar();
}
}
void write_file_content(char * filename, int cnt, const char* mode) {
FILE *fp;
if ((fp = fopen(filename, mode)) == NULL) {
fprintf(stderr, "Can not open file: %s\n", filename);
exit(1);
}
fputc(cnt, fp);
fclose (fp);
}
void process_save_reading(char * filename, const char* mode) {
int c = fgetc(stdin);
while (c != EOF) {
putchar(c);
write_file_content(filename, c, mode);
c = getchar();
}
}
int file_exists(char * filename) {
return access(filename, F_OK) != -1;
}
int main(int argc, char * argv[]) {
char * opts = "a:";
int c;
if (argc == 1) {
process_reading();
}
else if (argc == 2) {
printf("Write to file: %s\n", argv[1]);
process_save_reading(argv[1],"w+");
}
else {
while ((c = getopt(argc, argv, opts)) != -1) {
switch (c) {
case 'a':
if (!file_exists(optarg)) {
fprintf(stderr, "File: '%s' doesn't exists\n", optarg);
exit(1);
}
printf("Save to file: %s\n", optarg);
process_save_reading(optarg,"a+");

Recursively Remove Directories

I've tried several times to write a function to remove directories and the files within the directories, like rm -r, but I haven't managed to do it. The technique I've tried is:
/* rm command */
#include <fts.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#define DEBUG
int rm_file(const char **argv);
int rm_tree(const char **argv);
void usage(void);
int rflag = 0;
int main(int argc, char *argv[])
{
int ch;
while((ch = getopt(argc, argv, "Rr")) != -1) {
switch(ch) {
case 'R':
case 'r':
rflag = 1;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
while(*argv) {
if(rflag)
rm_tree(argv);
else
rm_file(argv);
argv++;
}
return 0;
}
int rm_tree(const char **argv)
{
FTS *ftsp;
FTSENT *ftsent;
if((ftsp = fts_open(argv, 0, NULL)) == NULL) {
fprintf(stderr, "error: rm: can't stat directory\n");
return 1;
}
while((ftsent = fts_read(ftsp)) != NULL) {
switch(ftsent->fts_info) {
case FTS_DNR:
fprintf(stderr, "error: rm: can't stat directory\n");
break;
#ifndef DEBUG
case FTS_D:
rm_tree(&ftsent->fts_accpath);
break;
#endif
case FTS_F:
if(unlink(ftsent->fts_accpath) == -1) {
fprintf(stderr, "error: rm: can't remove file\n");
}
break;
case FTS_SL:
if(unlink(ftsent->fts_accpath) == -1) {
fprintf(stderr, "error: rm: can't remove file\n");
}
break;
default:
if(unlink(ftsent->fts_accpath) == -1) {
fprintf(stderr, "error: rm: can't remove file\n");
}
break;
}
}
if(rmdir(*argv) == -1) {
fprintf(stderr, "error: rm: can't remove directory\n");
return 1;
}
return 0;
}
int rm_file(const char **argv)
{
struct stat st;
if(lstat(*argv, &st) == -1) {
fprintf(stderr, "error: rm: can't stat file\n");
return 1;
}
if(S_ISDIR(st.st_mode)) {
fprintf(stderr, "error: rm: can't remove directory\n");
return 1;
}
if(unlink(*argv) == -1) {
fprintf(stderr, "error: rm: can't remove file\n");
return 1;
}
return 0;
}
void usage(void)
{
fprintf(stderr, "usage: rm file1 file2\n");
exit(1);
}
But invariably, I get a segmentation fault or it just doesn't work. Am I looking in the right direction? I've tried using the ftw() functions and the opendir() functions, but I just haven't been able to figure out how to get this to work. I would appreciate it if someone could help.
The code included in the debug tags is where it tends to fail.
Take a look at how it is done in practice by analysing source code of rm in open source operating systems, e.g. OpenBSD (look for rm_tree).

Resources