Python command to check the disk space on UNIX servers - python-2.7

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")

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 :)

Creating a Arcmap tool that buffers and then intersects

Im trying to create a tool that buffers a feature class (polygon) and then intersects the buffer output layer with a point shapefile. When I run the tool the buffer analysis runs and completes but the intersect analysis does not. The error message is
ExecuteError: Failed to execute. Parameters are not valid.
ERROR 000732: (my buffer output layer & point shapefile) does not exist or is not supported
Failed to execute (Intersect).
All my layers are loaded in my arcmpap so I am not sure why it does that.
import arcpy
in_Path = arcpy.GetParameterAsText(0) # first parameter in the interactive tool
out_Path = arcpy.GetParameterAsText(1) # second parameter in the interactive tool
bufferDistance = arcpy.GetParameterAsText(2)# third parameter in the interactive tool
result_buffer = arcpy.Buffer_analysis(in_Path, out_Path, bufferDistance,"FULL", "ROUND", "ALL", "") #the parameters to able compute the tool
# ^^ assign variable for the buffer analysis tool
in_CitiesShapefile = arcpy.GetParameterAsText(3)# fourth parameter in the interactive tool
out_CitiesWithinBuffer = arcpy.GetParameterAsText(4) # fifth parameter in the interactive tool
arcpy.Intersect_analysis([out_Path, in_CitiesShapefile], out_CitiesWithinBuffer,"ALL", "", "INPUT") #the parameters to able compute the tool
This error often comes up when there is a problem with file/folder paths.
I'd check the parameters that take paths for the following:
Misspelled folder names
Using backslashes instead of forward slashes
Having spaces in the path names
This esri kb article might help.

Crontab No Longer Runs Raspberry Pi Python Script in Background But Still Runs Manually

I am able to run my Python script in the background to control two servos by automatically launching the script at boot up using sudo crontab -e. I modified the script so I am now continually writing the servos current position to a horz.txt and vert.txt file and using those files to initialize the steppers to their home position so I can find home position again after a power loss. The script works fine with the horz.txt and vert.txt code that I added when I manually launch the script from the command line on the black screen using sudo python mystepper6.py, but it doesn't launch automatically at startup nor does it show up as running when I type ps ax on the command line. I added a little extra code just to wiggle the servos before the main program starts and and the servos automatically wiggle as programmed in the sudo crontab -e but then it just stops and won't continue to find the home position. It seems to be something with the new code but I don't know what it could be. My sudo crontab -e line is #reboot (sleep2;python /home/pi/mystepper6.py) &. Below is the script for mystepper6.py.
The script below was shortened to show the relevant lines due to limited space available in this post. The sudo reboot hangs with no error message near the bottom where it is commented 'move to home position' (it doesn't move). I am able to print adjustv and adjusth integers prior to that point so the variables are properly assigned a value from the .txt files at that point. When I manually run mystepper6.py from the command line it runs perfectly.
I have spent waaay too many hours on this problem and have purchased two e-books to no avail. Please help.
import RPi.GPIO as gpio # import library RPi.GPIO gpio=use general purpose input output pin names
import time # import time library
PINSh = [27,10,18,23] # variable 'PINS' holds a list of gpio pin numbers
SEQAh = [(27,),(10,),(18,),(23,)]
PINSv = [4,17,22,24] # variable 'PINS' holds a list of gpio pin numbers
SEQAv = [(4,),(17,),(22,),(24,)]
DELAY = 0.01 # time between motor steps (too small of a number then the motor stalls)
alpha = 140 # horizontal full scale viewing angle in motor counts 128 counts = 360 degrees
beta = 30 # was 15 vertical full scale viewing angle in motor counts 128 counts = 360 degrees
gpio.setmode(gpio.BCM) # tells RPi.GPIO we want to use pin names (BCM is the mfg)
for pin in PINSh: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT) # this says we want to use 'pin' as an output
for pin in PINSv: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT)
def stepper(sequence, pins): # def says 'stepper' is the function name (like a variable), then parameters are inside ()
for step in sequence:
for pin in pins:
if pin in step:
gpio.output(pin, gpio.HIGH)
else:
gpio.output(pin, gpio.LOW)
webcam_horz_home = open("horz.txt", "a")
webcam_horz_home.close()
webcam_vert_home = open("vert.txt", "a")
webcam_vert_home.close()
# load last position prior to power down
webcam_horz_home = open("horz.txt", "r")
rows = webcam_horz_home.readlines();
for row in rows:
adjusth = int(row)
webcam_horz_home.close()
webcam_vert_home = open("vert.txt", "r")
rows = webcam_vert_home.readlines();
for row in rows:
adjustv = int(row)
webcam_vert_home.close()
counter = 0 # move to home position
while counter < adjustv:
stepper(SEQAv, PINSv)
counter = counter + 1
# CONTINUAL PAN AND TILT OPERATION (box pattern):
I just tested this on my Pi running Raspbian and it worked.
First, I created a python script called some_script.py in the primary user's home directory.
Script contents:
import sys
import time
with open("/home/username/some_script.py.out", "w") as f:
f.write(str(time.time()) + " " + "some_script.py RAN!\n")
Then, in the terminal, I set the executable bit on the file which allows it be executed:
sudo chmod +x some_script.py
Then, also in the terminal, I typed sudo crontab -e and added the following line at the bottom of the root user's crontab:
#reboot sleep 2; /usr/bin/python /home/username/some_script.py
I then rebooted, cded to /home/username/ and confirmed that python had run at reboot and written to a file:
cat some_script.py.out
1458062009.53 some_script.py RAN!
UPDATE / SOLUTION
After confirming that the OP was able to successfully replicate the steps above, I was fairly confident that this was not an issue stemming from varying implementations of cron on different *nix systems or some other edge case. As expected, he could run python via cron, he could use the #reboot feature and he could write to disk without any sort of permission issues.
However, it still didn't work. What did solve the issue was simply to use absolute paths rather than relative paths.
Changing
webcam_horz_home = open("horz.txt", "a")
to
webcam_horz_home = open("/home/pi/horz.txt", "a")
and
webcam_vert_home = open("vert.txt", "a")
to
webcam_vert_home = open("/home/pi/vert.txt", "a")
got OP's steppers purring again :)
EXPLANATION / BACKGROUND
When executing scripts or commands via the crontab of other users (in this case root), paths relative to the regular user's home directory (eg. ~/.bashrc) will no longer be valid or will point to a different file with the same filename if it exists. The same "issue" is sometimes seen when people run servers that call scripting languages such as PHP (often executed by the www-data user).
On a Raspberry Pi, these things can cause a bit of a catch-22 when working with GPIOs because the GPIO device is locked down and not accessible to unprivileged users without a change of permissions and groups.
If OP ran his script as root by adding the cron entry via sudo crontab -e, he would have access to the GPIO device (since root has access to almost everything). However, the relative paths in his python script that implicitly reference the home folder of the non-privileged user pi would no longer be valid (since home now means the folder /root which is the home folder of the root user).
If OP ran his scripts via the non-privileged pi user's crontab by adding the cron entries via crontab -e (without sudo), the paths would be valid (home or ~/ would now mean /home/pi/) but then he wouldn't have access to the GPIO device since pi is pretty unprivileged. Note: the #reboot feature is not available in all cron implementations (some embedded and stripped down *nix distros don't have it) and often it doesn't work for users other than root.
This means that OP had two options (there might be more; i'm no Linux guru):
place the files vert.txt and horz.txt in the home folder of the root user.
simply change the paths specified in the python script and keep running the script #reboot in root's crontab.
No. 2 is probably better since it keeps the home folder of root empty and keeps OP's files in pi's home folder. root should generally not be messed with unless there's no other options such as using sudo.

Permissions issue calling bash script from c++ code that apache is running

The goal of this code is to create a stack trace whenever a sigterm/sigint/sigsegv/etc is caught. In order to not rely on memory management inside of the C++ code in the case of a sigsegv, I have decided to write a bash script that will receive the PID and memory addresses in the trace array.
The Sig events are being caught.
Below is where I generate the call to the bash script
trace_size = backtrace(trace, 16);
trace[1] = (void *)ctx->rsi;
messages = backtrace_symbols(trace, trace_size);
char syscom[356] = {0};
sprintf(syscom,"bash_crash_supp.sh %d", getpid());
for (i=1; i<(trace_size-1) && i < 10; ++i)
{
sprintf(syscom,"%s %p",syscom,trace[i]);
}
Below is where my issue arises. The command in syscom is generating correctly. I can stop the code before the following popen, run the command in a terminal, and it functions correctly.
However running the script directly from the c++ code does not seem to work.
setuid(0);
FILE *bashCommand = popen(syscom,"r");
char buf[256] = {0};
while(fgets(buf,sizeof(buf),bashCommand) != 0) {
LogMessage(LOG_WARNING, "%s\n", buf);
}
pclose(bashCommand);
exit(sig);
The purpose of the bash script is to get the offset from /proc/pid/maps, and then use that to run addr2line to get the file name/line number.
strResult=$(sudo cat /proc/"$1"/maps | grep "target_file" | grep -m 1 '[0-9a-fA-F]')
offset=$( cut -d '-' -f 1 <<< "$strResult");
However offset is getting 0 when I run from the c++ code, but when I run the exact same command (that is stored in syscom in the c++ code) in a terminal, I get the expected output.
I have been trying to fix this for a while. Permissions are most likely the issue, but I've tried to work around these with every way I know of/have seen via google. The user trying to run the script (currently running the c++ code) is apache.
The fix does not need to worry about the security of the box. If something as simple as "chmod 777 /proc -r" worked, that would have been the solution (sadly the OS doesn't let me mess do such commands with /proc).
Things I've already tried:
Adding `` around the command that's stored in syscom from the c++ code
chown the script to apache
chmod 4755 on the bash_crash_supp.sh script, allowing it to always fire as root.
I have added apache to sudoers (visudo), allowing them to run sudo without using a password
I have added a sub file to sudoers.d (just in case) that does the same as above
I have looked into objdump, however it does not give me either the offset or the file/line num for an addr (from what I can see)
I have setuid(0) in the c++ code to set the current user to root
Command generated in C++
bash_crash_supp.sh 25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Params in bash:
25817 0x7f4bfe600ec8 0x7f4bf28f7400 0x7f4bf28f83c6 0x7f4bf2904f02 0x7f4bfdf0fbb0 0x7f4bfdf1346e 0x7f4bfdf1eb30 0x7f4bfdf1b9a8 0x7f4bfdf176b8
Can anyone think of any other ways to solve this?
Long story short, almost all Unix-based systems ignore setuid on any interpreted script (anything with a shebang #!) as a security precaution.
You may use setuid on actual executables, but not the shell scripts themselves. If you're willing to take a massive security risk, you can make a wrapper executable to run the shell script and give the executable setuid.
For more information, see this question on the Unix StackExchange: https://unix.stackexchange.com/a/2910

Mount NTFS device in C++ on linux?

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.