I have the following code in C. I run it at FreeBSD. I compile it as cc -o bbb bb.c. Then run and get the output
$ ./bbb
-1
stat: No such file or directory
This is the Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
int main() {
struct stat *st;
int stat_code =0;
stat_code = stat("/", st);
printf("%d\n", stat_code);
perror("stat");
return 0;
}
int stat(const char *restrict path, struct stat *restrict buf);
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.
In your code stat("/", st); is path for directory only.
This the the function prototype for stat() from man 2 stat
int stat(const char *path, struct stat *buf);
Your code will get segmentation fault, because address of structure variable need to pass in stat() function.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {
struct stat st;
int stat_code =0;
stat_code = stat("test.txt", &st);
printf("%d\n", stat_code);
perror("stat");
return 0;
}
above will help you. For reference
man 2 stat
Related
I have a device that acts like a HID (keyboard). I was able to capture and grab the raw input of the device on Linux. I needed to get exclusive rights to the device so that no other application could receive input from it. I accomplished this using ioctl and EVIOCGRAB
But it doesn't compile under Windows. I have found that there is a RegisterRawInputDevices function but it doesn't seem to provide exclusive rights to the device. What could be used on Windows to achieve the same effect?
Here is my code that works on Linux
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <sys/time.h>
#include <termios.h>
#include <signal.h>
int main(int argc, char* argv[])
{
struct input_event ev[64];
int fevdev = -1;
int result = 0;
int size = sizeof(struct input_event);
int rd;
int value;
char name[256] = "Unknown";
char *device = "/dev/input/event16";
fevdev = open(device, O_RDONLY);
ioctl(fevdev, EVIOCGRAB, 1);
while (1)
{
read(fevdev, ev, size * 64);
value = ev[0].value;
printf ("code - %d \n", ev[1].code);
}
ioctl(fevdev, EVIOCGRAB, 0);
close(fevdev);
}
I am trying to get the parent directory stats.
If I wrtie code like below it return error: Bad address
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dirent.h>
int main(int agrc, char * argv[]){
struct stat *buffer;
int res = stat("..", buffer);
if(res != 0){
perror("error");
exit(1);
}
//printf("%d", buffer->st_ino);
}
But If I write code like this below, there is no problem.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dirent.h>
int main(int agrc, char * argv[]){
/* struct stat *buffer; */
struct stat buffer;
int res = stat("..", &buffer);
if(res != 0){
perror("error");
exit(1);
}
//printf("%d", buffer->st_ino);
printf("%d", buffer.st_ino);
}
I do not know why the result is different.
The variable buffer of definition struct stat * buffer is a pointer of struct stat
The &buffer is also a pointer of struct stat
The function is defined as below in manpage
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
...
I expected the result to be both successful, why the result is different? anyone can help, thanks a lot.
With struct stat buffer; , there is memory allocated for buffer on the stack.
But with struct stat *buffer; there is no memory allocated for buffer. You have to use a memory allocation function to allocate memory. This allocation happens on what is known as heap.
struct stat *buffer = malloc(sizeof(struct stat));
Note that stat() stats the file pointed to by path and fills in buf. So if buf does not point to memory that the program owns, it will result in error: Bad address.
similar question here.
But it only covers for a single directory level. For example if you gave /home/mypc/directory and if only directory doesn’t exist, it creates one. but when it comes to /home/mypc/directory/directory2 where both directory and directory2 doesn't exist, It gives a segmentation fault error. Could anyone suggest a suitable method for this.
thanks in advance.
If you don't want to depend on external processes, you could just write a recursive function to create a directory hierarchy:
int mkdirhier(char const* target) {
int r = 0;
struct stat st = {0};
if (-1 != stat(target, &st))
return 0; // already exists
char* parent = strdup(target);
if (strcmp(dirname(parent), target))
r = mkdirhier(parent); // recurse
if (parent)
free(parent);
if (!r && (r = mkdir(target, 0700)))
perror(target);
return r;
}
Live On Coliru
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <errno.h>
#include <time.h>
int mkdirhier(char const* target);
int main() {
char buf[1024];
srand(time(NULL));
snprintf(buf, sizeof(buf), "./tree/some%d/dir%d/sub", rand(), rand());
mkdirhier(buf);
snprintf(buf, sizeof(buf), "/nopermissions/tree/some%d/dir%d/sub", rand(), rand());
return mkdirhier(buf);
}
Prints
gcc main.c; ./a.out; find .
/nopermissions: Permission denied
.
./tree
./tree/some1804649601
./tree/some1804649601/dir1553142090
./tree/some1804649601/dir1553142090/sub
./main.cpp
./a.out
./main.c
Split the path into its components, and check each and every component of the path. So for the path /home/mypc/directory/directory2 you check and possibly create, in order
/home
/home/mypc
/home/mypc/directory
/home/mypc/directory/directory2
If you are going to use mkdir to create the directory just add -p.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
struct stat st = {0};
if (stat("/home/mypc/directory/directory2", &st) == -1) {
system("mkdir --mode=744 -p /home/mypc/directory/directory2");
}
I am looking for a peace of code to check if the argument I pass to my program is a directory or not. So far I found this:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
struct stat buf;
stat(argv[1],&buf);
exit(0);
}
But it does not really help me.
Use:
if(S_ISDIR(buf.st_mode))
printf(" Its a directoy\n");
else
printf("Its a file\n");
after stat(argv[1],&buf); call
I wrote a simple program to test lsetxattr() and lgetxattr() functions.
I just wanted to add an extended property to this file, and get the value again.
But I can't get the result as expected.
So what's the right way to use these two methods?
Thanks!
#define _GNU_SOURCE
#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <time.h>
#include <unistd.h>
int main()
{
char *path = "/tmp/abc.txt";
FILE *file = fopen(path, "w");
int id = 101;
if (lsetxattr(path, "user.id", &id, sizeof(int), 0) < 0)
printf("lsetxattr wrong\n");
int result;
if (lgetxattr(path, "user.id", &result, sizeof(int)) != sizeof(int)) {
printf("lgetxattr wrong\n");
}
printf("%d\n", result);
return 0;
}
This is likely because your /tmp mount does not support extended attributes. Looking at the man page:
ENOTSUP
Extended attributes are not supported by the file system, or are
disabled, errno is set to ENOTSUP.
You can verify this by changing the path to be outside of that mount, such as in the current directory (assuming it's outside of that mount of course):
char *path = "abc.txt";
Assuming your other mounts do support extended attributes of course (this is more likely). If you have to do it on /tmp, then you'll have to look at some manuals to figure out how to enable it on /tmp (tmpfs).
Looks like both lsetxattr() and lgetxatter() return -1 by default:
#include <errno.h>
#include <sys/xattr.h>
ssize_t
lgetxattr (const char *__path, const char *__name,
void *__value, size_t __size)
{
__set_errno (ENOSYS);
return -1;
}
stub_warning (lgetxattr)
#include <stub-tag.h>
I found this on glibc's source code: lgetxattr.c and lsetxattr.c