How to fix "too few arguments to function mkdir" - c

Im a coding noob. I have to compile some codes for my project in a HPC server. I can compile the codes in my laptop but when i run it on the HPC i get the error message
"too few arguments to function mkdir".
I have tried to print the output in the cwd and not in the output directory but it still didnt fix the problem. If i use the check command declared as a comment (which one of my instructors advised), I get the error check undeclared first use in the function.
void write_collection_pvd(int time_total, int time_save, char *directory, char *filename)
{
int x;
char dataFileName[255];
FILE *dataFile;
//#ifdef WIN32
mkdir(directory);
//#else
// check = mkdir(directory,0777);
//#endif
sprintf(dataFileName, "%s/%s.pvd", directory, filename);
}
i expect the pvd file to be written in the ouput directory. Thanks in advanceenter code here

In C, the mkdir function accepts two parameters: the name of the directory to create and the (typically octal) permission mode to give it. So instead of calling
mkdir(directory);
you should call something like
mkdir(directory, 0777);
That will give the new directory permissions of read, write, and search (execute) by the owner, group, and everybody else. But (at least under Unix and Linux) these permissions will be adjusted downward by your process's default permissions, which will typically turn off writability by world and often group.

Related

fprintf() is not working in ubuntu

I'm trying to learn File I/O concepts in C programming language. I'm using GNU / Linux ( Ubuntu 16.04 LTS ) and my IDE is eclipse 3.8. when I try to write in a file through fprintf() method, it doesn't create any files or if the file is even created, it doesn't write in it. I tried to fix the problem by using fflush() or setbuf(file_pointer, NULL) methods as is suggested here but still no change. I guess I'm writing the address of the file in a wrong way.
Here is the code:
#include <stdio.h>
int main(void){
FILE *file_pointer;
file_pointer=fopen("~/.textsfiless/test.txt","w+");
setbuf(file_pointer,NULL);
fprintf(file_pointer,"Testing...\n");
fclose(file_pointer);
return EXIT_SUCCESS;
}
Can someone explain what's wrong here?
On Linux, the ~ in ~/.textsfiless/test.txt is not expanded by the C library fopen... When you use ~ on the command line, it is expanded by your shell (but not by the program using it, started by the shell doing some execve(2)...) into your home directory; the expansion is called globbing. Read glob(7). You are very unlikely to have a directory named ~.
You should read Advanced Linux Programming
So you should check if fopen failed (it is very likely that it did fail). If you want to get a file in the home directory, you'll better use getenv(3) with "HOME" (or perhaps getpwuid(3) & getuid(2)...). See environ(7)
Perhaps a better code might be:
char*homedir = getenv("HOME");
if (!homedir) { perror("getenv HOME"); exit(EXIT_FAILURE); };
char pathbuf[512]; /// or perhaps PATH_MAX instead of 512
snprintf(pathbuf, sizeof(pathbuf),
"%s/.textsfiless/test.txt", homedir);
FILE *file_pointer = fopen(pathbuf, "r");
if (!file_pointer) { perror(pathbuf); exit(EXIT_FAILURE); };
and so on.
Notice that you should check against failures most C standard library (& POSIX) functions. The perror(3) function is useful to report errors to the user on stderr.
(pedantically, we should even test that snprintf(3) returns a length below sizeof(pathbuf) or use and test against failure asprintf(3) instead; I leave that test as an exercise to the reader)
More generally, read the documentation of every external function that you are using.
Beware of undefined behavior (your code is probably having some, e.g. fprintf to a NULL stream). Compile your code with all warnings & debug info (so gcc -Wall -g) and use the gdb debugger. Read What every C programmer should know about undefined behavior.
BTW, look into strace(1) and try it on your original (faulty) program. You'll learn a lot about the system calls used in it.
Most likely your call to fopen() fails. You don't have any checking in your program to ensure fopen even worked. It may not have, and this could be due to a variety of things, like you spelling the path wrong, wrong file or process permissions, etc.
To see what really happened, you should check fopen's return value:
#include <stdio.h>
int main(void){
FILE *file_pointer;
file_pointer=fopen("~/.textsfiless/test.txt","w+");
if (file_pointer == NULL) {
printf("Opening the file failed.");
return EXIT_FAILURE;
}
setbuf(file_pointer,NULL);
fprintf(file_pointer,"Testing...\n");
fclose(file_pointer);
return EXIT_SUCCESS;
}
Edit: Since your comment, you getting the path wrong is most certainly what happened. If you're executing your program from the current directory, and your file is in a folder called "textfiless" in your current directory and your file is called "test.txt", then you'd call fopen like this:
file_pointer=fopen("/textsfiless/test.txt","w+");

Daemon process unable to find file (specified via relative path)

I have a daemon process that spawns several threads one of which handles HTTP requests. The handler is intended to return a file located in
resources/html/index.html
I have the following code:
void * read_file_ex(char *file_name, int32_t *data_len) {
FILE *fp;
fp = fopen(file_name, "r");
... // more code to fetch file contents
fclose(fp);
}
void * read_file(char *file_name){
return read_file_ex(file_name, NULL);
}
And in the thread, I call:
read_file("resources/html/index.html");
The code crashes with a "Segmentation Fault" error when a request is made for that file.
When I use GDB to break at fopen, I notice that a NULL is returned and errno is set to 2 (File not found).
Also, when I change the code to use the absolute path of the file:
/usr/sbin/app/resources/html/index.html
then `fopen()' is able to find the index file and everything works fine.
Another thing to mention is that this error happens when run on Debian Linux but not on Ubuntu 12.04 which makes my question look even dumber.
I forgot to add that I am running the program from the same folder that contains the `resources' folder.
If the current directory of the process is not /usr/sbin/app (and it seems a bit unlikely that the current directory would be /usr/bin/app), then the relative pathname won't work. You should always check the return result from fopen() before attempting to use it. There are endless reasons why an open operation can fail even if you're in the correct directory, let alone when there's a chance that you aren't.
Note that if your process uses functions like daemon(), or is run via a daemonize program, the current directory can be changed to / even if you expected it to be somewhere else.
If you need to check the current directory of the process (a process has a single current directory common to all threads), you can use the getcwd() to get the current working directory.
If you need to change directory (again) after daemonizing your process, you can use chdir() to do so. There's also fchdir() which can be used to change back to a directory if you have an open file descriptor for the directory.

program doesnt work if called from another folder

In Command Prompt, this works: whatever\folder> bezier.exe
but this doesn't: whatever> folder\bezier.exe
My bezier program loads some settings from a local file, so I believe the problem is that the program thinks its directory is whatever\ when it is actually whatever\folder\. I'm calling it from within a C program using CreateProcess(). If I am correct in guessing the problem, is there any way to ensure the program has the right directory for itself?
the main method of bezier.exe:
int main(int argc, char* argv[]) {
char buf[200];
FILE* f = fopen("out.txt","w");
GetCurrentDirectory(200,buf);
fprintf(f,buf);
fclose(f);
SDL_Surface* screen;
SDL_Event e;
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_FULLSCREEN|SDL_HWSURFACE);
if (screen == NULL)
exit(-1);
SDL_ShowCursor(SDL_DISABLE);
srand(time(NULL));
loadColors(COLOR_FILE);
fill(screen, backColor);
initialiseVars();
while (e.type != SDL_KEYDOWN)
{
//do stuff
}
SDL_Quit();
return 0;
}
Here's the crazy part. With "..> folder\bezier.exe" it doesn't write its path, but it does start a new window. That doesn't make any sense to me, because SDL_SetVideoMode is after writing the path.
You can use GetModuleHandle and GetModuleFileName to find out where your execuatble file is, then use that information to create a file specification for your local settings file.
GetModuleHandle with a NULL argument will give you the handle for the current executable. Then, passing that to GetModuleFileName will give you the fully qualified name of that executable. Just strip off the executable filename from the end and add your configuration file name.
However, that's been a bad idea for a long time now, since Windows provides per-application and per-user settings areas for this sort of stuff - you can generally get those locations with SHGetFolderLocation() and its brethren.
Use the first method only if this is for a personal project. If you plan to release your software to the wild, you should separate executable and configuration information as per Microsoft guidelines.
Regardless of that, it appears you now have the problem that you think the file is not being written to. You need to check that. When you open that file out.txt for write, it does so in the current directory. If you're running in the parent directory (with folder\bezier.exe), it will create it in the parent directory and looking for it in the folder directory is a waste of time.
If you are looking in the directory where you're running the program from, and it's still not being created, there are possible reasons for this. For a start, you should check (ie, capture and output) the return codes from all those f* functions, fopen, fprintf and fclose.

Distinguish between optional arguments, pathname or file? c language

I am very new with c and less experienced with any other language :/
For an assignment at uni, I am a little stuck on this small part. Essentially I am required to write a 'ls' function that has 4 optional arguments, for example:
list [-l] [-f] [pathname] [localfile]
Now, the first two are straight forward. To make things more difficult, the 'localfile' doesn't necessarily exist and the 'pathname'(if given) will be located on the server I'm connecting to through a socket (so checking if it is a file is out and checking the pathname is out). I was thinking, check last 4 chars in the string for a '.txt' or something similar. I'm actually completely stumped and will present this problem to my course conveyor tomorrow, if I can't find a solution.
This is a very small part of what I actually have to do but any push in the right direction would be appreciated.
You will need to process argc and argv to get your command line arguments. That is the first thing to work on, getting the arguments - ensuring they are correct, and determining what is being asked for.
int main(int argc, char *argv[])
Assuming your are on Linux/Unix, you will need to use the directory functions opendir()/readdir()/closedir() - dirent.h. The stat() function will be required to satisfy the -l requirement. access() will determine if a file exists and then stat() will tell you if the file is a regular file or a directory.
I'd make a struct to hold the four optional arguments and return it from a function called "process_arguments" that takes argc and argv as parameters.
struct args {
bool valid;
bool l_option;
bool f_option
char directory[200];
char filename[200];
}
With the requirement for a socket connection you will have to write a "server program" that will be constantly running on the server and a "client program" that it will fork to handle the requests from your local program. Try and locate examples of socket programs.
Another check for whether you have a path string or a filename is to look for the path separator character - '/' if the server is Unix/Linux. This scheme shouldn't have any path separators in filenames, so the presence of one tells you it is a path.

Using popen() to open a program in command line?

Is it possible to open a program using another program? For example:
I want to make a command line application in C that will prompt the user to type in the name of a program (lets say Microsoft Word.app), and that program will launch. Would I do something like this:
#include <stdio.h>
#include <time.h>
int main (int argc, const char * argv[]) {
char programName[1000];
printf("Type in the name of the program you would like to open: ");
scanf("%s", programName);
popen(programName);
}
However, popen() asks me for another char. How would I go about using popen() to open the program?
EDIT: The following code works!
#include <stdio.h>
#include <time.h>
int main (int argc, const char * argv[]) {
char programName[1000];
char app[100] = ".app";
char openApp[100] = "open /Applications/";
printf("Type in the name of the program you would like to open: ");
scanf("%s", programName);
strcat(openApp, programName);
strcat(openApp, app);
system(openApp);
}
popen lets you launch a program and get a file descriptor to its input or output, much like fopen works for files. For instance, if you wanted to read the output of your program, you'd use popen("program", "r"). On the other hand, if you want to write to its input, you would use popen("program", "w"). Mac OS X also allows for r+, which lets you read the output and write to the input but this capability isn't standard and shouldn't be relied on for cross-platform code.
If you just want to launch a program, you might as well use the system function, which does that and waits until the program exits, at which point it returns the status code. system actually invokes the shell to work, so arguments will undergo expansion (environment variables, ~, etc).
EDIT Following your comment that system("Microsoft Word.app") doesn't work as you'd expect: there are several reasons for this, actually. Starting with the message you get: this is because what you wrote is equivalent to opening a terminal window and typing Microsoft Word.app. In other words, it tries to find a program called "Microsoft", then pass it the argument "Word.app". You would need to either quote the program name or escape spaces to have the shell understand it's a whole program name and not a program name then an argument: system("Microsoft\ Word.app")
Now, this should complain saying that the shell can't find the program "Microsoft Word.app", which is already a step forward.
This is because on Mac OS, app files aren't executable files: they're folders that the Finder displays as a single file. You can verify that by ctrl+clicking (or right-clicking) an app and selecting "Show package contents" (this will open the app folder). The actual executable for Microsoft Word.app must be somewhere along the path of Microsoft Word.app/Contents/MacOS/Microsoft Word.
As you can see, this is getting kind of complex. Luckily enough, Apple provides the open executable, which can use a bunch of OS services to figure out those details. It allows to launch applications in the following fashion:
open -a Microsoft\ Word
This should launch Word. (Notice how you still need to escape the spaces.) In pure C code, that would get you something like this:
system("open -a Microsoft\\ Word");
If you choose to use Objective-C and Cocoa, however, there is a very simple way to open applications:
NSString* appName = #"Microsoft Word"; // no escape!
[[NSWorkspace sharedWorkspace] launchApplication:appName];
NSString objects can be created from C string easily enough:
NSString* appName = [[NSString alloc] initWithCString:programName encoding:NSUTF8StringEncoding];
[[NSWorkspace sharedWorkspace] launchApplication:appName];
[appName release];
It would be better to use system(3) for this purpose.
The popen(3) function establishes a pipeline that can be read or written by the caller. But GUI applications do not use standard input and standard output, they connect to the graphical interface server, sometimes called the "window server". This server is already running and already has decided what its keyboard input will be, and it is always writing its output to the video device.
To start a .app you should actually run the open(1) program, so try something like:
system("open /Applications/MacVim.app");

Resources