Related
I'm getting a "too many arguments in function call" error in my C program. The error occurs at a line where I'm calling a function that has a fixed number of arguments. I'm not sure why I'm getting this error, as I'm not passing in more arguments than the function expects. Here's the code where the error occurs:
if (mkdir(path, 0777) == -1)
Here is full code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#define BUF_SIZE 1024
#define MAX_ARGS 10
// Print the usage message for the program
void print_usage() {
fprintf(stderr, "Usage: syscalls <command> [arguments]\n");
}
// Read the contents of a file and write them to stdout
int read_file(const char *path) {
static char buf[BUF_SIZE];
int fd = open(path, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 1;
}
ssize_t num_read;
while ((num_read = read(fd, buf, BUF_SIZE)) > 0) {
if (write(STDOUT_FILENO, buf, num_read) != num_read) {
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
return 1;
}
}
if (num_read == -1) {
fprintf(stderr, "Failed to read %s: %s\n", path, strerror(errno));
return 1;
}
return 0;
}
// Write a set of lines to a file
int write_file(const char *path, char *lines[], int num_lines) {
int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
fprintf(stderr, "Failed to open %s: %s\n", path, strerror(errno));
return 1;
}
int total_bytes = 0;
for (int i = 0; i < num_lines; i++) {
const char *line = lines[i];
size_t len = strlen(line);
ssize_t num_written = pwrite(fd, line, len, total_bytes);
if (num_written == -1) {
fprintf(stderr, "Failed to write to %s: %s\n", path, strerror(errno));
return 1;
}
total_bytes += num_written;
}
printf("Wrote %d B\n", total_bytes);
return 0;
}
// Create a directory
int make_directory(const char *path) {
if (mkdir(path, 0777) == -1) {
if (errno == EEXIST) {
fprintf(stderr, "%s already exists\n", path);
} else {
fprintf(stderr, "Failed to create %s: %s\n", path, strerror(errno));
}
return 1;
}
return 0;
}
// List the contents of a directory
int list_directory(const char *path) {
DIR *dir = opendir(path);
if (dir == NULL) {
fprintf(stderr, "Failed to open directory %s: %s\n", path, strerror(errno));
return 1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("%s\n", entry->d_name);
}
if (closedir(dir) == -1) {
fprintf(stderr, "Failed to close directory %s: %s\n", path, strerror(errno));
return 1;
}
return 0;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
print_usage();
return 1;
}
char *command = argv[1];
if (strcmp(command, "read") == 0) {
if (argc != 3) {
print_usage();
return 1;
}
return read_file(argv[2]);
} else if (strcmp(command, "write") == 0) {
if (argc < 4 || argc > MAX_ARGS + 2) {
print_usage();
return 1;
}
return write_file(argv[2], argv + 3, argc - 3);
} else if (strcmp(command, "mkdir") == 0) {
if (argc != 3) {
print_usage();
return 1;
}
return make_directory(argv[2]);
} else if (strcmp(command, "ls") == 0) {
if (argc != 3) {
print_usage();
return 1;
}
return list_directory(argv[2]);
} else {
print_usage();
return 1;
}
}
I am getting this error in terminal:
syscalls.c: In function 'write_file':
syscalls.c:54:31: warning: implicit declaration of function 'pwrite' [-Wimplicit-function-declaration]
ssize_t num_written = pwrite(fd, line, len, total_bytes);
^~~~~~
syscalls.c: In function 'make_directory':
syscalls.c:67:9: error: too many arguments to function 'mkdir'
if (mkdir(path, 0777) == -1) {
^~~~~
In file included from c:\mingw\include\unistd.h:56:0,
from syscalls.c:3:
c:\mingw\include\io.h:516:38: note: declared here
_CRTIMP __cdecl __MINGW_NOTHROW int mkdir (const char *);
Please help me to resolve this issue. Thank you
mkdir() is not specified in the C standard. It is specified in the POSIX standard, which is more or less a superset of the C standard.
This declaration of mkdir():
c:\mingw\include\io.h:516:38: note: declared here
_CRTIMP __cdecl __MINGW_NOTHROW int mkdir (const char *);
is the Microsoft version of the function, which takes a single argument, and does not conform to the POSIX standard.
From Microsoft's page:
The Microsoft-implemented POSIX function name mkdir is a deprecated
alias for the _mkdir function.
int _mkdir(
const char *dirname
);
Possible fix:
#ifdef _CRTIMP
#define mkdir(d,m) (mkdir)(d)
#endif
Credit: #chqrlie
Here is my code, for my own shell in C. When compiling I get an error: use of undeclared identifier 'output'. Here are examples of some of the errors when compiling:
error: use of undeclared identifier 'output' char
input[100];output[100];
test3.c:53:15: error: use of undeclared identifier 'output'
strcpy(output,args[i+1]);
^
test3.c:53:15: error: use of undeclared identifier 'output'
test3.c:60:8: warning: implicit declaration of function 'open' is
invalid in C99
[-Wimplicit-function-declaration] j = open(input, O_RDONLY, 0);
^
test3.c:60:20: error: use of undeclared identifier 'O_RDONLY' j =
open(input, O_RDONLY, 0);
^
test3.c:61:29: error: use of undeclared identifier 'O_RDONLY'
if ((j = open(input, O_RDONLY, 0)) < 0) {
test3.c:70:12: warning: implicit declaration of function 'creat' is
invalid in
C99 [-Wimplicit-function-declaration] if ((i= creat(output , 0644)) < 0) {
test3.c:70:18: error: use of undeclared identifier 'output' if ((i=
creat(output , 0644)) < 0) {
Here is my code:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "signal.h"
#include "unistd.h"
void prompt(char*);
void execute( char* );
char** parse( char* );
int main( int ac, char* av[] )
{
char input[255]; // buffer for supporting command
signal( SIGINT, SIG_IGN ); // ignore ctrl-c
while(1)
{
prompt(input);
execute( input );
}
};
void execute( char* str)
{
int fork_result, status, i = 0,j=0,in=0,out=0;
char input[100];output[100];
char** args = parse( str ); // splits the user command into arguments
fork_result = fork(); // attempt to fork
if ( fork_result == -1 ) // failure
{
perror("Failed to fork\n");
exit(1);
}
else if ( fork_result == 0 ) // I'm the child
{
for(i=0;args[i]!='\0';i++)
{
if(strcmp(args[i],"<")==0)
{
args[i]=NULL;
strcpy(input,args[i+1]);
in=2;
}
if(strcmp(args[i],">")==0)
{
args[i]=NULL;
strcpy(output,args[i+1]);
out=2;
}
}
if (in)
{
j = open(input, O_RDONLY, 0);
if ((j = open(input, O_RDONLY, 0)) < 0)
{
perror("Couldn't open input file");
exit(0);
}
dup2(j, 0);
close(j);
}
if (out)
{
if ((i= creat(output , 0644)) < 0)
{
perror("Couldn't open the output file");
exit(0);
}
dup2(i, STDOUT_FILENO);
close(i);
}
execvp( args[0], args );
perror("failed to exec\n");
exit(2);
}
else // I'm the parent
{
// wait here
wait(&status); // wait for child to finish
free( args ); // free dynamic memory
}
}
char** parse( char* str )
{
char** args = malloc( 256 );
int i = 0;
args[i] = strtok( str, " " );
while( args[i] )
{
i++;
args[i] = strtok( NULL, " " );
}
return args;
}
void prompt(char* input)
{
printf("$ "); // print prompt
fgets( input, 255, stdin );
input[strlen(input)-1] = '\0'; // overwrite \n with \0
if ( strcmp( input, "exit" ) == 0 ) // shell command
exit(0);
}
char input[100];output[100];
You want:
char input[100], output[100];
Also add: #include <fcntl.h>
In general, man open (and other functions you use) is your friend -- it tells you what #includes to add.
There are many more potential bugs and arbitrary limitations in your code. Some examples:
void execute( char* str)
{
char input[100], output[100];
...
if(strcmp(args[i],"<")==0)
{
args[i]=NULL;
strcpy(input,args[i+1]); // possible stack buffer overflow.
if(strcmp(args[i],">")==0)
{
args[i]=NULL;
strcpy(output,args[i+1]); // possible stack buffer overflow
char** parse( char* str )
{
char** args = malloc( 256 ); // limit of 256/sizeof(char*) parameters.
// on a 64-bit system, if more than 32 parameters are supplied ...
args[i] = strtok( NULL, " " ); // ... possible heap buffer overflow.
fgets( input, 255, stdin ); // arbitrary limit of 254 characters on command line.
There is no guarantee that the string ends with \n:
input[strlen(input)-1] = '\0'; // overwrite \n with \0
If I was grading this "shell", I'd give it an "F".
There are multiple errors in your code.
1. On line 27 you need to separate the two variable definitions of input and output with a comma instead of a semicolon char input[100], output[100]; or specify the type of output like char input[100]; char output[100]; You have done this already in the line above.
2. The compiler complains about missing definitions of the function open and the identifier O_RDONLY. This can be fixed by adding #include "fcntl.h" to your includes at the top of the file.
After these changes, the code compiles fine for me (with gcc 5.4.0):
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "signal.h"
#include "unistd.h"
#include "fcntl.h"
void prompt(char*);
void execute( char* );
char** parse( char* );
int main( int ac, char* av[] )
{
char input[255]; // buffer for supporting command
signal( SIGINT, SIG_IGN ); // ignore ctrl-c
while(1)
{
prompt(input);
execute( input );
}
};
void execute( char* str)
{
int fork_result, status, i = 0,j=0,in=0,out=0;
char input[100], output[100];
char** args = parse( str ); // splits the user command into arguments
fork_result = fork(); // attempt to fork
if ( fork_result == -1 ) // failure
{
perror("Failed to fork\n");
exit(1);
}
else if ( fork_result == 0 ) // I'm the child
{
for(i=0;args[i]!='\0';i++)
{
if(strcmp(args[i],"<")==0)
{
args[i]=NULL;
strcpy(input,args[i+1]);
in=2;
}
if(strcmp(args[i],">")==0)
{
args[i]=NULL;
strcpy(output,args[i+1]);
out=2;
}
}
if (in)
{
j = open(input, O_RDONLY, 0);
if ((j = open(input, O_RDONLY, 0)) < 0)
{
perror("Couldn't open input file");
exit(0);
}
dup2(j, 0);
close(j);
}
if (out)
{
if ((i= creat(output , 0644)) < 0)
{
perror("Couldn't open the output file");
exit(0);
}
dup2(i, STDOUT_FILENO);
close(i);
}
execvp( args[0], args );
perror("failed to exec\n");
exit(2);
}
else // I'm the parent
{
// wait here
wait(&status); // wait for child to finish
free( args ); // free dynamic memory
}
}
char** parse( char* str )
{
char** args = malloc( 256 );
int i = 0;
args[i] = strtok( str, " " );
while( args[i] )
{
i++;
args[i] = strtok( NULL, " " );
}
return args;
}
void prompt(char* input)
{
printf("$ "); // print prompt
fgets( input, 255, stdin );
input[strlen(input)-1] = '\0'; // overwrite \n with \0
if ( strcmp( input, "exit" ) == 0 ) // shell command
exit(0);
}
I am new in this field, and writing one server and client, but it really confusing that I can't get all the content, but some small clip.
My server code:
read(connfd, name, 20);
//recv(connfd,name,1024,0);
char* a=name;
while(a[0]!='\n'){
a++;
}
a[0]='\0';
printf("name:%s\n", name);
read(connfd, size, 20);
printf("size:%s\n", size);
recv(connfd,buf,8192,0);
printf("buf:%s\n", buf);
if((stream = fopen(name,"w+t"))==NULL){
printf("The file was not opened! \n");
}
int write_length = fwrite(buf,sizeof(char),8192,stream);
bzero(buf,8192);
if(put){
char *res="OK\n";
write(connfd, res, 1024);
}
fclose(stream);
and my client code is:
char buffer[8192];
bzero(buffer,8192);
char * put="PUT\n";
if ((write(fd, put, 8192)) <= 0) {
if (errno != EINTR) {
fprintf(stderr, "Write error: %s\n", strerror(errno));
exit(0);
}
}
struct stat st ;
stat( put_name, &st );
char str[100];
sprintf(str, "%d", st.st_size);
int len;
char *current=NULL;
len=strlen(put_name);
char sendname[1024];
strcpy(sendname,put_name);
strcat(sendname,"\n");
write(fd, sendname, 10);
strcat(str,"\n");
write(fd, str, 10);
FILE *stream;
if((stream = fopen(put_name,"r"))==NULL)
{
printf("The file was not opened! \n");
exit(1);
}
int lengsize = 0;
while((lengsize = fread(buffer,1,8192,stream)) > 0){
if(send(fd,buffer,8192,0)<0){
printf("Send File is Failed\n");
break;
}
bzero(buffer, 8192);
}
Now, I can send all content, but can receive part of them. for example, on my mac, server can receive name but the str is neglected, when I printf the str in the server, it shows the content of file. and the content of file is not the whole file content. Some content disappear. Could you tell me why?
The read and write functions are not guaranteed to send or receive the entire message with a single call. Instead, you're expected to sit in a loop, writing the message incrementally until everything has been sent and reading everything incrementally until everything has been read. For example, if you know exactly how much has been sent, you can do this:
char recvBuffer[BUFFER_SIZE];
int bytesRead = 0;
while (bytesRead < BUFFER_SIZE) {
int readThisTime = read(file, recvBuffer + bytesRead, BUFFER_SIZE - bytesRead);
if (readThisTime == -1) {
// handle error...
}
bytesRead += readThisTime;
}
If you don't know exactly how much has been sent, try this:
char recvBuffer[BUFFER_SIZE];
int bytesRead = 0;
while (bytesRead < BUFFER_SIZE) {
int readThisTime = read(file, recvBuffer + bytesRead, BUFFER_SIZE - bytesRead);
if (readThisTime == -1) {
// handle error...
}
if (readThisTime == 0) break; // Done!
bytesRead += readThisTime;
}
You are ignoring the return values of send() and recv(). You MUST check return values!
When sending the file, lengsize receives how many bytes were actually read from the file. Your client is sending too many bytes when lengsize is < 8192 (typically the last block of the file if the file size is not an even multiple of 8192).
But more importantly, although the client is telling the server the file size, the server is ignoring it to know when to stop reading. The server is also ignoring the return value of recv() to know how many bytes were actually received so it knows how many bytes can safely be written to the output file.
Try something more like this instead:
common:
int readData(int s, void *buf, int buflen)
{
int total = 0;
char *pbuf = (char*) buf;
while (buflen > 0) {
int numread = recv(s, pbuf, buflen, 0);
if (numread <= 0) return numread;
pbuf += numread;
buflen -= numread;
total += numread;
}
return total;
}
int sendData(int s, void *buf, int buflen)
{
int total = 0;
char *pbuf = (char*) buf;
while (buflen > 0) {
int numsent = send(s, pbuf, buflen, 0);
if (numsent <= 0) return numsent;
pbuf += numsent;
buflen -= numsent;
total += numsent;
}
return total;
}
int readInt32(int s, int32_t *value)
{
int res = readData(s, value, sizeof(*value));
if (res > 0) *value = ntohl(*value);
return res;
}
int sendInt32(int s, int32_t value)
{
value = htonl(value);
return sendData(s, &value, sizeof(value));
}
char* readStr(int s)
{
int32_t size;
if (readInt32(s, &size) <= 0)
return NULL;
char *str = malloc(size+1);
if (!str)
return NULL;
if (readData(s, str, size) <= 0) {
free(str);
return NULL;
}
str[size] = '\0';
return str;
}
int sendStr(int s, const char *str)
{
int len = strlen(str);
int res = sendInt32(s, len);
if (res > 0)
res = sendData(s, str, len);
return res;
}
server:
char buffer[8192];
char *name = readStr(connfd);
if (!name) {
// error handling ...
sendStr(connfd, "Socket read error");
return;
}
printf("name:%s\n", name);
int32_t filesize;
if (readInt32(connfd, &filesize) <= 0) {
// error handling ...
free(name);
sendStr(connfd, "Socket read error");
return;
}
printf("size:%d\n", filesize);
if ((stream = fopen(name, "wb")) == NULL) {
// error handling ...
printf("The file was not opened!\n");
free(name);
sendStr(connfd, "File not opened");
return;
}
while (filesize > 0) {
int numread = readData(connfd, buf, min(filesize, sizeof(buffer)));
if (numread <= 0) {
// error handling ...
close(stream);
free(name);
sendStr(connfd, "Socket read error");
return;
}
printf("buf:%.*s\n", numread, buf);
if (fwrite(buf, 1, numread, stream) != numread) {
// error handling ...
close(stream);
free(name);
sendStr(connfd, "File write error");
return;
}
filesize -= numread;
}
fclose(stream);
free(name);
sendStr(connfd, "OK");
client:
char buffer[8192];
struct stat st;
if (stat( put_name, &st ) != 0) {
// error handling ...
exit(0);
}
if ((stream = fopen(put_name, "rb")) == NULL) {
// error handling ...
printf("The file was not opened!\n");
exit(0);
}
if (sendStr(fd, put_name) <= 0) {
// error handling ...
close(stream);
exit(0);
}
int32_t filesize = st.st_size;
if (sendInt32(fd, filesize) <= 0) {
// error handling ...
close(stream);
exit(0);
}
int lengsize;
while (filesize > 0) {
lengsize = fread(buffer, 1, min(filesize , sizeof(buffer)), stream);
if (lengsize <= 0) {
printf("Read File Failed\n");
// error handling ...
close(stream);
exit(0);
}
if (sendData(fd, buffer, lengsize) <= 0) {
printf("Send File Failed\n");
// error handling ...
close(stream);
exit(0);
}
filesize -= lengsize;
}
close(stream);
char *resp = readStr(fd);
if (!resp) {
// error handling ...
exit(0);
}
if (strcmp(resp, "OK") == 0)
printf("Send File OK\n");
else
printf("Send File Failed: %s\n", resp);
free(resp);
how would you be able to check if the files have the same/different i-node numbers in C?
Because I want the rightly get the source and destination file information, where the files need to be rightly tested if they are the same.
Code:
#define BUFFER 100 // ** increased - file path can get pretty long
#define buffersize 4096
#define copymode 0644
void error(char *, char *);
int file_exist(char *filename)
{
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
int main()
{
int ac;
char *avc[4096];
int in_fd, out_fd, chars_n;
char buf[BUFFERSIZE];
char ch, sourceFile[20], targetFile[20];
FILE *source, *target;
printf("Enter name of file to copy\n");
fgets(source_file, 20, stdin);
source = fopen(sourceFile, "r");
*avc = sourceFile;
if( source == NULL )
{
printf("Press any key to exit...\n");
exit(1);
}
printf("Enter name of target file\n");
fgets(targetFile, 20, stdin);
// open(path, O_WRONLY | O_CREAT | O_TRUNC, mod);
if (file_exist (targetFile))
{
printf("File exists. \n");
}
else
target = fopen(targetFile, "w");
int dFN;
dFN = malloc(strlen(targetFile) + strlen(av[2] + 1));
if( target == NULL )
{
fclose(source);
printf("Press any key to exit...\n");
exit(1);
}
while( ( ch = fgetc(source) ) != EOF )
fputc(ch, target);
printf("File copied successfully.\n");
fclose(source);
fclose(target);
if ( ac != 3 ){
fprintf( stderr, "usage: %s source destination\n", *avc);
exit(1);
}
if ( (in_fd=open(avc[1], O_RDONLY)) == -1 )
error("Cannot open ", avc[1]);
if ( (out_fd=creat( avc[2], copymode)) == -1 )
error( "Cannot creat", avc[2]);
while ( (chars_n = read(in_fd , buf, buffersize)) > 0 )
if ( write( out_fd, buf, chars_n ) != chars_n )
error("Write error to ", av[2]);
if ( chars_n == -1 )
error("Read error from ", avc[1]);
if ( close(in_fd) == -1 || close(out_fd) == -1 )
error("Error closing files","");
return 0;
}
void error(char *s1, char *s2)
{
fprintf(stderr,"Error: %s ", s1);
perror(s2);
exit(1);
}
Use the stat(2) or fstat function call, which returns various informations about a file, including its inode number.
See for example http://pubs.opengroup.org/onlinepubs/009695399/functions/stat.html
I'm writing a simple program in Linux and when compiling I keep getting this error and don't understand why — I put all ; or {} in place:
ex1.c:49.1: error:expected declaration or statement at end of input
My code:
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>
int main (int argc, char* argv[])
{
if (argc!=3)
printf("Number of arugements passed is wrong - not 2\n");
char * file1 = argv[1];
char * file2 = argv[2];
int fdout1 = open(file1, O_RDONLY);
int fdout2 = open(file2, O_RDONLY);
struct stat stat_p1,stat_p2;
char * f1;
char * f2;
int i=0;
if (fdout1 < 0 || fdout2<0) /* means file open did not take place */
{
perror("ERROR opening files"); /* text explaining why */
return 1;
}
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
{
if((read(fdout1,f1,stat_p1.st_size)==-1) ||(read(fdout1,f1,stat_p1.st_size)==-1))
{
printf("ERROR reading files"); /* text explaining why */
return 1;
}
if (stat_p1.st_size!=stat_p2.st_size)
return 1;
if (strcmp(f1,f2)!=0)
return 1;
return 0;
}
Can anyone tell me why I keep getting this error?
It seems there is a typo
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
{
The last brace shall be a closing brace.
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
}
Take into account that if argc is less than 3 you have to exit the program
if (argc!=3)
printf("Number of arugements passed is wrong - not 2\n");
Otherwise these statements are invalid
char * file1 = argv[1];
char * file2 = argv[2];
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
>>>> { >>>>> change this to '}'
This error occurs when you have missing closing braces. As can be seen here:
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
{
You seem to have a typo, you should have closing brace instead of opening brace.
It should be like this
if ( (stat (file1, &stat_p1) == -1) ||( stat (file2, &stat_p2) == -1) ) /* declare the 'stat' structure */
{
printf(" Error occurred attempting to stat files");
return 1;
}
The closing brace is the problem, here it was opening brace on your program.