Below code lists out all files in a directory, can somebody tell me how to copy these files/directory to another location provided using command line argument.
I want to return the name from the list function, the problem is ftw(,list,) takes the return type as int. Since name char, how can i return it?
#include <ftw.h>
#include <stdio.h>
#include <sys/stat.h>
#include<string.h>
int list(const char *name, const struct stat *status, int type);
int main(int argc, char *argv[]) {
if(argc == 1)
ftw(".", list, 1);
else
ftw(argv[1], list, 1);
return 0;
}
int list(const char *name, const struct stat *status, int type) {
if(type == FTW_NS)
return 0;
if(type == FTW_F)
if(type == FTW_D && strcmp(".", name) != 0)
return 0;
}
Related
I am trying to write a program that implements somehow the "dir" command that you can use in the Unix shell but I have encountered the following problem. I managed to read the current directory as I will show in the code but I don't know exactly how I am supposed to sort it in order to make it like the dir function which sorts the files from the directory
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
void dirfunction()
{
DIR* directory=opendir(".");
if(directory==NULL)
{
perror("Directory does not exist");
exit(1);
}
struct dirent* p;
p=readdir(directory);
int i=0;
while(p!=NULL)
{
if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
{
printf("%s ",p->d_name);
i++;
}
p=readdir(directory);
}
printf("\n");
closedir(directory);
}
int main(int argc,char** argv[])
{
dirfunction();
}
Should I basically do the normal sorting for an array of character, like adding all file names in an array of string and sort it with selection sort or another sort method? I don't really get how dir command sorts the files before printing them to the terminal.
Because readdir reuses the same buffer for the returned entry, we need a dynamic [growing] array to save/store the struct dirent entries.
Then, we need to sort the stored entries (e.g. use qsort).
Side note: int main(int argc,char **argv[]) is incorrect. It should be: int main(int argc,char **argv) There was one too many levels of indirection.
Below is the updated code with some enhancements. It is annotated:
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
// dynamic array of dirent structs
struct dirlist {
size_t count; // number of entries
struct dirent *base; // pointer to list start
};
// dirload -- load up directory
// RETURNS: directory list
struct dirlist *
dirload(const char *path)
{
size_t capacity = 0;
struct dirlist *list = calloc(1,sizeof(*list));
DIR *directory = opendir(path);
if (directory == NULL) {
perror("Directory does not exist");
exit(1);
}
struct dirent *p;
while (1) {
// get next entry
// this is overwritten, so we need to copy/save it below
p = readdir(directory);
if (p == NULL)
break;
// skip over "." and ".."
if (p->d_name[0] == '.') {
if (p->d_name[1] == 0)
continue;
if ((p->d_name[1] == '.') && (p->d_name[2] == 0))
continue;
}
// enlarge array
if (list->count >= capacity) {
capacity += 10;
list->base = realloc(list->base,sizeof(*list->base) * capacity);
if (list->base == NULL) {
perror("realloc");
exit(1);
}
}
// save dirent entry
list->base[list->count++] = *p;
}
closedir(directory);
// trim list to actual size
list->base = realloc(list->base,sizeof(*list->base) * list->count);
if (list->base == NULL) {
perror("realloc");
exit(1);
}
return list;
}
// dircmp -- compare dirent structs
int
dircmp(const void *lhsp,const void *rhsp)
{
const struct dirent *lhs = lhsp;
const struct dirent *rhs = rhsp;
int cmp;
cmp = strcmp(lhs->d_name,rhs->d_name);
return cmp;
}
// dirsort -- sort directory list
void
dirsort(struct dirlist *list)
{
if (list->count > 0)
qsort(list->base,list->count,sizeof(*list->base),dircmp);
}
// dirprint -- print directory list
void
dirprint(const struct dirlist *list)
{
const struct dirent *p = list->base;
for (size_t idx = 0; idx < list->count; ++idx, ++p)
printf("%s\n",p->d_name);
}
// dirdestroy -- destroy directory list
void
dirdestroy(struct dirlist *list)
{
if (list != NULL)
free(list->base);
free(list);
}
int
main(int argc, char **argv)
{
--argc;
++argv;
const char *dir;
if (argc > 0)
dir = *argv;
else
dir = ".";
struct dirlist *list = dirload(dir);
// sort the list
dirsort(list);
// print the list
dirprint(list);
// destroy the list
dirdestroy(list);
return 0;
}
I'm making a code to remove the file name and type from a path. However, i'm receiving warnings concerning the line where i change the content from a character. How could i get rid of the warning?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getPath(char *fullPath){
char *aux;
int a, b, c;
aux = malloc(50 * sizeof(char));
aux = fullPath;
a = strlen(aux);
for(b=0; b<a; b++){
if (aux[b] == '/'){
c = b;
}
}
for(c; c < a; c++){
///PROBLEM HERE
aux[c] = "";
}
///PROBLEM HERE
return aux;
}
int main(void) {
char C[50];
char *path, *filename;
scanf("%s", C);
path = getPath(C);
printf("%s", path);
}
aux[c] = ""; // here "" is a char *
aux is a char *, therefore aux[c] is a char (not a string "")
aux[c] = '\0';
As written in the comments, there still have other mistakes in the rest of the code: for example aux value is erased.
Tried fixing the entire code.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool getPath(char *const strippedPath, const int strippedPath_buflen,const char *const fullPath){
int b=strlen(fullPath);
for(;;){
--b;
if(b<0)
return false;
if('/'==fullPath[b])
break;
}
if(strippedPath_buflen<b+1)
return false;
strncpy(strippedPath,fullPath,b);
strippedPath[b]='\0';
return true;
}
int main(void) {
for(;;){
char C[50]={};
printf("> ");
fflush(stdout);
scanf("%s",C);
if(0==strcmp("quit",C))
break;
char path[3+1]={'X','X','X','X'};
if(getPath(path,4,C))
printf("%s\n",path);
else
printf("err\n");
}
return 0;
}
> aaaa/b.txt
err
> aaa/b.txt
aaa
> a/c/b.txt
a/c
> aa/b.txt
aa
> a/b.txt
a
> a/
a
> /b.txt
> b.txt
err
> quit
I am creating a struct called Job and I want to create an array of struct Job. The name of my array is jobQueue I populate the array using commandline args. The instructor has it set up to where **args is being used. After the user inputs the name of the job and the execution time it gets added to the array. However, when I try to print jobQueue[0].name using the list() funct I have written, the name does not get printed. I'm trying to get my code set up to where I can print the name. I have provided a minimal version of my overall project that just focuses on the specific problem I am encountering and should compile and run fine.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <assert.h>
#include <sys/wait.h>
#include <stdint.h>
#define EINVAL 1
#define E2BIG 2
#define MAXMENUARGS 7
//structure job initialize
struct Job {
//initializing name variable
char *name;
int executionTime;
};
//init the array
struct Job jobQueue[5] = {0};
//cmd function provided by intructor
int cmd_run(int nargs, char **args) {
int execT;
sscanf(args[2], "%d", &execT);
run(args[1], execT);
return 0;
}
//cmd function provided by intructor
void cmd_list() {
list();
}
//cmd function provided by intructor
static struct {
const char *name;
int (*func)(int nargs, char **args);
} cmdtable[] = {
/* commands: single command must end with \n */
{ "r", cmd_run},
{ "run", cmd_run},
{ "list\n", cmd_list}
};
//cmd function provided by intructor
//this is the function that handles the arguments entered by the user
//provided it just in case someone needs to see how arguments are being
//processed
int cmd_dispatch(char *cmd) {
time_t beforesecs, aftersecs, secs;
u_int32_t beforensecs, afternsecs, nsecs;
char *args[MAXMENUARGS];
int nargs = 0;
char *word;
char *context;
int i, result;
void *Dispatcher(void *arg);
for (word = strtok_r(cmd, " ", &context);
word != NULL;
word = strtok_r(NULL, " ", &context)) {
if (nargs >= MAXMENUARGS) {
printf("Command line has too many words\n");
return E2BIG;
}
args[nargs++] = word;
}
if (nargs == 0) {
return 0;
}
for (i = 0; cmdtable[i].name; i++) {
if (*cmdtable[i].name && !strcmp(args[0], cmdtable[i].name)) {
assert(cmdtable[i].func != NULL);
/* Call function through the cmd_table */
result = cmdtable[i].func(nargs, args);
return result;
}
}
printf("%s: Command not found\n", args[0]);
return EINVAL;
}
//adds job to the array using user arguments
void run(char name[], int executionTime) {
//creates a job using the arguments specified by user
struct Job job = {name, executionTime};
jobQueue[0] = job;
printf("\nJob added to queue now please type 'list'\n");
}
//name will not print here
void list() {
printf("\nSee how the name will not print below?\n");
char executionTimeStr[5];
for (int c = 0; c < sizeof (jobQueue) / sizeof (jobQueue[0]); c++) {
//prints job info formatted
if (jobQueue[c].name != NULL) {
sprintf(executionTimeStr, "%d", jobQueue[c].executionTime);
//job name will not print here, output is just left blank
printf("%s %20.8s", "Name", "ExecTime");
printf("%-10.15s %11.3s\n",
jobQueue[c].name,
executionTimeStr
);
}
}
}
int main(int argc, char *argv[]) {
printf("Welcome to our batch job scheduler\n");
printf("Please enter the following exactly: 'run job1 10' \n");
//ignore this, it handles my commandline parser
char *buffer;
size_t bufsize = 64;
buffer = (char*) malloc(bufsize * sizeof (char));
if (buffer == NULL) {
perror("Unable to malloc buffer");
exit(1);
}
while (1) {
printf("User Input: ");
getline(&buffer, &bufsize, stdin);
cmd_dispatch(buffer);
}
//ignore this, it handles my commandline parser
return 0;
}
I need to know a way for use environment variables in the C programming language. How can I use and read them?
For example, read an environment variable or take the value of an environment variable and load it in another variable.
You can use following functions -
char * getenv (const char *name)-returns a string that is the value of the environment variable name.
char * secure_getenv (const char *name)
Read about some more functions here -http://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access
Use the getenv function from stdlib.h. That's it!
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("test\n");
const char* s = getenv("PATH");
// If the environment variable doesn't exist, it returns NULL
printf("PATH :%s\n", (s != NULL) ? s : "getenv returned NULL");
printf("end test\n");
}
getenv:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char* my_env_var = getenv("MY_ENV_VAR");
if(my_env_var)
printf("Var found: %s", my_env_var );
else
printf("Var not found.");
return 0;
}
On windows, you would use GetEnvironmentVariable.
#include <stdio.h>
#include <winbase.h>
int main(int argc, char *argv[])
{
TCHAR buff[100] = T("");
DWORD resultLengthInCharacters = GetEnvironmentVariable(T("USERDOMAIN"), buff, 100);
if (resultLengthInCharacters > 0 && resultLengthInCharacters < 100) {
_tprintf(T("USERDOMAIN: %s\n"), buff);
} else if ( resultLengthInCharacters > 100) {
_tprintf(T("USERDOMAIN too long to store in buffer of length 100, try again with buffer length %lu\n"), resultLengthInCharacters);
} else {
// Error handling incomplete, should use GetLastError(),
// but typically:
_tprintf(T("USERDOMAIN is empty or not set in the Environment\n"));
}
return 0;
}
But if you are trying to get a standard path variable, you should use the SHGetFolderPath function with the right CSIDL variable (like from this question: How do I get the application data path in Windows using C++?)
Another way could be to use the global variable environ.
#include <stdio.h>
extern char** environ;
void main(int argc, char* argv[])
{
int i=0;
while(environ[i]!=NULL){
printf("%s\n",environ[i++]);
}
}
//Goal: Load data from a file into the struct
typedef struct {
int year;
char* make;
char* model;
int miles;
} Car;
void fill_garage(Car** garage, char* cars, int* size);
int main(int argc, char** argv)
{
if(argc<3)
{
printf("Not enough arguments.\n");
return 0;
}
int size;
Car** garage;
fill_garage(garage, argv[1], &size);
return 0;
}
void fill_garage(Car** garage, char* cars, int* size)
{
int i;
FILE* inputF=fopen(cars, "r");
fscanf(inputF, "%d", size);
garage=malloc(sizeof(Car)*(*size));
for(i=0; i<(*size); i++)
{
garage[i].make=malloc(sizeof(char)*MAX_STRING_LEN);
garage[i].model=malloc(sizeof(char)*MAX_STRING_LEN);
//The line below causes a segmentation fault when there are no errors
fscanf(inputF, "%d %s %s %d", &garage[i].year, garage[i].make, garage[i].model, &garage[i].miles);
}
}
//I'm not expecting anyone to just give me the corrected code (though that would be nice) If you could point be to a resource where I could learn about pointers would be great. Here's the assignment sheet if you want to see it. http://pastebin.com/LNeCx70m
You have to pass the address of garage to fill_garage(), so this
Car** garage;
fill_garage(garage, argv[1], &size);
should be
Car *garage;
fill_garage(&garage, argv[1], &size);
/* ^ pass the address of garage */
You don't need malloc() for a fixed size string, just redefine your struct like
typedef struct {
int year;
char make[MAX_STRING_LEN];
char model[MAX_STRING_LEN];
int miles;
} Car;
Check fopen() and malloc() returned values, if they fail both return NULL, if you failed to open the file, then you will cause undefined behavior. Also check the return value of fscanf().
Include stdio.h for printf() and fscanf() and stdlib.h for malloc().
I fixed your code, so it must not have any issues in principle
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRING_LEN 128
typedef struct {
int year;
char make[MAX_STRING_LEN];
char model[MAX_STRING_LEN];
int miles;
} Car;
void fill_garage(Car **garage, char *cars, int *size);
int main(int argc, char** argv)
{
if (argc < 3)
{
printf("Not enough arguments.\n");
return 0;
}
int size;
Car *garage;
fill_garage(&garage, argv[1], &size);
return 0;
}
void fill_garage(Car **output, char *cars, int *size)
{
int i;
FILE *inputF;
Car *garage;
if (output == NULL)
return;
*output = NULL;
inputF = fopen(cars, "r");
if (inputF == NULL)
return;
if (fscanf(inputF, "%d", size) != 1)
{
fclose(inputF);
return;
}
garage = malloc(sizeof(*garage) * *size);
*output = garage;
if (garage == NULL)
{
fclose(inputF);
return;
}
i = 0;
while ((i < *size) && (fscanf(inputF, "%d%127s%127s%d", &garage[i].year, garage[i].make,
garage[i].model, &garage[i].miles) == 4))
{
i += 1;
}
}