System command failing on Linux C++ - c++

In my program I am copying an executable file from one location to another, and then execute the copied file. When the copied file is executed I get a "permission denied" error. But if I restart my program then the file gets executed without a problem. Can someone please help me with the problem? The code below is simple, but demonstrates the problem.
void copyFile(string _from, string _to)
{
std::ifstream src(_from.c_str());
std::ofstream dst(_to.c_str());
dst << src.rdbuf();
}
int main()
{
string original("./exe_file");
string dest_file("./exe_dir/exefile");
system("./exe_dir/exefile"); //Fails on first run because exe_dir does not exist.
//mkdir and copy the file.
mkdir("./exe_dir",S_IRWXO | S_IRWXU | S_IRWXG);
copyFile(original, dest_file);
//Open the file and close it again to flush the attribute cache.
int fd = open(dest_file.c_str(),O_RDONLY);
close(fd);
//The line below fails with system error code 2 (Permission denied) on exefile.
return system("./exe_dir/exefile");
{
I used 'chmod 777 exe_file' on the original file before executing the program, and after running this program the destination also has the same access rights. I can execute it manually just fine. And every subsequent run of the program is successful. Why does it fail on the first run?

You should close file you've created.
See cplusplus.com: std::ifstream::close

Coderz, no idea what problems you are experiencing with your IDE but this works fine for me.
#include <iostream>
#include <fstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cstdlib>
using namespace std;
void copyFile(string _from, string _to)
{
std::ifstream src(_from.c_str());
std::ofstream dst(_to.c_str());
dst << src.rdbuf();
}
int main()
{
string original("./exe_file");
string dest_file("./exe_dir/exefile");
system("./exe_dir/exefile");
if (mkdir("./exe_dir", S_IRWXO | S_IRWXU | S_IRWXG))
perror("mkdir");
copyFile(original, dest_file);
if (chmod("./exe_dir/exefile", S_IRWXU | S_IRWXG | S_IRWXO) == -1)
perror("chmod");
return system("./exe_dir/exefile");
}
Note that exe_file is a simple Hello World binary and the results are
sh: 1: ./exe_dir/exefile: not found
Hello World
where the copied file is
-rwxrwxrwx 1 duck duck 18969 May 9 19:51 exefile
within directory
drwxrwxr-x 2 duck duck 4096 May 9 19:51 exe_dir

Related

Cannot write an array in a Ubuntu device using C++ (Debug Assertion Failed. Expression (stream !=NULL))

I am working on Windows and I am trying to write an array into a Ubuntu device using C++ in Visual Studio 2019. Here's a sample of my code:
int Run_WriteCalibTable(char *pcIPAddress, int iNumArgs, float *fArgs, int *iAnsSize, char *sAns)
...
...
...
char pcFolderName[256];
char pcFileName[256];
sprintf(pcFolderName, "%s\\%s",pcSavePath, pcUUTSerialNumber);
sprintf(pcFileName, "%s\\calib_rfclock.conf",pcFolderName);
// WRITE TABLE ON PC
FILE *pFileW;
pFileW = fopen(pcFileName,"wb");
fwrite(&CalibTable, sizeof(char), CalibTable.hdr.v1.u32Len, pFileW);
fclose(pFileW);
}
return 0;
However, I keep having this pop-up from Microsoft Visual C++ Debug Library that says:
Debug Assertion Failed:
Program:...
File: f:\dd\vctools\crt_bld\sefl_x86\crt\src\fwrite.c
Line: 77
Expression: (stream != NULL)
...
I found this thread and I tried logging in as root on my Ubuntu device. I also tried:
mount -o remount,rw /path/to/parent/directory
chmod 777 /path/to/parent/directory
And I can also create/edit manualy any file in the directory I'm trying to write into with my code, but I get the same error when running it.
Anyone knows what could cause this? I think it could be on the Windows side, but I don't know what I am doing wrong. Thanks a lot in advance.
You never check that opening the file succeeds - and it most likely fails, which is why you get the debug pop-up. Your use of \ as directory delimiters may be the only reason why it fails, but you should check to be sure.
I suggest that you use std::filesystem::path (C++17) to build your paths. That makes it easy to create paths in a portable way. You could also make use of a C++ standard std::ofstream to create the file. That way you don't need to close it afterwards. It closes automatically when it goes out of scope.
Example:
#include <cerrno>
#include <cstring>
#include <filesystem>
#include <fstream>
int Run_WriteCalibTable(char *pcIPAddress, int iNumArgs, float *fArgs,
int *iAnsSize, char *sAns)
{
...
// Build std::filesystem::paths:
auto pcFolderName = std::filesystem::path(pcSavePath) / pcUUTSerialNumber;
auto pcFileName = pcFolderName / "calib_rfclock.conf";
// only try to write to the file if opening the file succeeds:
if(std::ofstream pFileW(pcFileName, std::ios::binary); pFileW) {
// Successfully opened the file, now write to it:
pFileW.write(reinterpret_cast<const char*>(&CalibTable),
CalibTable.hdr.v1.u32Len);
} else {
// Opening the file failed, print the reason:
std::cerr << pcFileName << ": " << std::strerror(errno) << std::endl;
}
...
}

Geting the file size of a system application on windows in C++

I am trying to get the file size of a system application on windows. To test this i have created a test application that tries to get the file size of smss.exe in C:\Windows\System32\smss.exe but it fails with error: ERROR_FILE_NOT_FOUND. The file does actually exist (i have checked). I've also tried different methods for getting the file size, with: FindFirstFile, CreateFile and GetFileSizeEx. But all return the same error. I would also like to read the file contents.
What am i doing wrong?
The code:
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>
__int64 getFileSize(LPWSTR filePath)
{
WIN32_FILE_ATTRIBUTE_DATA fad;
if (!GetFileAttributesEx(filePath, GetFileExInfoStandard, &fad))
{
_tprintf(TEXT("\n CAnt get file size for file %s error %d"), filePath, GetLastError());
return 0;
}
LARGE_INTEGER size;
size.HighPart = fad.nFileSizeHigh;
size.LowPart = fad.nFileSizeLow;
return size.QuadPart;
}
int _tmain(int argc, _TCHAR* argv[])
{
_tprintf(TEXT("File size %d "), getFileSize(L"C:\\Windows\\System32\\smss.exe"));
}
As your application is 32-bit, the system redirects your path to go to SysWOW64 instead, where there is no smss.exe. While you have discovered that Wow64DisableWow64FsRedirection disables this redirection, also consider that having a 64-bit program would also do the trick.
Getting the size of a file is already answered here (can't yet add a comment to your question, so I need to write it as an answer):
How can I get a file's size in C++?
std::ifstream::pos_type filesize(const char* filename)
{
std::ifstream in(filename, std::ifstream::in | std::ifstream::binary);
in.seekg(0, std::ifstream::end);
return in.tellg();
}

Why does O_CREAT create files only accessible by administrators?

I have the following simple program:
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <string>
using namespace std;
int main() {
string data { "The quick brown fox jumps over the lazy dog" };
int file_descriptor = open("some_file.txt", O_CREAT | O_WRONLY);
write(file_descriptor, data.c_str(), data.size());
cout << file_descriptor << endl;
return 0;
}
which for the most part works fine - the data is outputted into the file. But per http://linux.die.net/man/2/open , the O_CREAT flag should set the file owner to the effective user ID of the process. I'm compiling/running my application from the terminal, but not with any sort of privileges, so why is the created file only visible to administrators?
Random mischance. When you use O_CREAT, open() is a 3-argument function, which takes the file mode as the third argument.
You should be using:
int fd = open("some_file.txt", O_CREATE | O_WRONLY, 0444);
This will create a file with no write permission for anybody (but which your process will be able to write to).
See <sys/stat.h> for more information about the POSIX symbolic constants to use in place of 0444.

Redirection in Linux with dup2() and create() inside a loop

I am running the code below and I cannot redirect to a file. The file is made, but nothing is put into it. If I remove the last dup2(saveout,1) statement, I can create and write into the file, but I cannot get back to the terminal, which is important. As soon as I put the dup2(saveout,1) back in my code, the redirection stops working, but I can get back to the terminal. I do not understand why this is happening. I would like to redirect and go back into the terminal.
main.cpp
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
using namespace std;
void printmessage() {
printf("this is the message\n");
}
int main(int argc, char** argv) {
int saveout;
int fd;
saveout = dup(1);
for (int i = 0; i < 10; i++) {
fd = creat("/home/carl/example.txt",O_CREAT|O_APPEND);
dup2(fd, 1);
close(fd);
printf("Testing the message");
printmessage();
dup2(saveout,1);
close(saveout);
}
return 0;
}
This is a file rights issue, you should read the man pages of the functions you are using.
creat() takes as first argument the filename, and as second the file creation rights, not its opening mode.
The creat() functions is a simple open() call, with some particular flags, so that you'll just have to set up the rights.
if you want to open your file, and create it if he doesn't exists, use
open(filename, O_CREAT | O_RDWR | O_APPEND, 0600) for example, or
creat(filename, 0600),
which is mostly its equivalent, but you wont be able to append text, as "creat() is equivalent to open() with flags equal to O_CREAT | O_WRONLY | O_TRUNC"
The second dup2(saveout,1); will fail because you closed saveout.
printf is buffered by default. (line-by-line for output to a tty, perhaps differently for output to something else). Before both your calls to dup2(..., 1), you should flush with fflush:
fflush(stdout);

Cannot access file in Network Attached Storage (NAS) by using C++ access() function?

I have an Isilon NAS in 10.20.30.11 for example, and I mounted it like following:
mount 10.20.30.11:/folder /content
I could use ls command to find the file in folder or /content. Its mod is 777.
bash-3.00# ls -l /content/a/b/1.txt
total 344131
rwxrwxrwx 1 1005 65533 140750 Feb 28 00:58 1.txt
But I cannot access it by access() function.
#include <iostream>
#include <string>
#include <unistd.h>
#include <cerrno>
using namespace std;
#include <stdio.h>
int main( int argc, const char* argv[] )
{
int returnVal = 0;
returnVal = access(argv[1], R_OK);
cout << returnVal << endl;
cout << errno << endl;
return 0;
}
It will return -1 and 2 as a result, which means 'No such file or directory'.
./a.out /content/a/b/1.txt
-1
2
#define ENOENT 2 /* No such file or directory */
It is not a permission problem I think, because the mod is 777, and the result is 'No such file or directory'.
From the Linux man pages.
access() may not work correctly on NFS
file systems with UID mapping enabled,
because UID mapping is done on the
server and hidden from the client,
which checks permissions.
Finally, it is found that it need to use following command to mount the Isilon storage.
mount -o vers=2,proto=tcp
1.2.3.4:/remote /mnt
The version and protocol need specified.
Thanks!