blob: d5410d64d8e6a0af24508da30345222c07e82377 [file] [log] [blame]
apatrick@chromium.org1218a882010-07-29 08:02:22 +09001#!/usr/bin/env python
maruel@chromium.org1f144a32011-11-24 04:13:44 +09002# Copyright (c) 2011 The Chromium Authors. All rights reserved.
apatrick@chromium.org1218a882010-07-29 08:02:22 +09003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
maruel@chromium.org1f144a32011-11-24 04:13:44 +09006"""Extracts a single file from a CAB archive."""
apatrick@chromium.org1218a882010-07-29 08:02:22 +09007
8import os
grt@chromium.org509c7542011-12-14 07:20:46 +09009import shutil
apatrick@chromium.org1218a882010-07-29 08:02:22 +090010import subprocess
11import sys
apatrick@chromium.org38ff3d22011-12-13 09:34:15 +090012import tempfile
apatrick@chromium.org1218a882010-07-29 08:02:22 +090013
apatrick@chromium.org3faf3c82011-12-13 12:32:12 +090014
maruel@chromium.org1f144a32011-11-24 04:13:44 +090015def main():
16 if len(sys.argv) != 4:
17 print 'Usage: extract_from_cab.py cab_path archived_file output_dir'
18 return 1
apatrick@chromium.org1218a882010-07-29 08:02:22 +090019
maruel@chromium.org1f144a32011-11-24 04:13:44 +090020 [cab_path, archived_file, output_dir] = sys.argv[1:]
apatrick@chromium.org1218a882010-07-29 08:02:22 +090021
grt@chromium.org509c7542011-12-14 07:20:46 +090022 # Expand.exe does its work in a fixed-named temporary directory created within
23 # the given output directory. This is a problem for concurrent extractions, so
24 # create a unique temp dir within the desired output directory to work around
25 # this limitation.
26 temp_dir = tempfile.mkdtemp(dir=output_dir)
27
apatrick@chromium.org38ff3d22011-12-13 09:34:15 +090028 try:
29 # Invoke the Windows expand utility to extract the file.
maruel@chromium.orgc04ced42011-12-09 05:47:15 +090030 level = subprocess.call(
grt@chromium.org509c7542011-12-14 07:20:46 +090031 ['expand', cab_path, '-F:' + archived_file, temp_dir])
32 if level == 0:
33 # Move the output file into place, preserving expand.exe's behavior of
34 # paving over any preexisting file.
35 output_file = os.path.join(output_dir, archived_file)
36 try:
37 os.remove(output_file)
38 except OSError:
39 pass
40 os.rename(os.path.join(temp_dir, archived_file), output_file)
apatrick@chromium.org38ff3d22011-12-13 09:34:15 +090041 finally:
grt@chromium.org509c7542011-12-14 07:20:46 +090042 shutil.rmtree(temp_dir, True)
43
44 if level != 0:
45 return level
maruel@chromium.org1f144a32011-11-24 04:13:44 +090046
47 # The expand utility preserves the modification date and time of the archived
48 # file. Touch the extracted file. This helps build systems that compare the
49 # modification times of input and output files to determine whether to do an
50 # action.
51 os.utime(os.path.join(output_dir, archived_file), None)
52 return 0
53
54
55if __name__ == '__main__':
56 sys.exit(main())