0
# Mount and Access
1
2
Mounting archives as filesystems for browsing and selective file restoration, providing direct access to backup contents without full extraction.
3
4
```python
5
import subprocess
6
import os
7
```
8
9
## Capabilities
10
11
### Archive Mounting
12
13
Mount archives as read-only filesystems for browsing and selective file access.
14
15
```python { .api }
16
def mount_archive(repo_path: str, mount_point: str, archive_name: str = None,
17
foreground: bool = False, numeric_owner: bool = False,
18
strip_components: int = None, **options) -> None:
19
"""
20
Mount archive as filesystem.
21
22
Args:
23
repo_path: Path to repository
24
mount_point: Directory to mount at
25
archive_name: Specific archive to mount (optional, mounts all if not specified)
26
foreground: Run in foreground (default: background daemon)
27
numeric_owner: Show numeric user/group IDs
28
strip_components: Strip N leading path components
29
**options: Additional options like first, last, glob_archives
30
"""
31
cmd = ['borg', 'mount']
32
if foreground:
33
cmd.append('--foreground')
34
if numeric_owner:
35
cmd.append('--numeric-owner')
36
if strip_components:
37
cmd.extend(['--strip-components', str(strip_components)])
38
if options.get('first'):
39
cmd.extend(['--first', str(options['first'])])
40
if options.get('last'):
41
cmd.extend(['--last', str(options['last'])])
42
if options.get('glob_archives'):
43
cmd.extend(['--glob-archives', options['glob_archives']])
44
45
if archive_name:
46
cmd.append(f'{repo_path}::{archive_name}')
47
else:
48
cmd.append(repo_path)
49
cmd.append(mount_point)
50
51
subprocess.run(cmd, check=True)
52
53
def unmount_archive(mount_point: str) -> None:
54
"""
55
Unmount archive filesystem.
56
57
Args:
58
mount_point: Directory to unmount
59
"""
60
cmd = ['borg', 'umount', mount_point]
61
subprocess.run(cmd, check=True)
62
```
63
64
Usage example:
65
```python
66
import subprocess
67
import os
68
69
# Create mount point
70
os.makedirs('/mnt/backup', exist_ok=True)
71
72
# Mount specific archive
73
subprocess.run([
74
'borg', 'mount', '/backup/repo::documents-2023-12-01', '/mnt/backup'
75
], check=True)
76
77
# Browse mounted archive (now you can use regular file operations)
78
# files = os.listdir('/mnt/backup')
79
# with open('/mnt/backup/home/user/important.txt', 'r') as f:
80
# content = f.read()
81
82
# Unmount when done
83
subprocess.run(['borg', 'umount', '/mnt/backup'], check=True)
84
85
# Mount all archives (creates subdirectories for each archive)
86
subprocess.run(['borg', 'mount', '/backup/repo', '/mnt/all-backups'], check=True)
87
```
88
89
### FUSE Filesystem Features
90
91
Access mounted archives with full filesystem features including browsing, copying, and searching.
92
93
```python { .api }
94
def mount_with_options(repo_path: str, mount_point: str,
95
archive_pattern: str = None, versions_view: bool = False,
96
allow_damaged_files: bool = False) -> None:
97
"""
98
Mount with advanced FUSE options.
99
100
Args:
101
repo_path: Path to repository
102
mount_point: Directory to mount at
103
archive_pattern: Glob pattern for archive selection
104
versions_view: Enable versions view (shows all versions of files)
105
allow_damaged_files: Allow access to damaged files
106
"""
107
cmd = ['borg', 'mount']
108
if archive_pattern:
109
cmd.extend(['--glob-archives', archive_pattern])
110
if versions_view:
111
cmd.append('--versions-view')
112
if allow_damaged_files:
113
cmd.append('--consider-damaged-chunks')
114
115
cmd.extend([repo_path, mount_point])
116
subprocess.run(cmd, check=True)
117
```
118
119
Usage example:
120
```python
121
import subprocess
122
import os
123
import shutil
124
125
# Mount with pattern matching
126
subprocess.run([
127
'borg', 'mount', '--glob-archives=documents-*',
128
'/backup/repo', '/mnt/documents'
129
], check=True)
130
131
# Copy specific files from mounted archive
132
source_path = '/mnt/documents/documents-2023-12-01/home/user/important.txt'
133
if os.path.exists(source_path):
134
shutil.copy2(source_path, '/restore/important.txt')
135
136
# Search for files in mounted archive
137
def find_files(mount_path, pattern):
138
"""Find files matching pattern in mounted archive"""
139
matches = []
140
for root, dirs, files in os.walk(mount_path):
141
for file in files:
142
if pattern in file:
143
matches.append(os.path.join(root, file))
144
return matches
145
146
# Find all PDF files
147
pdf_files = find_files('/mnt/documents', '.pdf')
148
149
# Unmount
150
subprocess.run(['borg', 'umount', '/mnt/documents'], check=True)
151
```
152
153
### Repository Web Interface
154
155
Serve repository contents via HTTP for web-based browsing (if borg-web or similar tools are available).
156
157
```python { .api }
158
def serve_web_interface(repo_path: str, host: str = '127.0.0.1',
159
port: int = 8080, readonly: bool = True) -> None:
160
"""
161
Serve repository via web interface (requires additional tools).
162
163
Args:
164
repo_path: Path to repository
165
host: Host interface to bind to
166
port: Port to serve on
167
readonly: Serve in read-only mode
168
169
Note: This requires additional tools like borg-web or borgmatic-web
170
"""
171
# This is a conceptual example - actual implementation depends on web interface tool
172
cmd = ['borg-web', '--repo', repo_path, '--host', host, '--port', str(port)]
173
if readonly:
174
cmd.append('--readonly')
175
subprocess.run(cmd, check=True)
176
```
177
178
### Archive Browsing Utilities
179
180
Utility functions for programmatically browsing mounted archives.
181
182
```python { .api }
183
def browse_archive(mount_point: str, callback_func = None) -> dict:
184
"""
185
Programmatically browse mounted archive contents.
186
187
Args:
188
mount_point: Path to mounted archive
189
callback_func: Optional callback for each file/directory
190
191
Returns:
192
Dictionary with archive structure and file information
193
"""
194
archive_contents = {}
195
196
for root, dirs, files in os.walk(mount_point):
197
rel_root = os.path.relpath(root, mount_point)
198
archive_contents[rel_root] = {
199
'directories': dirs,
200
'files': []
201
}
202
203
for file in files:
204
file_path = os.path.join(root, file)
205
try:
206
stat = os.stat(file_path)
207
file_info = {
208
'name': file,
209
'size': stat.st_size,
210
'mtime': stat.st_mtime,
211
'mode': stat.st_mode
212
}
213
archive_contents[rel_root]['files'].append(file_info)
214
215
if callback_func:
216
callback_func(file_path, file_info)
217
except OSError:
218
# Handle potential issues with damaged files
219
pass
220
221
return archive_contents
222
223
def extract_files_from_mount(mount_point: str, file_patterns: list,
224
destination: str) -> list:
225
"""
226
Extract specific files from mounted archive.
227
228
Args:
229
mount_point: Path to mounted archive
230
file_patterns: List of file patterns to extract
231
destination: Destination directory for extracted files
232
233
Returns:
234
List of successfully extracted file paths
235
"""
236
import fnmatch
237
import shutil
238
239
extracted_files = []
240
os.makedirs(destination, exist_ok=True)
241
242
for root, dirs, files in os.walk(mount_point):
243
for file in files:
244
file_path = os.path.join(root, file)
245
rel_path = os.path.relpath(file_path, mount_point)
246
247
# Check if file matches any pattern
248
for pattern in file_patterns:
249
if fnmatch.fnmatch(rel_path, pattern) or fnmatch.fnmatch(file, pattern):
250
dest_path = os.path.join(destination, rel_path)
251
dest_dir = os.path.dirname(dest_path)
252
os.makedirs(dest_dir, exist_ok=True)
253
254
try:
255
shutil.copy2(file_path, dest_path)
256
extracted_files.append(dest_path)
257
except OSError as e:
258
print(f"Failed to extract {rel_path}: {e}")
259
break
260
261
return extracted_files
262
```
263
264
Usage example:
265
```python
266
import subprocess
267
import os
268
269
# Mount archive
270
subprocess.run(['borg', 'mount', '/backup/repo::backup-2023-12-01', '/mnt/backup'], check=True)
271
272
try:
273
# Browse archive contents
274
def file_callback(path, info):
275
if info['size'] > 1000000: # Files larger than 1MB
276
print(f"Large file: {path} ({info['size']} bytes)")
277
278
contents = browse_archive('/mnt/backup', file_callback)
279
280
# Extract specific file types
281
extracted = extract_files_from_mount('/mnt/backup', ['*.pdf', '*.doc*'], '/restore/documents')
282
print(f"Extracted {len(extracted)} files")
283
284
finally:
285
# Always unmount
286
subprocess.run(['borg', 'umount', '/mnt/backup'], check=True)
287
```
288
289
## Types
290
291
```python { .api }
292
class MountOptions:
293
"""Mount operation options"""
294
def __init__(self):
295
self.repository: str # Repository path
296
self.archive: str # Archive name (optional)
297
self.mount_point: str # Mount point directory
298
self.foreground: bool # Run in foreground
299
self.numeric_owner: bool # Show numeric IDs
300
self.strip_components: int # Strip path components
301
302
class FileInfo:
303
"""File information from mounted archive"""
304
def __init__(self):
305
self.name: str # File name
306
self.path: str # Full path
307
self.size: int # File size in bytes
308
self.mtime: float # Modification time (timestamp)
309
self.mode: int # File mode/permissions
310
self.is_directory: bool # Is directory flag
311
312
class ArchiveStructure:
313
"""Archive directory structure"""
314
def __init__(self):
315
self.directories: dict # Directory tree structure
316
self.files: list # List of all files
317
self.total_size: int # Total size of all files
318
self.file_count: int # Total number of files
319
self.directory_count: int # Total number of directories
320
```