Skip to content

Commit

Permalink
Dont barf if home directory is not writable (#814)
Browse files Browse the repository at this point in the history
* Handle the home directory being read-only / cache directory being unavailable

Fixes #799

* Add doctest for context.cache_dir
  • Loading branch information
zachriggle authored Dec 15, 2016
1 parent 386e686 commit df54bf2
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 5 deletions.
40 changes: 40 additions & 0 deletions pwnlib/context/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import os
import platform
import socket
import stat
import string
import subprocess
import sys
Expand Down Expand Up @@ -1126,6 +1127,45 @@ def adb(self):

return command

@property
def cache_dir(self):
"""Directory used for caching data.
Note:
May be either a path string, or ``None``.
Example:
>>> cache_dir = context.cache_dir
>>> cache_dir is not None
True
>>> os.chmod(cache_dir, 0o000)
>>> context.cache_dir is None
True
>>> os.chmod(cache_dir, 0o755)
>>> cache_dir == context.cache_dir
True
"""
home = os.path.expanduser('~')

if not os.access(home, os.W_OK):
return None

cache = os.path.join(home, '.pwntools-cache')

if not os.path.exists(cache):
try:
os.mkdir(cache)
except OSError:
return None

# Some wargames e.g. pwnable.kr have created dummy directories
# which cannot be modified by the user account (owned by root).
if not os.access(cache, os.W_OK):
return None

return cache


#*************************************************************************
# ALIASES
Expand Down
8 changes: 7 additions & 1 deletion pwnlib/shellcraft/internal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import os
from collections import defaultdict

from ..context import context

__all__ = ['make_function']

loaded = {}
Expand Down Expand Up @@ -33,10 +35,14 @@ def go_inside(self):

render_global = IsInside()

cache = context.cache_dir
if cache:
cache = os.path.join(cache, 'mako')

curdir = os.path.dirname(os.path.abspath(__file__))
lookup = TemplateLookup(
directories = [os.path.join(curdir, 'templates')],
module_directory = os.path.expanduser('~/.pwntools-cache/mako')
module_directory = cache
)

# The purpose of this definition is to create a new Tag.
Expand Down
26 changes: 22 additions & 4 deletions pwnlib/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,11 @@ def available_on_pypi(prerelease=current_version.is_prerelease):

def cache_file():
"""Returns the path of the file used to cache update data, and ensures that it exists."""
cache_dir = os.path.expanduser('~/.pwntools-cache')
cache_dir = context.cache_dir

if not cache_dir:
return None

cache_file = os.path.join(cache_dir, 'update')

if not os.path.isdir(cache_dir):
Expand All @@ -66,12 +70,23 @@ def cache_file():

def last_check():
"""Return the date of the last check"""
return os.path.getmtime(cache_file())
cache = cache_file()
if cache:
return os.path.getmtime(cache_file())

# Fallback
return time.time()

def should_check():
"""Return True if we should check for an update"""
if read(cache_file()).strip() == 'never':
filename = cache_file()

if not filename:
return False

if read(filename).strip() == 'never':
return False

return time.time() > (last_check() + update_freq)

def perform_check(prerelease=current_version.is_prerelease):
Expand Down Expand Up @@ -109,7 +124,10 @@ def perform_check(prerelease=current_version.is_prerelease):
where = None
command = None

os.utime(cache_file(), None)
cache = cache_file()

if cache:
os.utime(cache, None)

if best == current_version:
log.info("You have the latest version of Pwntools (%s)" % best)
Expand Down

0 comments on commit df54bf2

Please sign in to comment.