Mount NTFS device in C++ on linux? - c++

I'm attempting to mount an external drive in my C++ application. I originally tried to use mount(2) but this fails:
int ret = mount(deviceName.c_str(), mountPoint.c_str(), fsType.c_str(), 0, NULL);
errno is 19, ENODEV (filesystem type not configured in kernel)
However, if I switch to using mount(8) it works fine:
std::string cmd = "mount -t " + fsType + " " + deviceName + " " + mountPoint;
int ret = system(cmd.c_str());
Does mount(2) have a different list of acceptable filesystem types? This is an ntfs device, so I was using ntfs-3g as the fstype. I checked /proc/filesystems and saw that this was not listed, so I tried fuseblk but that just changes the error to 22, EINVAL.
What is the correct way to mount NTFS devices using mount(2)?

mount.2 is just a kernel call. mount.8 is a complete external tool which is extended beyond what kernel does.
I think you may be looking for libmount which is a library implementing the whole mounting magic done by mount.8. Newer mount versions use it as well. It's provided in util-linux.

Have you tried running mount(8) using the strace command? It will print out the system calls made by the program, including mount(2). When I do such a mount, it spawns mount.ntfs (which is NTFS-3g) which then does a mount for fuseblk and then spins off into the background to support that mount point.
FUSE-based filesystems are handled differently because the user-space daemon must be started. Mounting with fuseblk doesn't provide enough information for the kernel to start the daemon (and the kernel doesn't even really have the information to start the daemon). For ntfs-3g, one would normally do something like ntfs-3g /dev/sda1 /mnt/windows (from the help). There isn't a programmatic way to tell the kernel to do this because it happens in user-space.

Related

C++ Win32 How to unlock a Bitlocker volume and assign a drive letter after?

I have the following problem: I am trying to unlock a Bitlocker volume (by using the unique drive ID) and assign a mount point after it's unlocked. The reason why I try to do this in the previous mentioned order is that if I assign a drive letter before it's unlocked the Windows Autorun will try to open it and will prompt an error message (ex: Cannot open F:\ because it's encrypted). I am using Win32 API to get the BitLocker volume ID and set the mount point. The unlocking part is done using a call to powershell from C++ program (using system(), WinExe(), CreateProcess(), etc).
The following sequence works (but has the drawback mentioned above): Find the Bitlocker volume ID -> Set mount point/volume letter for it -> Unlock using system + PS script with volume letter argument;
What I am trying to do is: Find Bitlocker volume ID -> Unlock using system + PS script with volume ID argument -> Set mount point/volume letter of unlocked volume.
The second method is not working: the volume is encrypted after the Set mount point function gives it a drive letter.
The only hint I have is that the PS script is not working from C++ program when using Volume ID as parameter (instead of drive letter).
Powershell script (with drive letter as parameter):
start powershell.exe -WindowStyle Hidden Set-ExecutionPolicy Unrestricted; Unlock-BitLocker -MountPoint "F:\" -RecoveryPassword ..........
Powershell script (with Volume ID as parameter, not working):
start powershell.exe -WindowStyle Hidden Set-ExecutionPolicy Unrestricted; Unlock-BitLocker -MountPoint "\\?\Volume{00000000-0000-0000-0000-000000000000}\" -RecoveryPassword ..........
C++ code snapshot (working version):
/* Code that identifies the VolumeID for the BitLocker volume */
SetVolumeMountPointW(L"F:\\", VolumeID); // this sets the mount point for the BitLocker volume
system(ps_script_drive_letter); // this does the unlocking thing; also works with WinExe; haven't tried CreateProcess but I think it works with that function also;
C++ code snapshot (not-working version):
/* Code that identifies the VolumeID...... */
system(ps_script_volume_id); // this doesn't seems to be working; in debug mode, after I execute this and assign a drive letter using Windows Drive Management the Bitlocker Volume is locked;
SetVolumeMountPointW(L"F:\\", VolumeID); // same as above
I also tested the Powershell command Unlock-BitLocker -MountPoint "\\?\Volume{00000000-0000-0000-0000-000000000000}\" -RecoveryPassword .......... and is working when executed from Powershell (but not from inside the C++ app). If I assign the mount point from Windows GUI it works ok (the bitlocker volume is unlocked). If i assign the mount point from C++ code, it get locked.
Hope we can find a workaround this problem (or what am I doing wrong in the code above).
Thanks :)

C++ system call to other C++ program not working when called on startup

I have a C++ program which is called at startup via a cronjob (in crontab):
#reboot sudo /home/pi/CAN/RCR_datalogging/logfileControl
Which does run logfileControl anytime the Pi is booted as it shows up in the list of running programs (ps -e). LogfileControl contains two system calls to C++ programs related to SocketCAN (SocketCAN is part of the Linux Kernel, it allows for dealing with CAN data as network sockets). I want logfileControl to run on startup so that it can initialize the CAN socket (system call 1) and then start the first logfile (systemcall 2, candumpExternal, this is candump from socketCAN with a minor modification to make the logfile a specific location rather than just where candump is, but using the original version had the same issue). The first systemcall seems to be working properly as if I try and initialize the socket again it is busy, but the second systemcall doesn't appear to be happening as a logfile is not created at all as a logfile is not created. If I manually run logfileControl from the command line it works as expected and creates the logfile which has left me quite confused...
Does anyone have an insight as to what is going on here?
system("sudo /sbin/ip link set can0 up type can bitrate 500000");
// This is ran initially as logging should start as soon as the pi is on
system("/home/pi/CAN/RCR_datalogging/candumpExternal can0 -l -s 0"); // candump with the option to log(-l) as well as
// continue to output to console (-s 0)
std::cout <<"Setup Complete" << std:: endl;
while(true) { //sleeping indefinitely so that the program can stay open and wait for button presses
sleep(60);
}
Edit: I also tried adding a simple 5 second pause at the beginning of the program, but this didn't seem to make any difference.

Python command to check the disk space on UNIX servers

I am writing a script which checks space on UNIX servers. But I am unable to find the right command. I used the following but it gives me same percentage for all paths.
st = os.statvfs("/dev/hd3")
You give it the mount point, not the device name.
So, instead of e.g.
st = os.statvfs("/dev/hd3")
you do
st = os.statvfs("/boot")

detecting if program is installed on machine

Say I have an application I write, that relies for some task on an externat app (lets call it "tool") that is installed on my machine. In my program, I call it with system( "tool myarguments" ); , works fine.
Now, I want to distribute my app. Of course, the end-user might not have "tool" installed on his machine, so I would like my app to check this, and printout a message for the user. So my question is:
Is there a portable way to check for the existence of an app on the machine? (assuming we know its name and it is accessible through the machine's shell).
Additional information: First idea was to check the existence of the binary file, but:
This is platform dependent,
depending on how it has been installed (build from sources, installed through package,...), it might not always be in the same place, although it can be accessed through local path.
My first opinion on this question is "No", but maybe somebody has an idea ?
Reference: system()
Related: stackoverflow.com/questions/7045879
If you use the Qt toolkit, QProcess may help you.
Edit: and look for QProcess::error() return value: if it is QProcess::FailedToStart , then either it is not installed, or you have insufficient permissions.
If running the tool without argument has no side-effect, and is expected to return an exit code of 0, you can use system("tool") to check tool's existence.
You can check whether the command has been found by checking system's return value like this:
int ret = system("tool");
if (ret != 0) {
std::cout << "tool is not here, move along\n";
}
It is portable in the sense that system is expected to return 0 if all goes well and the command return status is 0 too.
For example, on Linux, running system("non_existing_command") returns 0x7F00 (same type of value as returned by wait()).
On Windows, it returns 1 instead.

Folder size linux

I need to monitor folders on my linux machine periodically to check whether they are exceeding certain limits.
I have checked stat function call but running stat recursively on all sub folders and files is time consuming and I need to do this for all folders.
Does kernal maintain any datastructures which I can interpret in my program.Or is their any standard api for this.
If you need to enforce limits then use quotas
In case the quota mechanism isn't suitible, then
inotify might be handy:
From wikipedia:
inotify is a Linux kernel subsystem
that acts to extend filesystems to
notice changes to the filesystem, and
report those changes to applications.report those changes to applications.
Type
du -sm directory_name
Will give you the total size of the directory in megabytes recursively.
Type
man du
for help with this command.
You want quotactl:
quotactl -- manipulate filesystem quotas
SYNOPSIS
#include <sys/types.h> /* types needed by quota.h */
#include <sys/quota.h> /* for disk quotas */
Calling stat recursively is the only way to get the current folder size. If you want to continuously monitor the file system, take a look at inotify.
I agree with #Axel. However if you really need to do this in code, you could execute the du shell command via popen:
FILE* pf = popen("du -ch [your folder] | grep total")
Then read the output from the command via the file handle and fgets(...)
Use command du, check this link ...
"How To Check Folder Size"