I do not understand why after creating directory mkdir return different values. In this example i'm trying to make a directory if not so error handle otherwise go to this directory if not so error handle.
But it's not working as I want!
It shows me 'failed to create' but actually creates the directory.
If I read reference right it returns 0 when successes.
Code:
char* dirName = "Output";
FILE *output;
if(!mkdir(dirName))
if(chdir(dirName))
printf("Permission to open a new directory is denied");
else
printf("Permission to create a new directory is denied");
It looks like you need curly braces around the if statement bodies so that the else is bound to the correct if statement.
According to the documentation of mkdir:
Upon successful completion, mkdir() shall return 0. Otherwise, -1 shall be returned, no directory shall be created, and errno shall be set to indicate the error.
Now, remember, in C 0 evaluates to false, non-zero evaluates to true. So, when you check if( mkdir( ... ) ) you are essentially asking if mkdir returned non-zero. And -1 is non-zero, so you are asking whether mkdir() failed, not whether mkdir() succeeded.
What you want to do instead is if( mkdir ( ... ) == 0 ).
Also, in the event of failure, you have no reason to suppose that the reason of the failure was an "access denied" error. Check errno and report the correct error accordingly.
As correctly diagnosed by John Carpenter, the else relates to the second if. Use braces to avoid this bug known as the dangling else issue.
There is another issue in your code: under Linux or BSD, the prototype for mkdir is:
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *path, mode_t mode);
Do you include the system header files?
Not passing proper permissions, such as 0777 invokes undefined behavior, the syscall wrapper will pass indeterminate permissions, creating the directory with inconsistent permissions.
Here is a corrected version:
const char *dirName = "Output";
if (!mkdir(dirName, 0777)) {
if (chdir(dirName)) {
printf("Permission to open a new directory is denied");
}
} else {
printf("Permission to create a new directory is denied");
}
Related
While executing a C program,A debug print should be inserted to a log file (say log.txt),
but this C program is executed from various places.
So, multiple logs were found in log.txt
I want that debug to be present only once in the log.txt.
How to insert a check in C program to achieve the above requirement
I have tried with static variable, but it works only if for the function called first time
not the file.
whether access function would help this scenario??
You need some way for the programs to store that they've done a thing, know as a semaphore.
Simplest thing to do is use a shared location like /var/run/ to place a semaphore file. Then each program attempts to create that file. If it already exists, they can assume someone else already performed the action.
To do that we use the open system call (not fopen) for fine control. Using both the O_CREAT and O_EXCL flags says to create the file, and error if it already exists. This is atomic, we're checking if the file exists and creating it in one action. There's no way two programs could accidentally check & create at the same time.
#include <stdio.h>
#include <fcntl.h>
#include <stdbool.h>
bool check_semaphore(const char *file) {
if( open(file, O_CREAT|O_EXCL) >= 0 ) {
return true;
}
else {
return false;
}
}
int main() {
if( check_semaphore("did_debug_log") ) {
FILE *log = fopen("log.txt", "a");
if( !log ) {
perror("Couldn't open log.txt");
}
fprintf(log, "Some debug stuff\n");
}
}
You can use more sophisticated shared storage as a semaphore, like shared memory or a shared database such as SQLite, but the basic technique is the same. Check if the operation has been complete while also declaring you're going to do it in an atomic operation.
Language: C
OS: Ubuntu
I'm simply trying to create a FIFO named pipe using the command:
state = mknod("pipe.txt", S_IFIFO | 0666, 0);
the problem is i always get the state's value to be -1 (meaning it has failed) instead of 0.
perror returns 'pipe.txt: File exists'
i have no idea how should i debug such issue or what could be the reason, hope anyone code guide me what's wrong.
(note: the file pipe.txt exist on same path as source file.)
Read: int mknod(const char *path, mode_t mode, rdev_t dev_identifier);
General Description:
Creates a new character special file or FIFO special file (named pipe), with the path name specified in the path argument.
If file already exists then it will fails with error: File exists
To avoid this error, remove(unlink()) the file, As I am doing in my below code(read comment):
int main() {
char* file="pipe.txt";
unlink(file); // Add before mknod()
int state = mknod(file, S_IFIFO | 0666, 0);
if(state < 0){
perror("mknod() error");
}
return 0;
}
You should examine errno to see what the error is but it's probably EEXIST since I believe that's what happens if the file already exists.
From the Linux documentation for mknod:
If pathname already exists, or is a symbolic link, this call fails with an EEXIST error.
However, if the file already exists and is the pipe you created in an earlier run, you can safely reopen it. All mknod (and its often preferred cousin, mkfifo) does is actually create the FIFO, you still have to open it at both ends to get the data transfer happening.
Here i used below in code on linux.
using cp command in system function.
I know about system function it will return the 0 if command successfully executed.otherwise it will return error code.
If here i use proper source and destination path than i got output like this
Number == 0
If i give wrong source and destination path than i got
cp: cannot create regular file `/home/sam/test/test': No such file or directory
Number == 256
cp: cannot stat `/home/sam/main/test2/test': Not a directory
Number == 256
Here i want to know the error code of cp command what cp command return here.
My questions are here
1 System function return error code of cp command?
2 Can i get error code of cp command from source code of cp command?
3 i want to handle all types of error in this cp command.
code :
#include <stdlib.h>
#include <stdio.h>
void main()
{
int a;
a = system("cp /home/sam/main/test /home/sam");
printf("Number == %d\n",a);
}
So any body please Explain me about this all
The correct way to user the return value of system is with the wait-specific macros.
if (WIFEXITED(a)) {
int rc;
rc = WEXITSTATUS(a);
printf("Exit with status: %d\n", rc);
} else {
/* Killed by a signal. */
}
The man page of system states:
RETURN VALUE
The value returned is -1 on error (e.g. fork(2) failed), and the return status of the command otherwise. This latter return
status is in the format specified in wait(2). Thus, the exit code of the command will be WEXITSTATUS(status). In case
/bin/sh could not be executed, the exit status will be that of a command that does exit(127).
If the value of command is NULL, system() returns nonzero if the shell is available, and zero if not.
system() does not affect the wait status of any other children.
So, you can get the exit status with WEXITSTATUS(a) whene WIFEXITED(a) is true.
In general, the possible exit codes of a command are specified in the manpage. For cp, there is no documentation, so you can't rely on anything. You might think of going with lower-level system commands (such as open or link).
256 typically means there was a permission issue
I have a simple example:
#include <stdio.h>
#include <errno.h>
int main() {
int result = rename("filea", "doesntexist/fileb");
if (result != 0) {
printf("NOOOO %d\n", errno);
}
return 0;
}
and I want to distinguish between 2 of the possible failures:
filea doesn't exist
directory for fileb doesn't exist
but it always returns errno = 2 when either doesn't exist... uhm
Any ideas how can I approach this?
Thanks
EDIT: If possible without manually checking if the files exist.
EDIT2: Not checking if the file exists is a stupid constraint ;) so, I've accepted one of the answers already. Thanks!
I don't know how you're going to check if a file exists without checking if a file exists, but hopefully this function will help you out:
#include <sys/stat.h>
if (!fileExists("foo")) { /* foo does not exist */ }
int fileExists (const char *fn)
{
struct stat buf;
int i = stat(fn, &buf);
if (i == 0)
return 1; /* file found */
return 0;
}
If your goal is to keep the code clean, then just use functions:
int main()
{
if (! renameFiles("fileA", "fileB")) {
fprintf(stderr, "rename failed...\n");
exit EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int renameFiles(const char *source, const char *destination)
{
int result = -1;
if ( (fileExists(source)) && (!fileExists(destination)) )
result = rename(source, destination);
if (result == 0)
return 1; /* rename succeeded */
/*
Either `source` does not exist, or `destination`
already exists, or there is some other error (take
a look at `errno` and handle appropriately)
*/
return 0;
}
You could return custom error codes from renameFiles() and conditionally handle errors based on which file does or does not exist, or if there is some other problem with the rename() call.
Call access() (unistd.h) first. Or stat(). And you are probably getting an ENOENT error when filea does not exist. Some ways you can get an error on fileB:
path cannot be found
no permissions on the path
fileB exists and you do not have permissions
you have a too long or malformed name
There are others but they are not very common.
There is no case where you should get an error when fileB is not there. You execute a mv filea fileb (what rename does) and all of the errors for mv apply here. Missing destination file is not one of them.
You should also have
#include <errno.h>
since you reference errno.
The ISO C standard does not even require the library function rename to set errno in case of error. All that is guaranteed is a non-zero return value on error (7.19.4.2, ยง3).
So whether this is possible or not depends on your platform (and it is not portable).
E.g. in Linux there is no way to distinguish which of them is missing by just looking at errno after rename (according to this man page).
If the errno is always 2 ENOENT "No such file or directory" on your system you are going to HAVE to check for the existence of something. On my system I get errno of 2 if old does not existent or if the directory path of new does not exist.
However there is much more then 2 possible errors. The link http://man.chinaunix.net/unix/susv3/functions/rename.html has 20 distinct errno values specified.
I would suggest that if the rename fails and the errno is 2 then check for the existence of old. If found then the problem is that the directory specified in the new doesn't exist.
While debugging some code I got something like below:
#include<stdio.h>
int main()
{
FILE *fb = fopen("/home/jeegar/","r");
if(NULL == fb)
printf("it is null");
else
printf("working");
}
Here in fopen I gave a somewhat valid path name but not a filename. Shouldn't fopen return NULL then? But it does not return null!
Edit:
If I give path of valid directory in fopen then it will print working:
If I give path of invalid directory in fopen then it will print it is null
Edit:
spec says
Upon successful completion, fopen() shall return a pointer to the object
controlling the stream. Otherwise, a null pointer shall be returned.
so here whether error code set or not, it MUST return NULL
And error code setting is an extansion to ISO C standard standard.
ERROR IS ALSO NOT GOING TO SET HERE
#include<stdio.h>
#include <errno.h>
int main()
{
errno = 0;
FILE *fb = fopen("/home/jeegar/","r");
if(fb==NULL)
printf("its null");
else
printf("working");
printf("Error %d \n", errno);
}
OUTPUT IS
workingError 0
I think that in Unix everything (directories included) is considered to be file so fopen should work on them.
The posix man page man 3p fopen says, in the section ERRORS:
The fopen() function shall fail if:
[...]
EISDIR The named file is a directory and mode requires write access.
(Emphasis mine). Since you are not requesting write access, and chances are that the path you use is a directory, the function does not fail.
About what can you use with a FILE* that refers to a directory, I have no idea.
As you might be very well aware that pretty much everything on Linux system is a file, if not a file then its a process (corrections & remarks welcome :) ) Directory is treated like a file which lists other files (Reference from TLDP); so opening to read a directory as a file is a valid operation and thus you do not get any error. Although trying to write to it is not allowed, so if you open directory in write or append mode, the fopen operation will fail (this has been very well mentioned is other responses & link to fopen documentation). Most of the file operation like read & write operations on this file stream will fail with the error stating that its a directory. Only use which could be found was finding the size of the file (directory in this case) using fseek to SEEK_END & ftell (which will most likely give a result of 4096).
Regarding using errno to get meaningful messages, you can use perror which is in stdio.h & pass message which will be added before the error message or strerror which is in string.h & pass errno which is in errno.h
Hope this helps!
How to check that errno?
You can check errno for example:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *fp;
errno = 0;
fp = fopen("file.txt", "r");
if ( errno != 0 )
{
// Here you can check your error types:
perror("Error %d \n", errno);
exit(1);
}
}
Error types you can find at http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html Error section.