Does QFile::copy keep the source file permissions in the copied file? - c++

I am trying to copy a game from a disk or USB flash drive to hard drive in my computer using Qt and I wanted to use QFile::copy and it is important for me to keep the permissions like being executable and writable.
Do I have to use QFile::setPermissions or the permissions are not changed by default in the copy function call?

QFile::copy preserves the file permissions, as evidenced by the source code:
if(!error) {
QFile::setPermissions(newName, permissions());
close();
unsetError();
return true;
}
QFile::setPermissions(newName, permissions()); actually copies the permissions from the current file to the file named newName. Hence, there is no need to do that manually.

Related

How to rename a file from ext4 file system to ntfs file system in C++

Have a query. I am always using the code in C++ (below) to move a file from one location to another in same drive (call it A drive)
rename(const char* old_filename, const char* new_filename);
Recently I need to amend the code to move it to another drive (call in B-Drive). It doesn't work but I could write code to write into that particular drive (B-drive). On investigation, I found that the drive (A-drive) on which I produce the result(the old file) is in ext4 file system but the drive i am writing/moving to is in NTFS (fuseblk)
How can i amend my code to move the file to NTFS. I am using C++ in ubuntu
Regards
--------------------------------------------------------------------
New Edit after heeding call from user4581301
This is the code I have written
int main()
{
std::string dirinADrive = "/home/akaa/data/test3/test_from.txt"; // this is the parent directory
std::string dirinBDrive = "/media/akaa/Data/GIRO_repo/working/data/test5/test_to.txt"; // this is where i want to write to
std::string dirinCDrive = "/home/akaa/data/test3/test_to.txt"; // this is where i want to write to
std::string dirinDDrive = "/media/akaa/Data/GIRO_repo/working/data/test5/test_to_write.txt";
bool ok1{std::ofstream(dirinADrive).put('a')}; // create and write to file
bool ok2{std::ofstream(dirinDDrive).put('b')}; // create and write to file
if (!(ok1 && ok2))
{
std::perror("Error creating from.txt");
return 1;
}
if (std::rename(dirinADrive.c_str(), dirinCDrive.c_str())) // moving file to same drive
{
std::perror("Error renaming local");
return 1;
}
if (std::rename(dirinADrive.c_str(), dirinBDrive.c_str())) // moving file to other drive
{
std::perror("Error renaming other");
return 1;
}
std::cout << std::ifstream(dirinBDrive).rdbuf() << '\n'; // print file
}
And I have gotten an error
Error renaming other: Invalid cross-device link
So what is invalid cross-device link??
Thanks
You can’t use rename across filesystems, because the data must be copied (and having a single system call do an arbitrary amount of work is problematic even without atomicity issues). You really do have to open the source file and destination file and write the contents of one to the other. Apply whatever attributes you want to preserve (e.g., with stat and chmod), then delete the source file if you want.
In C++17, much of this has been packaged as std::filesystem::copy_file. (There is also std::filesystem::rename, but it’s no better than std::rename for this case.)

How to convert Qt file path from resource to absolute path?

I need to receive the absolute file path like
C:/Users/Dima/YandexDisk/_Application/WeldAnalysis/ExperimentDefaults.xlsx
from path of QRC file like
:/Data/ExperimentDefaults.xlsx.
How can I do this?
Resources are packed all together into the QRC file, they are not exposed to the filesystem, thus they cannot be converted to a standard path; it is like accessing a file inside a zip file.
What are you willing to do with such file path? QFile can deal with resource paths (":/...") and open such files, but other file handling APIs don't (such as C's fopen or C++'s std::ifstream). Also, and for the same reason, non-Qt application won't be able to open such files if passed as a parameter.
Options you have include:
opening the file using QFile and read it using related Qt classes (given you are dealing with an Excel file I think it doesn't worth the effort, unless you have some library to read it from a memory buffer).
copying the file out of the resources container to a temporary directory (you can use QTemporaryDir to create one), and use the file from there:
QTemporaryDir tempDir;
if (tempDir.isValid()) {
const QString tempFile = tempDir.path() + "/yourfile.xlsx";
if (QFile::copy(":/yourfile.xlsx", tempFile)) {
// your file is now extracted to the filesystem
}
}
Only be aware that when tempDir is destroyed, the temporary directory is also deleted, therefore your file. You can avoid this by disabling the auto-remove feature: tempDir.setAutoRemove(false) and manually deleting the temporary directory when you finish with the extracted file.

copying binary files to remote location in C++

I'm in the process of trying to copy an hdf5 binary file on a local machine to a remote computing blade. I am using libssh to copy the desired directory or files out after they are generated by my Qt application. Using libssh I am able to open an ssh_session, authenticate it, open a channel and send remote commands.
for (QStringList::iterator it = ipList.begin(); it != ipList.end(); ++it)
{
ssh_session my_session = new ssh_new();
QString ip_address = *it;
ssh_options_set(my_session, SSH_OPTIONS_HOST, ip_address.toStdString().c_str());
// Connect...Authenticate using public key....
QString command = QString("rm -r %2; cp -r %1 %1; cp /local/file.txt /remote/file.txt").arg(local_dir, remote_dir);
execute_remote_command(my_session, command.toStdString().c_str());
// Open channel and execute command
ssh_disconnect(my_session);
ssh_free(my_session);
}
This command is being executed for each individual computing blade. In between each of the calls I am closing and opening an ssh session to the next blade. The files make it out the blades but they appear to be corrupt. They are the exact same file size. I haven't figured out a way to compare the individual bytes to see just how corrupt they are, any tips there would be appreciated as well.
When I run my ssh copy commands in a separate test terminal program the files appear to make it intact and are readable on the blades. The issue only seems to occur when the files are moved from within the Qt GUI program.
EDIT: So delving a little bit deeper into what is wrong, it appears that the file on the remote server is not the same size. It appears to be missing a large portion of the bytes. On top of that when I examine what is there byte by byte with the local version of the file, almost all of the bytes differ.
Turns out the answer was that the HDF5 writer wasn't being closed properly before the SSH commands were being called. I fixed the problem by dynamically allocating the custom H5 class that someone else wrote and made sure to delete it before the SSH commands were called. Turns out whoever wrote the HDF5 read and write class didn't handle file opening and closing properly and didn't provide functions to do so.
Below is an example of what I am talking about.
HDF5writer_class *hdf5_writer = new HDF5writer_class();
hdf5_writer->create_file("/local/machine/hdf5_file.h5");
// ... add the data to the file
delete hdf5_writer;
// Open SSH Session and run the copy commands
Long story short, make sure the file you are writing is closed and released for use before you try to copy it.

ofstream not creating file (Node.js addon)

I am attempting to create an addon for Node.js that (among other things) writes content to a file inside my C++ class using ofstream.
std::ofstream license_file;
std::string fileContent(*NanAsciiString(args[0]));
license_file.open(PATH);
//file doesn't yet exist, so create it
if(!license_file) {
printf("ERROR: %s (%s)\n", strerror(errno), PATH);
}
license_file << fileContent;
license_file.close();
This works fine if PATH is set to the same directory as my Node.js code (e.g. ./license.txt).
However, ofstream fails to open/create the file in question if it is located anywhere else. For example, using ~/license.txt does not work (note: I'm running OSX).
The error reported is always No such file or directory -- even after I physically create ~/license.txt.
Any ideas why this works in one directory but not others? If it were a permissions issue I would expect a different error message.
For the record, I've seen about 20 other SO questions about "ofstream fails to create file" but passing additional flags into open() has no effect. I have a feeling this is somehow related to running inside Node/V8.
I think the issue is that you need to find out the user directory in a different way than using ~.

Recovering Files on Windows and C

Well this time I'm trying to write a program in C which recover deleted files from a disk, it could be an external disk, I have an idea than i had used before on linux, it is to open the disk as a kind of file and scaning the Headers and file footers of everything within the disk, the point is I'm not sure if there's allow on windows to open a disk as an File, basiclly I have the logic how to develope this program, but I'm not sure how to implement it on windows, anybody can give me a hand with this?.
The code I used on linux to open a disk as a file was:
Edit: That was a sample of what I was using guys, it's just to give you an idea of what I was doing, the correct syntax I used was the next:
direccion = ui->linea->text().toLatin1().constData();
f = fopen(direccion,"rb");
I used QT creator on linux, and direccion variable was a TextField value which contained the file path of the disk through a button function that open a QFileDialog...
could I use it in windows as well?
Thank you before hand..
"The code I used on linux to open a disk as a file was:"
File *f = fopen("E:\", "rb");
I seriously doubt you ever got this code working on any linux system (or windows either).
You'll need to escape the backslash path delimiter, if it's presented in any string literal:
FILE* f = fopen("E:\\", "rb");
// ^
Also all that filesystem path style you are presenting to access a particular disk, is about accessing a windows file path/disk.
No linux file system has notion about drive characters, and the file path delimiter value used is '/', not '\\'.
To recover deleted files, you can't use fopen or fstream::open because the file was deleted. Check the return value from the function or test the stream state.
The way to recover deleted files is:
Get the Master File Table as raw data.
Search for the record containing a string similar to the deleted
filename.
Change the entry in the Master File Table to "undeleted".
Write the Master File Table back to the drive.
The above usually requires platform specific API, which is different on Linux and Windows platforms.