]> git.decadent.org.uk Git - dak.git/blob - daklib/holding.py
Merge commit 'ftpmaster/master' into sqlalchemy
[dak.git] / daklib / holding.py
1 #!/usr/bin/env python
2 # vim:set et sw=4:
3
4 """
5 Simple singleton class for storing info about Holding directory
6
7 @contact: Debian FTP Master <ftpmaster@debian.org>
8 @copyright: 2001 - 2006 James Troup <james@nocrew.org>
9 @copyright: 2009  Joerg Jaspert <joerg@debian.org>
10 @license: GNU General Public License version 2 or later
11 """
12
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation; either version 2 of the License, or
16 # (at your option) any later version.
17
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 # GNU General Public License for more details.
22
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
27 ###############################################################################
28
29 import os
30 from errno import ENOENT, EEXIST, EACCES
31 import shutil
32
33 from singleton import Singleton
34 from config import Config
35 from utils import fubar
36
37 ###############################################################################
38
39 class Holding(Singleton):
40     def __init__(self, *args, **kwargs):
41         super(Holding, self).__init__(*args, **kwargs)
42
43     def _startup(self):
44         self.in_holding = {}
45         self.holding_dir = Config()["Dir::Queue::Holding"]
46
47     def copy_to_holding(self, filename):
48         base_filename = os.path.basename(filename)
49
50         dest = os.path.join(self.holding_dir, base_filename)
51         try:
52             fd = os.open(dest, os.O_RDWR | os.O_CREAT | os.O_EXCL, 0640)
53             os.close(fd)
54         except OSError, e:
55             # Shouldn't happen, but will if, for example, someone lists a
56             # file twice in the .changes.
57             if e.errno == EEXIST:
58                 return "%s: already exists in holding area; can not overwrite." % (base_filename)
59
60         try:
61             shutil.copy(filename, dest)
62         except IOError, e:
63             # In either case (ENOENT or EACCES) we want to remove the
64             # O_CREAT | O_EXCLed ghost file, so add the file to the list
65             # of 'in holding' even if it's not the real file.
66             if e.errno == ENOENT:
67                 os.unlink(dest)
68                 return "%s: can not copy to holding area: file not found." % (base_filename)
69
70             elif e.errno == EACCES:
71                 os.unlink(dest)
72                 return "%s: can not copy to holding area: read permission denied." % (base_filename)
73
74         self.in_holding[base_filename] = ""
75
76         return None
77
78     def clean(self):
79         cwd = os.getcwd()
80         os.chdir(self.holding_dir)
81         for f in self.in_holding.keys():
82             # TODO: Sanitize path in a much better manner...
83             if os.path.exists(f):
84                 if f.find('/') != -1:
85                     fubar("WTF? clean_holding() got a file ('%s') with / in it!" % (f))
86                 else:
87                     os.unlink(f)
88         self.in_holding = {}
89         os.chdir(cwd)
90