Open() syscall filedesriptor - c++

I have to correct the return value of the open() syscall of a posix OS. I understood from the man-Pages that it has to return the file descriptor, and , in case of an error the system call will return -1 and set the errno value. The problem is that I do not know how to get the file descriptor for the opened nod. I checked all the files and didn't found a method that can assign a fd to processes.
Here is the method :
int syscalls::open(const char *path, int oflags, mode_t mode){
syscall_message msg;
msg.call.type = syscalls::open_call;
msg.open_data.path_name = &path[0];
msg.open_data.flags = oflags;
msg.open_data.create_mode = mode;
syscaller::call_system(msg);
return msg.error.number;
}
syscall_message is a struct that holds the data info for the system call. syscalls is the namesapace where all the system calls are. syscaller is used to send the call to the kernel, unsing the call_system method.
The call_system method:
syscalls::open_call:
{
//get the file
i_fs_node_ptr file = i_fs::open_node( msg.open_data.path_name );
//add the file handle
if ( file )
{
cur_process->push_filehandle(
file,
msg.open_data.flags,
msg.open_data.create_mode );
}
else
{
msg.error.type = syscalls::e_no_such_entry;
}
}

I don't know what you mean by "I can't get the file descriptor". As you have mentioned open() returns it. It's simply stored in an integer variable. If this variable is equal to -1, then something has gone wrong. For example if you have
int file = open(path, O_SYNC, O_DIRECT, O_RDONLY);
but you do not have the reading permissions for the file named path the variable file will get a value of -1. Additional manipulation on an opened file can be done via read() (if file was opened in read mode) and write() (if file was opened in write mode). I suggest you read the documentation on the open() function more carefully. If you need more control over the file descriptor I suggest you use fopen():
Discussion on the difference between open() and fopen()
Tutorial on fopen()
Documentation on fopen()

Related

fopen / ofstream::open fail when creating a BMP file

Years ago I created a C++ function using FILE to create bitmap files. Recently (not sure when or why) this code is now failing when opening the file. The problem is with the open call ...
file_ptr = fopen("ScreenShots/Screenshot1.bmp", "wb");
Currently this results in an error 13, permission denied error. Change the filename extension to something else and the fopen works fine. For example,
file_ptr = fopen("ScreenShots/Screenshot1.bm2", "wb");
The file saves correctly and when changing the extension back to BMP I can display the file correctly in Paintshop.
Did a quick check using ofstream and same problem.
Any ideas why I get a permission denied error when trying to open BMP files to write data? For information I am using Visual Studio Community 2017 on Windows 10.
To give the complete section of code ...
BITMAPFILEHEADER bitmap_header;
BITMAPINFOHEADER bitmap_info;
FILE *file_ptr;
unsigned int count;
unsigned char tempRGB;
char filename[256];
bool finished;
// CREATE A UNIQUE FILENAME
count = 1;
finished = false;
do
{
// CREATE NAME
sprintf(filename, "ScreenShots/Screenshot%d.bmp", count);
// CHECK IF FILE EXISTS
errno = 0;
file_ptr = fopen(filename, "rb");
if (file_ptr)
{
// FILE EXISTS
fclose(file_ptr);
count = count + 1;
}
else
{
// UNIQUE FILENAME
file_ptr = fopen(filename, "wb");
if (file_ptr == NULL)
{
// UNABLE TO OPEN FOR WRITING - GIVE UP
// (USING OWN LOGGING CLASS)
jalog.log("\nERROR on Screenshot >");
jalog.log(filename);
jalog.log("< >");
jalog.log((short)errno);
return;
}
finished = true;
}
}
while (finished == false);
I've managed to find the issue ... Avast antivirus. I noticed that trying to do an open action for a BMP file took a few seconds while opening any other file type (successfully or unsuccessfully) was instantaneous. As something similar happens when running new programs I tried disabling all the Avast shields and I could successfully create a BMP file using the existing code.
For my own personal use I can whitelist my own programs, but annoying if I get to distributing the program to other people.
Thanks for the help ... and sorry for raising a C++ issue that in the end had nothing to do with C++!

C++ redirect or disable stdio temporarily

In our C++ project under MacOS X, we are using stdio for interaction with clients. Yet, the dylib we are using is also using stdio to print "open log files". This breaks down all communication between our clients and the application. I looked at the examples of redirecting stdio to a file or temporarily disabling stdio. Yet, we could not succeed in it.
So, how can we disable or redirect stdio temporarily while interacting with the dylib.
void RedirectStandardStreamsToDEVNULL(int *_piOriginalSTDIN_FILENO, int *_piOriginalSTDOUT_FILENO, int *_piOriginalSTDERR_FILENO)
{
//flushing pending things before redirection.
//fflush(stdin);
fflush(stdout);
fflush(stderr);
*_piOriginalSTDIN_FILENO = dup(STDIN_FILENO);
*_piOriginalSTDOUT_FILENO = dup(STDOUT_FILENO);
*_piOriginalSTDERR_FILENO = dup(STDERR_FILENO);
int devnull = open("/dev/null", O_RDWR);
dup2(devnull, STDIN_FILENO);
dup2(devnull, STDOUT_FILENO);
dup2(devnull, STDERR_FILENO);
close(devnull);
}
void RestoreStandardStreams(int *_piOriginalSTDIN_FILENO, int *_piOriginalSTDOUT_FILENO, int *_piOriginalSTDERR_FILENO)
{
//flushing pending things before restoring.
//fflush(stdin);
fflush(stdout);
fflush(stderr);
dup2(*_piOriginalSTDIN_FILENO, STDIN_FILENO);
dup2(*_piOriginalSTDOUT_FILENO, STDOUT_FILENO);
dup2(*_piOriginalSTDERR_FILENO, STDERR_FILENO);
}
void myfunction()
{
int iOriginalSTDIN_FILENO = -1;
int iOriginalSTDOUT_FILENO = -1;
int iOriginalSTDERR_FILENO = -1;
RedirectStandardStreamsToDEVNULL(&iOriginalSTDIN_FILENO, &iOriginalSTDOUT_FILENO, &iOriginalSTDERR_FILENO);
//all of your code which prints to stdout or stderr will be directed to /dev/null
RestoreStandardStreams(&iOriginalSTDIN_FILENO, &iOriginalSTDOUT_FILENO, &iOriginalSTDERR_FILENO);
}
Important point is to identify the functions which are called inside dylib from your code. Now, surround such functions with Redirect and Restore functions described above.
OSX is a POSIX systems, and like all POSIX systems standard output is file descriptor STDOUT_FILENO (which is a macro defined as 1).
What you can do is duplicate STDOUT_FILENO to another file descriptor, open a temporary file and duplicating (using dup2) the temporary file as STDOUT_FILENO. Then whenever there is output to standard out (using plain write, C printf or C++ std::cout) it will be put in the temporary file.
When done with the temporary "redirection" you simply duplicate the saved standard output (from the first dup call) back into STDOUT_FILENO. and close and remove the temporary file.
Something like the following:
int saved_stdout = dup(STDOUT_FILENO);
int temp_file = open("/tmp/temp_stdout", O_WRONLY, 0600);
dup2(temp_file, STDOUT_FILENO); // Replace standard out
// Code here to write to standard output
// It should all end up in the file /tmp/temp_stdout
dup2(saved_stdout, STDOUT_FILENO); // Restore old standard out
close(temp_file)
unlink("/tmp/temp_stdout"); // Remove file

Read lines from a file opened with CreateFile [duplicate]

In Unix, if you have a file descriptor (e.g. from a socket, pipe, or inherited from your parent process), you can open a buffered I/O FILE* stream on it with fdopen(3).
Is there an equivalent on Windows for HANDLEs? If you have a HANDLE that was inherited from your parent process (different from stdin, stdout, or stderr) or a pipe from CreatePipe, is it possible to get a buffered FILE* stream from it? MSDN does document _fdopen, but that works with integer file descriptors returned by _open, not generic HANDLEs.
Unfortunately, HANDLEs are completely different beasts from FILE*s and file descriptors. The CRT ultimately handles files in terms of HANDLEs and associates those HANDLEs to a file descriptor. Those file descriptors in turn backs the structure pointer by FILE*.
Fortunately, there is a section on this MSDN page that describes functions that "provide a way to change the representation of the file between a FILE structure, a file descriptor, and a Win32 file handle":
_fdopen, _wfdopen: Associates a stream with a file that was
previously opened for low-level I/O and returns a pointer to the open
stream.
_fileno: Gets the file descriptor associated with a stream.
_get_osfhandle: Return operating-system file handle associated
with existing C run-time file descriptor
_open_osfhandle: Associates C run-time file descriptor with an
existing operating-system file handle.
Looks like what you need is _open_osfhandle followed by _fdopen to obtain a FILE* from a HANDLE.
Here's an example involving HANDLEs obtained from CreateFile(). When I tested it, it shows the first 255 characters of the file "test.txt" and appends " --- Hello World! --- " at the end of the file:
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include <cstdio>
int main()
{
HANDLE h = CreateFile("test.txt", GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if(h != INVALID_HANDLE_VALUE)
{
int fd = _open_osfhandle((intptr_t)h, _O_APPEND | _O_RDONLY);
if(fd != -1)
{
FILE* f = _fdopen(fd, "a+");
if(f != 0)
{
char rbuffer[256];
memset(rbuffer, 0, 256);
fread(rbuffer, 1, 255, f);
printf("read: %s\n", rbuffer);
fseek(f, 0, SEEK_CUR); // Switch from read to write
const char* wbuffer = " --- Hello World! --- \n";
fwrite(wbuffer, 1, strlen(wbuffer), f);
fclose(f); // Also calls _close()
}
else
{
_close(fd); // Also calls CloseHandle()
}
}
else
{
CloseHandle(h);
}
}
}
This should work for pipes as well.
Here is a more elegant way of doing this instead of CreateFile: specify "N" in fopen(). It's a Microsoft-specific extension to fopen, but since this code is platform-specific anyway, it's ok. When called with "N", fopen adds _O_NOINHERIT flag when calling _open internally.
Based on this:
Windows C Run-Time _close(fd) not closing file

how to get linux command output string and output status in c++

I want to get a Linux command's output string as well as command output status in a C++ program. I am executing Linux commands in my application.
for example:
Command:
rmdir abcd
Command output string:
rmdir: failed to remove `abcd': No such file or directory
Command Status:
1 (Which means command has been failed)
I tried using Linux function system() which gives the output status, and function popen() which gives me output string of a command, but neither function gives me both
the output string and output status of a Linux command.
The output string is in standard output or standard error descriptor (1 or 2, respectively).
You have to redirect these streams (take a look at dup and dup2 function) to a place, where you can read them (for example - a POSIX pipe).
In C I'd do something like this:
int pd[2];
int retValue;
char buffer[MAXBUF] = {0};
pipe(pd);
dup2(pd[1],1);
retValue = system("your command");
read(pd[0], buffer, MAXBUF);
Now, you have (a part of) your output in buffer and the return code in retValue.
Alternatively, you can use a function from exec (i.e. execve) and get the return value with wait or waitpid.
Update: this will redirect only standard output. To redirect standard error, use dup2(pd[1],1).
The simplest solution is to use system, and to redirect standard out and standard error to a temporarly file, which you can delete later.
Unfortunately there's no easy and simple way in C on Linux to do this. Here's an example how to read/write stdout/stderr/stdin of child process correctly.
And when you want to receive exit code you have to use waitpid (complete example is provided on the bottom of the provided page):
endID = waitpid(childID, &status, WNOHANG|WUNTRACED);
Now you just have to join those two together :)
There's also a great free book named Advanced Linux Programming (ALP) containing detailed information about these kinds of problem available here.
Building on Piotr Zierhoffer answer above, here's a function that does just that, and also restores stdout and stderr their original state.
// Execute command <cmd>, put its output (stdout and stderr) in <output>,
// and return its status
int exec_command(string& cmd, string& output) {
// Save original stdout and stderr to enable restoring
int org_stdout = dup(1);
int org_stderr = dup(2);
int pd[2];
pipe(pd);
// Make the read-end of the pipe non blocking, so if the command being
// executed has no output the read() call won't get stuck
int flags = fcntl(pd[0], F_GETFL);
flags |= O_NONBLOCK;
if(fcntl(pd[0], F_SETFL, flags) == -1) {
throw string("fcntl() failed");
}
// Redirect stdout and stderr to the write-end of the pipe
dup2(pd[1], 1);
dup2(pd[1], 2);
int status = system(cmd.c_str());
int buf_size = 1000;
char buf[buf_size];
// Read from read-end of the pipe
long num_bytes = read(pd[0], buf, buf_size);
if(num_bytes > 0) {
output.clear();
output.append(buf, num_bytes);
}
// Restore stdout and stderr and release the org* descriptors
dup2(org_stdout, 1);
dup2(org_stderr, 2);
close(org_stdout);
close(org_stderr);
return status;
}
you can use popen system call, it will redirect output to a file and from file you can redirect output to a string. like :
char buffer[MAXBUF] = {0};
FILE *fd = popen("openssl version -v", "r");
if (NULL == fd)
{
printf("Error in popen");
return;
}
fread(buffer, MAXBUF, 1, fd);
printf("%s",buffer);
pclose(fd);
For more information read man page for popen.

Using open and i2c in C++

I've realized that open() and ioctl() does not work inside a cpp object. I am able to do the operation if it is called inside my main() function, but NOT when inside any of my classes. I have a object that is running in my main loop that has another object that makes the file system calls.
So basically when in the main loop it can open (I get a 3 for the pointer and the ioctl is successful). But when I do it in object it returns 0 for open (which isn't supposedly an error) and the ioctl fails.
I know I can't use the ios:: iostream options because they don't work with ioctl. How can I make regular ioctl work inside a cpp object?
int add=0x4b;
int i2c_bus;
if(( i2c_bus = open( "/dev/i2c-0", O_RDWR )) < 0 )
{
printf("Unable to open file /dev/i2c-0.\n");
}
if( ioctl( i2c_bus, I2C_SLAVE, add ) < 0 )
{
printf("Open chip %d FAILED file %d\n",add, i2c_bus);
return -1;
}
else
{
printf("Open chip %d Succeeded file %d\n\n",add, i2c_bus);
return 1;
}
You've assigned the result of open to i2c_bus, but you're using fd in the ioctl. Did you change the variable names when you moved from main?