1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006, 2007, 2008 Guillaume Chazarain <guichaz@gmail.com>
22 from pysize
.core
.browsing
import browsedir
23 from pysize
.core
.observable
import observable
24 from pysize
.core
.pysize_global_fs_cache
import get_dev_ino
, cache_add_dir
25 from pysize
.core
.pysize_global_fs_cache
import cache_add_hardlink
26 from pysize
.core
.pysize_global_fs_cache
import cache_get_dir_size
27 from pysize
.core
.deletion
import get_deletion_info
, DELETED
28 from pysize
.core
.exception_propagation
import catches
30 size_observable
= observable()
32 def log_error(text
, e
):
36 def _fast(fullpath
, cross_device
, error_cb
):
37 """Return the size of the file or directory at path, using or updating the
40 assert fullpath
[0] == '/', fullpath
42 size_observable
.fire_observers()
43 st
= os
.lstat(fullpath
)
44 if stat
.S_ISDIR(st
.st_mode
): # Directory
45 dev_ino
= st
.st_dev
, st
.st_ino
46 cached_size
= cache_get_dir_size(dev_ino
)
47 if cached_size
is not None:
49 size
= st
.st_blocks
* 512
50 for child
in browsedir(fullpath
, cross_device
,
51 account_deletion
=False):
52 size
+= _fast(child
, cross_device
, error_cb
)
53 cache_add_dir(dev_ino
, size
)
55 if st
.st_nlink
> 1: # Hardlink
56 dir_ino
= get_dev_ino(os
.path
.dirname(fullpath
))[1]
57 if cache_add_hardlink(st
.st_dev
, st
.st_ino
, dir_ino
, fullpath
):
58 return st
.st_blocks
* 512
60 # Otherwise, it's a regular file
61 return st
.st_blocks
* 512
63 error_cb('size(%s)' % (fullpath
), e
)
66 def slow(fullpath
, cross_device
=True, error_cb
=log_error
,
67 account_deletion
=True):
68 """Same as _size_fast(path, ...), except that deletion can be
70 size
= _fast(fullpath
, cross_device
, error_cb
)
72 deletion_info
= get_deletion_info(fullpath
)
73 if deletion_info
is DELETED
:
79 def slow_sum(fullpaths
, cross_device
=True, error_cb
=log_error
,
80 account_deletion
=True):
83 res
+= slow(p
, cross_device
, error_cb
, account_deletion
)