src/modules/misc.py
author Bart Smaalders <Bart.Smaalders@Sun.COM>
Fri, 15 Aug 2008 14:33:39 -0700
changeset 462 910600c14093
parent 461 37cf3ac75e37
child 487 9cb85c3d8491
permissions -rw-r--r--
45 "move" action for files that are renamed, but must be preserved 590 actions should be evaluated across entire image transformation 2778 Need a way of adding the same commands to every package 2779 It would be handy to confine chatrr_glob to a single type
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
409
713e20963dc2 2314 shebang lines should use minimum python version
Shawn Walker <swalker@opensolaris.org>
parents: 404
diff changeset
     1
#!/usr/bin/python2.4
46
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     2
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     3
# CDDL HEADER START
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     4
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     5
# The contents of this file are subject to the terms of the
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     6
# Common Development and Distribution License (the "License").
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     7
# You may not use this file except in compliance with the License.
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     8
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
     9
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    10
# or http://www.opensolaris.org/os/licensing.
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    11
# See the License for the specific language governing permissions
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    12
# and limitations under the License.
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    13
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    14
# When distributing Covered Code, include this CDDL HEADER in each
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    15
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    16
# If applicable, add the following below this CDDL HEADER, with the
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    17
# fields enclosed by brackets "[]" replaced with your own identifying
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    18
# information: Portions Copyright [yyyy] [name of copyright owner]
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    19
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    20
# CDDL HEADER END
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    21
#
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    22
260
a1b77322abb2 255 Symbolic HTTP response codes should be used
Shawn Walker <swalker@opensolaris.org>
parents: 181
diff changeset
    23
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
46
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    24
# Use is subject to license terms.
119
537d69114be4 Implement bundled file downloads using filelist
johansen <johansen@sun.com>
parents: 108
diff changeset
    25
384
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
    26
import errno
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
    27
import httplib
119
537d69114be4 Implement bundled file downloads using filelist
johansen <johansen@sun.com>
parents: 108
diff changeset
    28
import os
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
    29
import platform
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
    30
import re
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
    31
import sha
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
    32
import socket
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    33
import urllib
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    34
import urllib2
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    35
import urlparse
384
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
    36
import sys
342
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
    37
import zlib
443
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    38
import time
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    39
import calendar
462
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    40
import shutil
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    41
from stat import *
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    42
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    43
import pkg.urlhelpers as urlhelpers
319
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    44
import pkg.portable as portable
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    45
from pkg.client.imagetypes import img_type_names, IMG_NONE
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    46
from pkg import VERSION
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    47
443
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    48
def time_to_timestamp(t):
462
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    49
        """convert seconds since epoch to %Y%m%dT%H%M%SZ format"""
443
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    50
        # XXX optimize?
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    51
        return time.strftime("%Y%m%dT%H%M%SZ", time.gmtime(t))
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    52
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    53
def timestamp_to_time(ts):
462
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    54
        """convert %Y%m%dT%H%M%SZ format to seconds since epoch"""
443
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    55
        # XXX optimize?
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    56
        return calendar.timegm(time.strptime(ts, "%Y%m%dT%H%M%SZ"))
5ffa5b7dac9c 2589 pyc files generate lots of verify chaff
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 429
diff changeset
    57
462
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    58
def copyfile(src_path, dst_path):
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    59
        """copy a file, preserving attributes, ownership, etc. where possible"""
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    60
        stat = os.lstat(src_path)
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    61
        shutil.copy2(src_path, dst_path)
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    62
        try:
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    63
                portable.chown(dst_path, stat.st_uid, stat.st_gid)
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    64
        except OSError, e:
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    65
                if e.errno != errno.EPERM:
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    66
                        raise
910600c14093 45 "move" action for files that are renamed, but must be preserved
Bart Smaalders <Bart.Smaalders@Sun.COM>
parents: 461
diff changeset
    67
46
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    68
def hash_file_name(f):
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    69
        """Return the two-level path fragment for the given filename, which is
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    70
        assumed to be a content hash of at least 8 distinct characters."""
119
537d69114be4 Implement bundled file downloads using filelist
johansen <johansen@sun.com>
parents: 108
diff changeset
    71
        return os.path.join("%s" % f[0:2], "%s" % f[2:8], "%s" % f)
46
86a10bea7bb6 commonize file/ prefix handling; sketch manifest difference algorithm
Stephen Hahn <sch@sun.com>
parents:
diff changeset
    72
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    73
def url_affix_trailing_slash(u):
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    74
        if u[-1] != '/':
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    75
                u = u + '/'
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    76
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    77
        return u
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    78
319
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    79
_client_version = "pkg/%s (%s %s; %s %s; %%s)" % \
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    80
    (VERSION, portable.util.get_canonical_os_name(), platform.machine(),
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    81
    portable.util.get_os_release(), platform.version())
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    82
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    83
def versioned_urlopen(base_uri, operation, versions = [], tail = None,
319
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
    84
    data = None, headers = {}, ssl_creds = None, imgtype = IMG_NONE):
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    85
        """Open the best URI for an operation given a set of versions.
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    86
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    87
        Both the client and the server may support multiple versions of
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    88
        the protocol of a particular operation.  The client will pass
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    89
        this method an ordered array of versions it understands, along
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    90
        with the base URI and the operation it wants.  This method will
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    91
        open the URL corresponding to the best version both the client
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    92
        and the server understand, returning a tuple of the open URL and
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    93
        the version used on success, and throwing an exception if no
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    94
        matching version can be found.
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    95
        """
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    96
        # Ignore http_proxy for localhost case, by overriding
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    97
        # default proxy behaviour of urlopen().
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
    98
        netloc = urlparse.urlparse(base_uri)[1]
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
    99
285
538afd6a9d3e 763 pkg image-create /foo , pkg image-create /tmp/foo both yield (different) tracebacks
Danek Duvall <danek.duvall@sun.com>
parents: 260
diff changeset
   100
        if not netloc:
538afd6a9d3e 763 pkg image-create /foo , pkg image-create /tmp/foo both yield (different) tracebacks
Danek Duvall <danek.duvall@sun.com>
parents: 260
diff changeset
   101
                raise ValueError, "Malformed URL: %s" % base_uri
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   102
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   103
        if urllib.splitport(netloc)[0] == "localhost":
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   104
                # XXX cache this opener?
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   105
                proxy_handler = urllib2.ProxyHandler({})
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   106
                opener_dir = urllib2.build_opener(proxy_handler)
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   107
                url_opener = opener_dir.open
310
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   108
        elif ssl_creds and ssl_creds != (None, None):
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   109
                cert_handler = urlhelpers.HTTPSCertHandler(
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   110
                    key_file = ssl_creds[0], cert_file = ssl_creds[1])
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   111
                opener_dir = urllib2.build_opener(cert_handler)
8fa744df663a 975 Catalogs need to know their origins
johansen <johansen@sun.com>
parents: 285
diff changeset
   112
                url_opener = opener_dir.open
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   113
        else:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   114
                url_opener = urllib2.urlopen
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   115
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   116
        for version in versions:
351
9301d4d85349 767 pkg client can't talk to repo at a path other than / on a server
johansen <johansen@sun.com>
parents: 342
diff changeset
   117
                if base_uri[-1] != '/':
9301d4d85349 767 pkg client can't talk to repo at a path other than / on a server
johansen <johansen@sun.com>
parents: 342
diff changeset
   118
                        base_uri += '/'
9301d4d85349 767 pkg client can't talk to repo at a path other than / on a server
johansen <johansen@sun.com>
parents: 342
diff changeset
   119
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   120
                if tail:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   121
                        uri = urlparse.urljoin(base_uri, "%s/%s/%s" % \
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   122
                            (operation, version, tail))
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   123
                else:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   124
                        uri = urlparse.urljoin(base_uri, "%s/%s" % \
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   125
                            (operation, version))
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   126
319
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
   127
                headers["User-Agent"] = \
39b8b5c538bf 1104 want custom user-agent string
Danek Duvall <danek.duvall@sun.com>
parents: 310
diff changeset
   128
                    _client_version % img_type_names[imgtype]
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   129
                req = urllib2.Request(url = uri, headers = headers)
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   130
                if data is not None:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   131
                        req.add_data(data)
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   132
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   133
                try:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   134
                        c = url_opener(req)
153
05d90faecc40 Fix versioned_urlopen() to catch the right error, and catch URLError higher up.
Danek Duvall <danek.duvall@sun.com>
parents: 145
diff changeset
   135
                except urllib2.HTTPError, e:
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   136
                        if e.code != httplib.NOT_FOUND or \
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   137
                            e.msg != "Version not supported":
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   138
                                raise
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   139
                        continue
260
a1b77322abb2 255 Symbolic HTTP response codes should be used
Shawn Walker <swalker@opensolaris.org>
parents: 181
diff changeset
   140
                # XXX catch BadStatusLine and convert to INTERNAL_SERVER_ERROR?
145
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   141
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   142
                return c, version
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   143
        else:
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   144
                # Couldn't find a version that we liked.
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   145
                raise RuntimeError, \
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   146
                    "%s doesn't speak a known version of %s operation" % \
08bee7fd13f6 Add versioning to the protocols
Danek Duvall <danek.duvall@sun.com>
parents: 119
diff changeset
   147
                    (base_uri, operation)
327
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   148
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   149
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   150
_hostname_re = re.compile("^[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9]+\.?)*$")
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   151
_invalid_host_chars = re.compile(".*[^a-zA-Z0-9\-\.]+")
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   152
_valid_proto = ["http", "https"]
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   153
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   154
def valid_auth_prefix(prefix):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   155
        """Verify that the authority prefix only contains valid characters."""
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   156
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   157
        # This is a workaround for the the hostname_re being slow when
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   158
        # it comes to finding invalid characters in the prefix string.
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   159
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   160
        if _invalid_host_chars.match(prefix):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   161
                # prefix bad chars
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   162
                return False
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   163
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   164
        if _hostname_re.match(prefix):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   165
                return True
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   166
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   167
        return False
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   168
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   169
def valid_auth_url(url):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   170
        """Verify that the authority URL contains only valid characters."""
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   171
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   172
        # First split the URL and check if the scheme is one we support
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   173
        o = urlparse.urlsplit(url)
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   174
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   175
        if not o[0] in _valid_proto:
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   176
                return False
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   177
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   178
        # Next verify that the network location is valid
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   179
        host, port = urllib.splitport(o[1])
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   180
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   181
        if not host or _invalid_host_chars.match(host):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   182
                return False
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   183
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   184
        if _hostname_re.match(host):
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   185
                return True
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   186
6c6bd07efe8d 1031 authority prefix needs validation
johansen <johansen@sun.com>
parents: 319
diff changeset
   187
        return False
342
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   188
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   189
def gunzip_from_stream(gz, outfile):
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   190
        """Decompress a gzipped input stream into an output stream.
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   191
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   192
        The argument 'gz' is an input stream of a gzipped file (XXX make it do
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   193
        either a gzipped file or raw zlib compressed data), and 'outfile' is is
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   194
        an output stream.  gunzip_from_stream() decompresses data from 'gz' and
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   195
        writes it to 'outfile', and returns the hexadecimal SHA-1 sum of that
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   196
        data.
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   197
        """
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   198
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   199
        FHCRC = 2
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   200
        FEXTRA = 4
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   201
        FNAME = 8
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   202
        FCOMMENT = 16
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   203
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   204
        # Read the header
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   205
        magic = gz.read(2)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   206
        if magic != "\037\213":
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   207
                raise IOError, "Not a gzipped file"
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   208
        method = ord(gz.read(1))
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   209
        if method != 8:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   210
                raise IOError, "Unknown compression method"
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   211
        flag = ord(gz.read(1))
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   212
        gz.read(6) # Discard modtime, extraflag, os
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   213
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   214
        # Discard an extra field
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   215
        if flag & FEXTRA:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   216
                xlen = ord(gz.read(1))
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   217
                xlen = xlen + 256 * ord(gz.read(1))
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   218
                gz.read(xlen)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   219
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   220
        # Discard a null-terminated filename
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   221
        if flag & FNAME:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   222
                while True:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   223
                        s = gz.read(1)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   224
                        if not s or s == "\000":
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   225
                                break
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   226
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   227
        # Discard a null-terminated comment
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   228
        if flag & FCOMMENT:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   229
                while True:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   230
                        s = gz.read(1)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   231
                        if not s or s == "\000":
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   232
                                break
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   233
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   234
        # Discard a 16-bit CRC
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   235
        if flag & FHCRC:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   236
                gz.read(2)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   237
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   238
        shasum = sha.new()
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   239
        dcobj = zlib.decompressobj(-zlib.MAX_WBITS)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   240
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   241
        while True:
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   242
                buf = gz.read(64 * 1024)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   243
                if buf == "":
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   244
                        ubuf = dcobj.flush()
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   245
                        shasum.update(ubuf)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   246
                        outfile.write(ubuf)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   247
                        break
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   248
                ubuf = dcobj.decompress(buf)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   249
                shasum.update(ubuf)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   250
                outfile.write(ubuf)
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   251
5e1f4d8429bf 669 Need method to print package licenses before installation
Danek Duvall <danek.duvall@sun.com>
parents: 327
diff changeset
   252
        return shasum.hexdigest()
384
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   253
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   254
class PipeError(Exception):
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   255
        """ Pipe exception. """
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   256
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   257
        def __init__(self, args=None):
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   258
                self.args = args
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   259
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   260
def msg(*text):
429
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   261
        """ Emit a message. """
384
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   262
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   263
        try:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   264
                print ' '.join([str(l) for l in text])
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   265
        except IOError, e:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   266
                if e.errno == errno.EPIPE:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   267
                        raise PipeError, e
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   268
                raise
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   269
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   270
def emsg(*text):
429
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   271
        """ Emit a message to sys.stderr. """
384
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   272
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   273
        try:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   274
                print >> sys.stderr, ' '.join([str(l) for l in text])
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   275
        except IOError, e:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   276
                if e.errno == errno.EPIPE:
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   277
                        raise PipeError, e
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   278
                raise
9d4746e5dd3e 115 pkg needs to not have a cow on a SIGPIPE
Shawn Walker <swalker@opensolaris.org>
parents: 351
diff changeset
   279
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   280
def port_available(host, port):
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   281
        """Returns True if the indicated port is available to bind to;
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   282
        otherwise returns False."""
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   283
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   284
        port = int(port)
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   285
        if host is None:
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   286
                # None is the same as INADDR_ANY, which for our purposes,
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   287
                # should be the hostname.
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   288
                host = socket.gethostname()
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   289
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   290
        try:
404
e5329e84b9a8 2331 depot command-line parsing errors cause traceback
Shawn Walker <swalker@opensolaris.org>
parents: 388
diff changeset
   291
                sock = None
e5329e84b9a8 2331 depot command-line parsing errors cause traceback
Shawn Walker <swalker@opensolaris.org>
parents: 388
diff changeset
   292
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   293
                # Get the address family of our host (to allow for IPV6, etc.).
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   294
                for entry in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   295
                    socket.SOCK_STREAM):
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   296
                        family, socktype, proto, canonname, sockaddr = entry
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   297
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   298
                        # First try to bind to the specified port to see if we
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   299
                        # have an access problem or some other issue.
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   300
                        sock = socket.socket(family, socktype, proto)
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   301
                        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   302
                            1)
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   303
                        sock.bind((host, port))
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   304
                        sock.close()
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   305
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   306
                        # Now try to connect to the specified port to see if it
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   307
                        # is already in use.
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   308
                        sock = socket.socket(family, socktype, proto)
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   309
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   310
                        # Some systems timeout rather than refuse a connection.
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   311
                        # This avoids getting stuck on SYN_SENT for those
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   312
                        # systems (such as certain firewalls).
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   313
                        sock.settimeout(1.0)
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   314
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   315
                        sock.connect((host, port))
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   316
                        sock.close()
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   317
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   318
                        # If we successfully connected...
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   319
                        raise socket.error(errno.EBUSY,
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   320
                            'Port already in use')
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   321
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   322
        except socket.error, e:
404
e5329e84b9a8 2331 depot command-line parsing errors cause traceback
Shawn Walker <swalker@opensolaris.org>
parents: 388
diff changeset
   323
                errnum = e[0]
e5329e84b9a8 2331 depot command-line parsing errors cause traceback
Shawn Walker <swalker@opensolaris.org>
parents: 388
diff changeset
   324
                try:
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   325
                        text = e[1]
404
e5329e84b9a8 2331 depot command-line parsing errors cause traceback
Shawn Walker <swalker@opensolaris.org>
parents: 388
diff changeset
   326
                except IndexError:
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   327
                        text = e[0]
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   328
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   329
                if sock:
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   330
                        sock.close()
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   331
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   332
                if errnum == errno.ECONNREFUSED:
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   333
                        # If we could not connect to the port, we know it isn't
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   334
                        # in use.
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   335
                        return True, None
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   336
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   337
                return False, text
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   338
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   339
def bytes_to_str(bytes):
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   340
        """Returns a human-formatted string representing the number of bytes
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   341
        in the largest unit possible."""
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   342
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   343
        units = [
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   344
            ("B", 2**10),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   345
            ("kB", 2**20),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   346
            ("MB", 2**30),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   347
            ("GB", 2**40),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   348
            ("TB", 2**50),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   349
            ("PB", 2**60),
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   350
            ("EB", 2**70)
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   351
        ]
386
5cd680466abe 2147 depot should check port instead of showing traceback if port binding fails
Shawn Walker <swalker@opensolaris.org>
parents: 384
diff changeset
   352
451
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   353
        for uom, limit in units:
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   354
                if uom != "EB" and bytes >= limit:
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   355
                        # Try the next largest unit of measure unless this is
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   356
                        # the largest or if the byte size is within the current
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   357
                        # unit of measure's range.
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   358
                        continue
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   359
                else:
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   360
                        return "%.2f %s" % (round(bytes / float(
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   361
                            limit / 2**10), 2), uom)
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   362
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   363
def get_rel_path(request, uri):
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   364
        # Calculate the depth of the current request path relative to our base
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   365
        # uri. path_info always ends with a '/' -- so ignore it when
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   366
        # calculating depth.
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   367
        depth = request.path_info.count("/") - 1
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   368
        return ("../" * depth) + uri
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   369
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   370
def get_res_path(request, name):
74f1fe85fe2d 1324 RSS / Atom feeds of repository updates
Shawn Walker <shawn.walker@sun.com>
parents: 443
diff changeset
   371
        return get_rel_path(request, "%s/%s" % ("static", name))
388
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   372
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   373
# Set the maximum number of timeouts before we giveup.  This can
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   374
# be adjusted by setting the environment variable PKG_TIMEOUT_MAX
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   375
MAX_TIMEOUT_COUNT = 4
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   376
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   377
class TransferTimedOutException(Exception):
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   378
        def __init__(self, args = None):
5a08791fb814 2188 Client must fail gracefully when network timeout occurs
johansen <johansen@sun.com>
parents: 386
diff changeset
   379
                self.args = args
429
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   380
461
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   381
class TransferContentException(Exception):
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   382
        def __init__(self, args = None):
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   383
                self.args = args
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   384
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   385
class InvalidContentException(Exception):
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   386
        def __init__(self, action, hashval):
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   387
                self.action = action
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   388
                self.hashval = hashval
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   389
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   390
        def __str__(self):
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   391
                str = "Action with path %s should have hash %s. Computed hash %s instead." % \
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   392
                    (self.action.attrs["path"], self.action.attrs["chash"], 
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   393
                    self.hashval)
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   394
                return str
429
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   395
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   396
# Default maximum memory useage during indexing
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   397
# This is a soft cap since memory usage is estimated.
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   398
try:
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   399
        phys_pages = os.sysconf("SC_PHYS_PAGES")
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   400
        page_size = os.sysconf("SC_PAGE_SIZE")
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   401
        SERVER_DEFAULT_MEM_USE_KB = (phys_pages / 1024.0) * page_size / 3
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   402
        CLIENT_DEFAULT_MEM_USE_KB = SERVER_DEFAULT_MEM_USE_KB / 2.0
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   403
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   404
except:
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   405
        CLIENT_DEFAULT_MEM_USE_KB = 100
6c9cbb6e6600 983 pkg search returns just one action per package/token-type combo
Brock Pytlik <bpytlik@sun.com>
parents: 409
diff changeset
   406
        SERVER_DEFAULT_MEM_USE_KB = 500
461
37cf3ac75e37 1018 actions with payloads should include all sizes and hashes
johansen <johansen@sun.com>
parents: 451
diff changeset
   407