~hazmat/pyjuju/local-provider-container-wait-flags

« back to all changes in this revision

Viewing changes to juju/charm/directory.py

  • Committer: kapil.thangavelu at canonical
  • Date: 2012-02-22 01:21:22 UTC
  • mfrom: (453.1.4 symlink-guard)
  • Revision ID: kapil.thangavelu@canonical.com-20120222012122-4eks0fe7g3bzcy0o
merge symlink-guard verify that charm symlinks don't extend outside of the charm and verify file types being included, internal symlinks are ok. [r=bcsaller,jimbaker][f=928348]

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import os
 
2
import stat
2
3
import zipfile
3
4
import tempfile
4
5
 
5
 
from juju.charm.base import CharmBase, get_revision
 
6
from juju.charm.base import CharmBase, get_revision, ZIP_SYMLINK_ATTR
6
7
from juju.charm.bundle import CharmBundle
7
8
from juju.charm.config import ConfigOptions
 
9
from juju.charm.errors import InvalidCharmFile
8
10
from juju.charm.metadata import MetaData
9
11
 
10
12
 
60
62
        """
61
63
 
62
64
        zf = zipfile.ZipFile(path, 'w', zipfile.ZIP_DEFLATED)
63
 
 
64
65
        for dirpath, dirnames, filenames in os.walk(self.path):
65
66
            relative_path = dirpath[len(self.path) + 1:]
66
67
            if relative_path and not self._ignore(relative_path):
69
70
                archive_name = os.path.join(relative_path, name)
70
71
                if not self._ignore(archive_name):
71
72
                    real_path = os.path.join(dirpath, name)
72
 
                    zf.write(real_path, archive_name)
73
 
 
 
73
                    self._check_type(real_path)
 
74
                    if os.path.islink(real_path):
 
75
                        self._check_link(real_path)
 
76
                        self._write_symlink(
 
77
                            zf, os.readlink(real_path), archive_name)
 
78
                    else:
 
79
                        zf.write(real_path, archive_name)
74
80
        zf.close()
75
81
 
 
82
    def _check_type(self, path):
 
83
        """Check the path
 
84
        """
 
85
        s = os.stat(path)
 
86
        if stat.S_ISDIR(s.st_mode) or stat.S_ISREG(s.st_mode):
 
87
            return path
 
88
        raise InvalidCharmFile(
 
89
            self.metadata.name, path, "Invalid file type for a charm")
 
90
 
 
91
    def _check_link(self, path):
 
92
        link_path = os.readlink(path)
 
93
        if link_path[0] == "/":
 
94
            raise InvalidCharmFile(
 
95
                self.metadata.name, path, "Absolute links are invalid")
 
96
        path_dir = os.path.dirname(path)
 
97
        link_path = os.path.join(path_dir, link_path)
 
98
        if not link_path.startswith(os.path.abspath(self.path)):
 
99
            raise InvalidCharmFile(
 
100
                self.metadata.name, path, "Only internal symlinks are allowed")
 
101
 
 
102
    def _write_symlink(self, zf, link_target, link_path):
 
103
        """Package symlinks with appropriate zipfile metadata."""
 
104
        info = zipfile.ZipInfo()
 
105
        info.filename = link_path
 
106
        info.create_system = 3
 
107
        info.external_attr = ZIP_SYMLINK_ATTR
 
108
        zf.writestr(info, link_target)
 
109
 
76
110
    def _ignore(self, path):
77
111
        if path == "build" or path.startswith("build/"):
78
112
            return True