C open() directory no error - c

I have a function that opens file then read theses files, with the standard open() et read() functions. I use the errno variables for all possible errors such as permission denied or no such file or directory, but when I use open on a directory it don't return a error it simply open it and try to read it.
So how can I get an error message when I give open a directory ?

Directory is also a file (In terms of Unix/Linux). So generally you won't get an error. You can use stat or fstat function for tracking of ordinary or special files.
When you use either stat or fstat, you need to declare a struct stat variable like struct stat var. The stat structure has a member called st_mode which has the information of what kind of file it is.
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

Directory also a file in Unix*, if you want to avoid to open a directory by open(), you may need to check the file type. As #nayabbashasayed say,you can use the stat to check the file type and more info.
Here is an example code to check the type by stat:
const char *filePath;
struct stat fileStatBuf;
if(stat(filePath,&fileStatBuf) == -1){
perror("stat");
exit(1);
}
/*
*You can use switch to check all
*the types you want, now i just use
*if to check one.
*/
if((fileStatBuf.st_mode & S_IFMT) == S_IFDIR){
printf("This type is directory\n");
}
Hope that can help you.

I don't wanted to use anything else as read and write, I found that the error is returned at using read() not by open()

Related

Get storage device block size from name/descriptor of a file on that device

Suppose that I have file name or an open file decriptor for a text file that resides on a storage device (hard disk, usb flash, dvd, etc.). How can I get block size of that device from file name/descriptor in Linux programmatically in C. I know about ioctl system call, but it accepts an open descriptor for device special file, not an open descriptor of a file on that device.
For example I have a file name "/home/hrant/file1.txt" (or an open file descriptor on that file) that is on some storage device (like /dev/sda1). I don't know on which device the file is. How to get block size of that device to read contents of file "/home/hrant/file1.txt" in blocks.
As fstat() man page says:
int fstat(int fildes, struct stat *buf);
int stat(const char *path, struct stat *buf);
The stat() function obtains information about the file pointed to by path. Read, write or execute permission of the named file is not required, but all directories listed in the path name leading to the file must be searchable.
The fstat() obtains the same information about an open file known by the file descriptor fildes.
The buf argument is a pointer to a stat structure as defined by and into which information is placed concerning the file.
the stat structure is defined as:
struct stat {
dev_t st_dev; /* device inode resides on */
ino_t st_ino; /* inode's number */
mode_t st_mode; /* inode protection mode */
nlink_t st_nlink; /* number of hard links to the file */
uid_t st_uid; /* user-id of owner */
gid_t st_gid; /* group-id of owner */
dev_t st_rdev; /* device type, for special file inode */
struct timespec st_atimespec; /* time of last access */
struct timespec st_mtimespec; /* time of last data modification */
struct timespec st_ctimespec; /* time of last file status change */
off_t st_size; /* file size, in bytes */
quad_t st_blocks; /* blocks allocated for file */
u_long st_blksize;/* optimal file sys I/O ops blocksize */
};
I hope it helps you.

What is lstat() alternative in windows?

In linux, when stat() is used with broken link files, it fails with -1. So I used lstat() which succeeded.
For the same case in windows, _stat() fails with broken shortcuts, but there is no _lstat() in windows. Please help to find the alternative for lstat() in windows.
The accepted answer does not provide a full stat equivalent. The stat struct is defined as
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
but GetFileAttributes.. does not provide any owner information (it returns data in a WIN32_FIND_DATA object). If you need that owner information, it looks like you can use GetSecurityInfo [1].
[1] https://msdn.microsoft.com/en-us/library/windows/desktop/aa446629%28v=vs.85%29.aspx
GetFileAttributes or GetFileAttributesEx probably (if I understood stat and lstat right). Quoting from the docs:
Symbolic link behavior—If the path points to a symbolic link, the function returns attributes for the symbolic link.
hey _stat() or stat() works fine on broken shortcuts as well. Thats the reason,there is no alternative like lstat(UNIX) in windows.
Where in Unix, stat() fails with broken links, so lstat is provided to fix the problem.
Thank you all for your help.

Function that returns file size?

int filesize(FILE * handle)
{
int filesize;
int old_pointer = ftell(handle);
fseek(handle, 0, SEEK_END);
filesize = ftell(handle);
fseek(handle, old_pointer, SEEK_SET);
return filesize;
}
Is this a good way for a function to return the size of a file?
It is one way to do it, as long as your files aren't too big (which, for a 32-bit system or Windows 64-bit, means not more than 2 GiB). It has the merit of more or less working on any platform. Of course, ftell() returns a long, not an int (so on a 64-bit non-Windows system, the files it can report on are much bigger, as long as you fix your code appropriately). However, requiring four function calls is a trifle expensive.
The POSIX alternatives are stat(), lstat() and fstat().
There will be analogues in the Windows API.
I'd personally use a function from the stat family, like so. Also, note that int may be too small for the return value (especially on 32-bit systems); off_t is guaranteed to work.
off_t filesize(FILE *handle) {
struct stat statbuf;
if (fstat(fileno(handle), &statbuf) != 0) {
// handle an error
} else {
return statbuf.st_size;
}
}
Note also that this can be easily tweaked to work for files that aren't open yet by using standard stat() instead of fstat().
You could use stat() or fstat() if you were on *nix.
Use stat:
#include <sys/stat.h>
int stat(const char *path, struct stat *buf);
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
---> off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

Is it possible getting and setting file name with struct stat descriptor?

Is it possible at get or set ( rename ) a file name with giving the absolute path of file, and a struct stat instance as parameters to lstat function. As I find in documentation struct seems like that;
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
What I want is something like that;
struct stat *s;
char *path; // assigning the ablosute path of file
int res = lstat(path, s);
if(res == -1)
return errno;
char *name = s->(someFielAboutFileName);
or
s->(someFieldAboutFileName) = name; // setting name
No. In unix, the name is not an inherent property of the file. A file can have multiple names (see hard links) or even none.
The names are just entries in directories.
In Unix, the name of the file belongs to the directory, not the file. Meaning, the same file can have multiple names (it's called "hard links" in Unix). This also means you can not find out the name from stat, since it deals with files, not names. You can use realpath to find real name of the file, with resolving symlinks, etc.
It seems that you want to modify a symbolic link. lstat() won't help you with that, as it only returns the status of the link, not even the name of the file it points to, and cannot be used to modify anything about the file anyway.
You'll probably have to unlink() the symbolic link, then call symlink() to recreate it and make it point to the other file:
unlink(path);
symlink(name, path);

Is there any C function to get the directory permission?

I am trying to implement the ls command in C without using the system function.
Is there a C function to get the directory/file permissions, so that I can display them?
Thanks.
The stat() system call takes a filename string and returns the following structure:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
This works equally well on directory entries as well as files and the st_mode is the specific field you're looking for.
The <sys/stat.h> header file should contain that structure and all the definitions along with #defines and/or macros for intelligently decoding the fields (see here for a sample).
If you're interested in how it's really done, you can look at the ls source code in GNU coreutils. But only use that to educate yourself. It's GPL so you can't just grab it for your own purposes and, if this is homework, your educator will almost certainly fail you if you turn in something that looks too similar to this.
Look into stat(). Sounds like you're on a Linux or POSIX system, so that should be the way.
Then look at the st_mode field of the struct stat, it contains the information about protection bits, which are often collectively called a file's "mode" (as reflected by the chmod command that changes the settings).
Going from the binary bits to a textual representation like ls' is ... an interesting challenge.
The stat functions family (stat(), lstat(), fstat()).

Resources