find directory in a C program - c

How can I find if a directory exists or not in a C program? I know that getcwd() gives you the current directory but I want to find ANY directory. Is there a function for that or how do I do it? I am using Ubuntu

opendir, readdir and closedir are POSIX functions, so they should be available in Linux, MacOS, Windows as well as any Unix type system.

you can use access() function , like for example:
access(path, F_OK);
It returns 0 if found. -1 if not found.

int mkdir (const char *filename, mode_t mode)
you need to include the header file sys/stat.h to use this function.
The mkdir function creates a new, empty directory with name filename. The argument mode specifies the file permissions for the new directory file.A return value of 0 indicates successful completion, and -1 indicates failure.
In case of failure and if your Directory already exists errno value will equal to EEXIST.

Related

Does the c rename() function delete files?

I am practicing programming in the C programming language and was experimenting with the rename() function. I am using the following code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
if(rename ("data", "database") )
{
fprintf(stderr, "Can't rename file\n");
exit(EXIT_FAILURE);
}
return 0;
}
This code changes the name of a file named, "data" to a file named, "database". I was wondering what would happen if you attempted to run this code, but already had a file named "database" in the same directory.
This is the contents of the directory that I have before running the rename() function:
And this is the contents of the directory that I have after running the rename() function:
It appears that the rename() function did correctly rename my file, but it also deleted the file that was already in this directory that had the same name. I was wondering if this is how the rename() function was designed to work or if this is something that my operating system (Windows 10 - cygwin64 - gcc compiler) is doing. Also, when using this function, should I first check to make sure that there are no files that already have the same name to prevent them from being deleted? Thank you for the help and insight.
You have to consult the documentation of your C library. According to the standard (N1570 7.21.4.2, emphasis mine):
The rename function causes the file whose name is the string pointed to by old to be
henceforth known by the name given by the string pointed to by new. The file named
old is no longer accessible by that name. If a file named by the string pointed to by new
exists prior to the call to the rename function, the behavior is implementation-defined.
In the case of gcc rename:
If oldname is not a directory, then any existing file named newname is removed during the renaming operation. However, if newname is the name of a directory, rename fails in this case.
In case of VS, however:
The new name must not be the name of an existing file or directory.
From cppreference.com:
If new_filename exists, the behavior is implementation-defined.
E.g. on Unix the behavior seems to be this (from man rename):
int
rename(const char *old, const char *new);
[…]
If new exists, it is first removed.
From rename doc :
If oldname is not a directory, then any existing file named newname is
removed during the renaming operation. However, if newname is the name
of a directory, rename fails in this case.

Create Directory Permissions

I would like to know something about directory creation in C.
I know in unix based systems, you can create a directory with this function:
mkdir (const char* directory_name,mode_t mode);
but, in windows, mkdir function, only accept one argument, the name of the directory.
you cannot specify mode bits for access permissions.
in windows the function for creating the directory is:
_mkdir (const char* directory_name);
so, a portable way to creating a directory is like:
#ifdef WIN32
_mkdir (directory_name);
#else
mkdir (directory_name,mode);
#endif
my question is, is there a way to specify permissions like mkdir in unix, but in windows?
You can use CreateDirectory and supply the appropriate SECURITY_ATTRIBUTES (the linked example uses the security descriptor and attributes for a registry key, but fundamentally this is no different than for a file).
You can set permissions with CreateDirectory, from the API Windows.
On windows there also is the chmod() analogon _chmod(): http://msdn.microsoft.com/en-us/library/1z319a54%28v=vs.100%29.aspx

does access function check the existence of file?

The access function checks to see whether the file can be accessed in the way specified by the how argument. The how argument either can be the bitwise OR of the flags R_OK, W_OK, X_OK, or the existence test F_OK.
The return value is 0 if the access is permitted, and -1 otherwise.
if the file does not exist, Does the access return -1 too?
I wan to develop a function in which I check the existence of a file. If the following access function did it, what kind of arguments I have to put according to the standard?
if (access("file_example", R_OK | W_OK | X_OK) != -1)
BTW: the file I want to check if exisits by access() function is created by the same application. so it's created by the same user
Those flags would check if the file is executable, writeable and readable by the process, lots of files won't be. The flag you're looking for is F_OK. F_OK tests for the existence of the file and nothing else.
I suggest reading the man page for access. It should be documented there.
You can use it.
if (access("file_example", F_OK) != -1)
int access(const char *path, int amode);
The value of amode is either the bitwise-inclusive OR of the access permissions to be checked (R_OK, W_OK, X_OK) or the existence test (F_OK).
Yes, with errno set to ENOENT.
According to the manual page, one of the errors returned is:
ENOENT A component of pathname does not exist or is a dangling symbolic link.
Also, in the second paragraph it clearly says:
F_OK tests for the existence of the file.

How to find out if a file or directory exists?

I am trying to make a simple program that handles files and directories, but I have two major problems:
how can I check whether a file or directory exists or not, and
how do I know if it is a file, directory, symbolic link, device, named pipe etc.? Mainly file and directories matter for now, but I'd like to know the others too.
EDIT: Too all of those who are suggesting to use stat() or a similar function, I have already looked into that, and while it might answer my first question, I can't figure out how it would answer the second...
Since you're inquiring about named pipes/symlinks etc, you're probably on *nix, so use the
lstat() function
struct stat info;
if(lstat(name,&info) != 0) {
if(errno == ENOENT) {
// doesn't exist
} else if(errno == EACCES) {
// we don't have permission to know if
// the path/file exists.. impossible to tell
} else {
//general error handling
}
return;
}
//so, it exists.
if(S_ISDIR(info.st_mode)) {
//it's a directory
} else if(S_ISFIFO(info.st_mode)) {
//it's a named pipe
} else if(....) {
}
Se docs here for the S_ISXXX macros you can use.
The stat() function should give you everything you are looking for (or more specifically lstat() since stat() will follow the link).
Use stat (or if you wish to get information about a symbolic link instead of following it and getting information about the destination, lstat)
NAME
stat - get file status
SYNOPSIS
#include <sys/stat.h>
int stat(const char *restrict path, struct stat *restrict buf);
DESCRIPTION
The stat() function shall obtain information about the named file and write it to the area pointed to by the buf argument. The path argument points to a pathname naming a file. Read, write, or execute permission of the named file is not required. An implementation that provides additional or alternate file access control mechanisms may, under implementation-defined conditions, cause stat() to fail. In particular, the system may deny the existence of the file specified by path.
If the named file is a symbolic link, the stat() function shall continue pathname resolution using the contents of the symbolic link, and shall return information pertaining to the resulting file if the file exists.
The buf argument is a pointer to a stat structure, as defined in the header, into which information is placed concerning the file.

"Getting" the path in Linux

I am writing a C program in Linux. Commands like execv() require a path in the form of a C string. Is there a command that will return the current path in the form of a C-style string?
getcwd():
SYNOPSIS
#include <unistd.h>
char *getcwd(char *buf, size_t size);
DESCRIPTION
The getcwd() function shall place an absolute pathname of the current working directory in the array pointed to by buf, and return buf. The pathname copied to the array shall contain no components that are symbolic links. The size argument is the size in bytes of the character array pointed to by the buf argument. If buf is a null pointer, the behavior of getcwd() is unspecified.
RETURN VALUE
Upon successful completion, getcwd() shall return the buf argument. Otherwise, getcwd() shall return a null pointer and set errno to indicate the error. The contents of the array pointed to by buf are then undefined....
The path argument to execv() is the path to the application you wish to execute, not the current working directory (which will be returned by getcwd()) or the shell search path (which will be returned by getenv("PATH")).
Depending on what you're doing, you may get more mileage out of the system() function in the C library rather than the lower-level exec() family.
This is not ANSI C:
#include <unistd.h>
char path[MAXPATHLEN];
getcwd(path, MAXPATHLEN);
printf("pwd -> %s\n", path);
If the path can be a relative path, you should be able to use '.' or './' as the path. I'm not sure if it will work, but you could try it.
You need to grab the environment variable PWD (present working directory).
I'm not sure what the library it is in, but it is a standard Linux header.
I was thinking of getenv() which would help if you also need to run system commands and need the various bin paths located in PATH.

Resources