S_ISDIR returning different value for directory [closed] - c

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I'm currently trying to do some kind of recursive find where I need to distinguish regular files with directory.
I made a loop to check with S_ISDIR if a given file is a directory but when applied to /home, I don't get the expected result.
I only have a pome directory in /home so expected result would be :
/home/.
/home/..
/home/pome
but it doesn't detect pome as a directory, S_ISDIR() returns 0 for pome and 1 for . and ..
Code :
DIR * dir = opendir("/home");
if(dir==NULL){
puts("Unknown directory");
return 1;
}
char path[SIZE_PATH];
memset(path,'\0',sizeof(path));
strcpy(path,"/home");
struct dirent * trucdir;
char filename[SIZE_PATH];
memset(filename,'\0',sizeof(filename));
struct stat * filestat=malloc(sizeof(struct stat));
while((trucdir=readdir(dir))!=NULL){
memset(filename,'\0',sizeof(filename));
strcpy(filename,trucdir->d_name);
stat(filename,filestat);
if(S_ISDIR(filestat->st_mode)!=0){
puts(filename);
}
}
Isn't S_ISDIR supposed to return a non-zero value if the file is a directory ?

You have to check, that your stat()-call actually succeeds by checking its return value. In your case, the call to stat is:
stat("pome", filestat);
but your current working directory (cwd) is not /home!
Hence, the call to stat fails with -1 and errno ENOENT and the IS_DIR-macro is meaningless. The stat-calls to . and .. of course succeed, since they are present in all directories (although other information like inode number etc. doesn't match then)
You have to make sure that you either provide the full path in filename (i.e. /home/pome) or you set the cwd to /home before (with chdir("/home");); this should solve your issue!

Related

Permission denied when opening a file written using C [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I was doing some simple exercices with file descriptors with the following code:
int main(int argc, char *argv[]){
int fd1 = open("etc/passwd", O_RDONLY);
int fd2 = open("output.txt", O_CREAT,O_TRUNC,O_WRONLY);
dup2(fd1,0);
close(fd1);
dup2(fd2,1);
close(fd2);
}
Whenever I try to open the "output.txt" i get the following error:
Unable to open 'output.txt': Unable to read file '/home/joao/Desktop/Exercicios/output.txt' (NoPermissions (FileSystemError): Error: EACCES: permission denied, open '/home/joao/Desktop/Exercicios/output.txt').
Even though I believe some of the error refers to VSCode, I'm unable to open the file anywhere. Here is what I get when executing "ls -l" on the folder that has the .c file, the executable and the "output.txt":
---------T 1 joao joao 0 jun 9 21:54 output.txt
-rwxrwxr-x 1 joao joao 16784 jun 9 21:54 test
-rw-rw-r-- 1 700 joao 387 jun 9 21:54 teste.c
How can I fix this?
This:
int fd2 = open("output.txt", O_CREAT,O_TRUNC,O_WRONLY);
is not right. All the flags go in the second argument, combined with bitwise or, and the third is for the "mode", i.e. the access rights. See the manual page for much more details, of course.
So, it should be:
const int fd2 = open("output.txt", O_CREAT | O_TRUNC | O_WRONLY, S_IRWXU);
this will open with the mode S_IRWXU, i.e. permissions are granted to read/write/execute for the owner only.

Implement sudo su in a C program [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 3 years ago.
Improve this question
I writing a program that is used by a parent process. I cannot control the parent process, its permissions, and how it runs my process.
My program runs a device that needs root permissions, while the parent process does not have the corresponding permissions.
Tried to use setuid(0); setgid(0); in my program. Also, tried to add the user of the process to use sudo. In addition, I run the solutions below. Does not works
The code
if(dry_run == 0)
{
PRINT("reached here\n");
ret = ioctl((int64_t)device, NVME_IOCTL, &usr_io_cmd);
}
if (ret != 0 ) {
PRINT("ERROR : error %x returned\n", ret);
PRINT( "%s\n",strerror(errno) );
Where PRINT prints to a log file.
The log file
[2019-09-05 14:27:25] reached here
[2019-09-05 14:27:25] ERROR : error ffffffff returned
[2019-09-05 14:27:25] Operation not permitted
What can my program do? How can I implement "sudo su" in my program? Is there an alternative solution?
Edit: why this question is locked? I tried the solutions below and it did not worked.
What you need to do is to have your program have the setuid or setgid bit set in the file permissions. This will cause the running process to have the effective user id of that of the program owner (setuid) or effective gid that of the program group (gid). You then can perform actions as those identities or become those with setuid and setgid.
sudo su is a cargo-cult way of doing things - both are programs that more or less do the same thing - elevate permissions of an unprivileged caller.
I.e. to have the program foo owned by root with setuid bit set, you'd do:
gcc foo.c -o foo
sudo chown root:root foo
sudo chmod 4755 foo

File IO unit test in C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I need to write unit tests for a simple logger implemented in C (unit tests are in c++).
I'm searching for a way to mock an unsuccessful 'write' to the log file ,in order to see that the logger to responds appropriately and returns an error.
I tried renaming the log-file before writing on to it:
static bool fileWriteMiss() {
const char* testFile = "missLogFile.log";
const char* movedFile = "missedLogFile.log";
ASSERT_TRUE(
spLoggerCreate(testFile, SP_LOGGER_DEBUG_INFO_WARNING_ERROR_LEVEL) ==
SP_LOGGER_SUCCESS);
rename(testFile, movedFile);
ASSERT_TRUE(spLoggerPrintError("MSGA", "sp_logger_unit_test.c", __func__,
__LINE__) == SP_LOGGER_WRITE_FAIL);
spLoggerDestroy();
return true;
}
and I tried deleting the log-file before writing on to it:
static bool fileWriteMiss() {
const char* testFile = "missLogFile.log";
ASSERT_TRUE(
spLoggerCreate(testFile, SP_LOGGER_DEBUG_INFO_WARNING_ERROR_LEVEL) ==
SP_LOGGER_SUCCESS);
remove(testFile);
ASSERT_TRUE(spLoggerPrintError("MSGA", "sp_logger_unit_test.c", __func__,
__LINE__) == SP_LOGGER_WRITE_FAIL);
spLoggerDestroy();
return true;
}
ASSERT_TRUE function is implemented in an assertion library that is assumed to work properly.
spLoggerCreate is the initialization function of the logger structure (I'm being careful not to call it construction and object since the implementation is not oop, but pure C code).
A working hack is to write to file that you cannot write to (please note that you can write to non-existent file in an existing directory - it would be created). There are few ways, some os-dependent:
write to a file in non-existing directory. While it is complicated in a generic case, you can use some tricks like using chars unlikely to meet in a filename, like '\x01'.
const char* testFile = "non-existent\x01dir/missLogFile.log";
write to a file you have no rights to write to. In UNIX you can issue
chmod a-w file.log
command on an existing file to revoke write permission.
write to a system read-only pseudo-file.
const char* testFile = "/proc/uptime"; // linux
const char* testFile = "CLOCK$"; // windows / dos
I believe unit-tests should never access OS, and your test becomes non-unit this way, but this is a terminology question and a holy war subject.
Update:
Your comment actually makes it a poorly asked but pretty interesting question. I think you can edit it and I will try to answer. As things go hacky here, I'll focus on Linux only, answering the question
"How to make file open-for-write succeed, but subsequent write fail?"
Probably the most common error real application face is "No space left on device". This is easy to reproduce in hermetic way: let us create a fat16 filesystem in local file, precisely:
$ dd if=/dev/urandom of=test_disk bs=1048576 count=1
$ mkdosfs test_disk
$ mkdir /tmp/mnt
$ sudo mount -o loop,rw,umask=000 test_disk /tmp/mnt/
Now fill the filesystem. Alternatively we could use smaller size.
$ perl -e 'print "a"x(1024*1002)' > /tmp/mnt/a.txt
$ echo test > /tmp/mnt/test || echo "can't write test file"
And finally hit the error:
$ echo `perl -e 'print "a"x4096'` > /tmp/mnt/test || echo "test succeeded"
bash: echo: write error: No space left on device
test succeeded
To be precise the error is encountered writing byte 1009:
$ ls -l /tmp/mnt/
total 1004
-rwxrwxrwx 1 root root 1026048 Mar 27 17:56 a.txt
-rwxrwxrwx 1 root root 1009 Mar 27 17:57 test
A nice side effect of FAT filesystem is that now you are free to open more files there and write will fail from byte 0, as you asked.

Why doesn't ls -al show message queue created by mq_open [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I use mq_open to create message queue /temp.1234,
but command ls -al and ipcs -qin directory / doesn't show any information about the message queue.
I use mq_send to send a message. Also, in another program, mq_open("/temp.1234", O_WRONLY) returns 3(message descriptor) succesfully, but when calling mq_receive, it outputs EBADF. OS is ubuntu.
Is it only effective on solaris rather than ubuntu?
Added:
it's from unix network programing volume 2.
Here is the output under Solaris 2.6:
solaris % mqcreatel /temp.l234
solaris % 1s -1 /tmp/.*l234
-rw-rw-rw- 1 rstevens otherl 132632 Oct 23 17:08 /tmp/.MQDtemp.1234
-rw-rw-rw- 1 rstevens other1
0 Oct 23 17:08 /tmp/.MQLtemp.l234
-rw-r--r--
1 rstevens other1
0 Oct 23 17:08 /tmp/.MQPtemp.l234
The first argument is not a filename, it is an identifier only. It will not exist on the filesystem.
Attempting to receive from a write-only queue is an error.

How to fix btrfs root inode errors [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 5 years ago.
Improve this question
Running btrfsck, or more officially, btrfs check --repair gives this output stating that there are root inode errors. The repair command does not fix the issue and reruns will display the same output. The system is fully mountable and operational, but I cannot perform advanced operations on the partition (resizing).
sudo btrfs check --repair /dev/sda9
enabling repair mode
Checking filesystem on /dev/sda9
UUID: 82fca3c2-703b-4fae-aec2-6b7df1be71c1
checking extents
Fixed 0 roots.
checking free space cache
cache and super generation don't match, space cache will be invalidated
checking fs roots
root 257 inode 452001 errors 400, nbytes wrong
root 257 inode 452004 errors 400, nbytes wrong
root 257 inode 452005 errors 400, nbytes wrong
root 257 inode 452006 errors 400, nbytes wrong
root 257 inode 452010 errors 400, nbytes wrong
root 257 inode 452011 errors 400, nbytes wrong
root 257 inode 452012 errors 400, nbytes wrong
root 257 inode 1666032 errors 400, nbytes wrong
checking csums
checking root refs
found 33957216263 bytes used err is 0
total csum bytes: 32206988
total tree bytes: 968933376
total fs tree bytes: 886636544
total extent tree bytes: 35323904
btree space waste bytes: 199109273
file data blocks allocated: 41090113536
referenced 32584159232
btrfs-progs v4.0.1
Provided that the broken inodes are the only problem present, the solution is to simply remove them. There may be a quicker way to do this, but here is what worked for me. From here I gleaned that you can use the find command to search for an inode like so:
find / -inum XXXXXX -print
of course giving it the inode in question from the btrfsck command. It will show you the offending file and you can delete it. When all have been removed, btrfsck will be clear and the system will function normally.

Resources