- Enabled source sharing for DISK, NFS, SMB
[platform/upstream/libzypp.git] / zypp / media / MediaHandler.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaHandler.h
10  *
11 */
12 #ifndef ZYPP_MEDIA_MEDIAHANDLERL_H
13 #define ZYPP_MEDIA_MEDIAHANDLERL_H
14
15 #include <iosfwd>
16 #include <string>
17 #include <list>
18
19 #include "zypp/Pathname.h"
20 #include "zypp/PathInfo.h"
21 #include "zypp/base/PtrTypes.h"
22
23 #include "zypp/Url.h"
24
25 #include "zypp/media/MediaSource.h"
26 #include "zypp/media/MediaException.h"
27
28 namespace zypp {
29   namespace media {
30
31
32 ///////////////////////////////////////////////////////////////////
33 //
34 //      CLASS NAME : MediaHandler
35 /**
36  * @short Abstract base class for 'physical' MediaHandler like MediaCD, etc.
37  *
38  * Handles the requests forwarded by @ref MediaAccess. The public interface
39  * contains nonvirtual methods, which should do common sanitychecks and
40  * logging. For the real action they call virtual methods overloaded by the
41  * concrete handler.
42  **/
43 class MediaHandler {
44     friend std::ostream & operator<<( std::ostream & str, const MediaHandler & obj );
45
46     public:
47         typedef shared_ptr<MediaHandler> Ptr;
48         typedef shared_ptr<const MediaHandler> constPtr;
49
50     private:
51         /**
52          * MediaAccess (MediaManager) needs access to the
53          * attachedMedia() function to deliver a shared
54          * media source and its attach point to other
55          * media handler instances.
56          */
57         friend class MediaAccess;
58
59         /**
60          * The attached media source.
61          */
62         MediaSourceRef _mediaSource;
63
64         /**
65          * Returns the attached media. Used by MediaManager
66          * to find other handlers using the same source.
67          */
68         AttachedMedia        attachedMedia() const;
69
70         /**
71          * this is where the media will be actually "mounted"
72          * all files are provided 'below' this directory.
73          **/
74         AttachPointRef _attachPoint;
75
76         /**
77          * The relative root directory of the data on the media.
78          * See also _localRoot and urlpath_below_attachpoint_r
79          * constructor argument.
80          */
81         Pathname _relativeRoot;
82
83         /**
84          * The local directory that corresponds to the media url.
85          * With NFS it's the '_attachPoint', as the directory on the
86          * server is mounted. With CD/DVD it's 'attach point+_relativeRoot'
87          * because the CDs root directory is mounted. And with CIFS
88          * it's '_url.path() without the shares name'.
89          **/
90         Pathname _localRoot;
91
92         /**
93          * True if concrete handler downloads files to the local
94          * filesystem. If true releaseFile/Dir will delete them.
95          **/
96         bool _does_download;
97
98     protected:
99         /**
100          * Url to handle
101          **/
102         const Url _url;
103
104         /**
105          * Return the currently used attach point.
106          **/
107         Pathname         attachPoint() const;
108
109         /**
110          * Set a new attach point and update localRoot.
111          */
112         void             setAttachPoint(const Pathname &path, bool _temporary);
113
114         /**
115          * Set a (shared) attach point and update localRoot.
116          */
117         void             setAttachPoint(const AttachPointRef &ref);
118
119         /**
120          * Try to create a default / temporary attach point.
121          * \return The name of the new attach point or empty path name.
122          */
123         Pathname         createAttachPoint() const;
124
125         /**
126          * Remove unused attach point.
127          */
128         void             removeAttachPoint();
129
130         std::string      mediaSourceName() const
131         {
132           return _mediaSource ? _mediaSource->name : "";
133         }
134
135         void             setMediaSource(const MediaSourceRef &ref);
136
137         /**
138          * Ask the media manager if specified media source
139          * is already attached.
140          */
141         AttachedMedia
142         findAttachedMedia(const MediaSourceRef &media) const;
143
144     protected:
145
146         ///////////////////////////////////////////////////////////////////
147         //
148         // Real action interface to be overloaded by concrete handler.
149         //
150         ///////////////////////////////////////////////////////////////////
151
152         /**
153          * Call concrete handler to attach the media.
154          *
155          * Asserted that not already attached, and attachPoint is a directory.
156          *
157          * @param next try next available device in turn until end of device
158          * list is reached (for media which are accessible through multiple
159          * devices like cdroms).
160          *
161          * \throws MediaException
162          *
163          **/
164         virtual void attachTo(bool next = false) = 0;
165
166         /**
167          * Call concrete handler to disconnect media.
168          *
169          * Asserted that media is attached.
170          *
171          * This is useful for media which e.g. holds open a connection to a
172          * server like FTP. After calling disconnect() the media object still is
173          * valid and files are present.
174          *
175          * After calling disconnect() it's not possible to call provideFile() or
176          * provideDir() anymore.
177          *
178          * \throws MediaException
179          *
180          **/
181         virtual void disconnectFrom() { return; }
182
183         /**
184          * Call concrete handler to release the media.
185          *
186          * If eject is true, and the media is used in one handler
187          * instance only, physically eject the media (i.e. CD-ROM).
188          *
189          * Asserted that media is attached.
190          *
191          * \throws MediaException
192          *
193          **/
194         virtual void releaseFrom( bool eject ) = 0;
195
196         /**
197          * Call concrete handler to physically eject the media (i.e. CD-ROM)
198          * in case the media is not attached..
199          *
200          * Asserted that media is not attached.
201          **/
202         virtual void forceEject() {}
203
204         /**
205          * Call concrete handler to provide file below attach point.
206          *
207          * Default implementation provided, that returns whether a file
208          * is located at '_localRoot + filename'.
209          *
210          * Asserted that media is attached.
211          *
212          * \throws MediaException
213          *
214          **/
215         virtual void getFile( const Pathname & filename ) const = 0;
216
217         /**
218          * Call concrete handler to provide a file under a different place
219          * in the file system (usually not under attach point) as a copy.
220          * Media must be attached before by callee.
221          *
222          * Default implementation provided that calls getFile(srcFilename)
223          * and copies the result around.
224          *
225          * \throws MediaException
226          *
227          **/
228         virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename ) const;
229
230
231         /**
232          * Call concrete handler to provide directory content (not recursive!)
233          * below attach point.
234          *
235          * Return E_not_supported_by_media if media does not support retrieval of
236          * directory content.
237          *
238          * Default implementation provided, that returns whether a directory
239          * is located at '_localRoot + dirname'.
240          *
241          * Asserted that media is attached.
242          *
243          * \throws MediaException
244          *
245          **/
246         virtual void getDir( const Pathname & dirname, bool recurse_r ) const = 0;
247
248         /**
249          * Call concrete handler to provide a content list of directory on media
250          * via retlist. If dots is false entries starting with '.' are not reported.
251          *
252          * Return E_not_supported_by_media if media does not support retrieval of
253          * directory content.
254          *
255          * Default implementation provided, that returns the content of a
256          * directory at '_localRoot + dirnname' retrieved via 'readdir'.
257          *
258          * Asserted that media is attached and retlist is empty.
259          *
260          * \throws MediaException
261          *
262          **/
263         virtual void getDirInfo( std::list<std::string> & retlist,
264                                  const Pathname & dirname, bool dots = true ) const = 0;
265
266         /**
267          * Basically the same as getDirInfo above. The content list is returned as
268          * filesystem::DirContent, which includes name and filetype of each directory
269          * entry. Retrieving the filetype usg. requires an additional ::stat call for
270          * each entry, thus it's more expensive than a simple readdir.
271          *
272          * Asserted that media is attached and retlist is empty.
273          *
274          * \throws MediaException
275          *
276          **/
277         virtual void getDirInfo( filesystem::DirContent & retlist,
278                                  const Pathname & dirname, bool dots = true ) const = 0;
279
280   protected:
281
282         /**
283          * Retrieve and if available scan dirname/directory.yast.
284          *
285          * Asserted that media is attached.
286          *
287          * \throws MediaException
288          *
289          **/
290         void getDirectoryYast( std::list<std::string> & retlist,
291                                const Pathname & dirname, bool dots = true ) const;
292
293         /**
294          * Retrieve and if available scan dirname/directory.yast.
295          *
296          * Asserted that media is attached.
297          *
298          * \throws MediaException
299          *
300          **/
301         void getDirectoryYast( filesystem::DirContent & retlist,
302                                const Pathname & dirname, bool dots = true ) const;
303
304   public:
305
306         /**
307          * If the concrete media handler provides a nonempty
308          * attach_point, it must be an existing directory.
309          *
310          * On an empty attach_point, MediaHandler will create
311          * a temporay directory, which will be erased from
312          * destructor.
313          *
314          * On any error, the attach_point is set to an empty Pathname,
315          * which should lead to E_bad_attachpoint.
316          **/
317         MediaHandler ( const Url&       url_r,
318                        const Pathname & attach_point_r,
319                        const Pathname & urlpath_below_attachpoint_r,
320                        const bool       does_download_r );
321
322         /**
323          * Contolling MediaAccess takes care, that attached media is released
324          * prior to deleting this.
325          **/
326         virtual ~MediaHandler();
327
328     public:
329
330
331         ///////////////////////////////////////////////////////////////////
332         //
333         // MediaAccess interface. Does common checks and logging.
334         // Invokes real action if necessary.
335         //
336         ///////////////////////////////////////////////////////////////////
337
338         /**
339          * Protocol hint for MediaAccess.
340          **/
341         std::string protocol() const { return _url.getScheme(); }
342
343         /**
344          * Url used.
345          **/
346         Url url() const { return _url; }
347
348         /**
349          * Use concrete handler to attach the media.
350          *
351          * @param next try next available device in turn until end of device
352          * list is reached (for media which are accessible through multiple
353          * devices like cdroms).
354          *
355          * \throws MediaException
356          *
357          **/
358         void attach(bool next);
359
360         /**
361          * True if media is attached.
362          **/
363         bool isAttached() const { return _mediaSource; }
364
365         /**
366          * Return the local directory that corresponds to medias url,
367          * no matter if media isAttached or not. Files requested will
368          * be available at 'localRoot() + filename' or better
369          * 'localPath( filename )'.
370          *
371          * Returns empty pathname if E_bad_attachpoint
372          **/
373         const Pathname & localRoot() const { return _localRoot; }
374
375         /**
376          * Files provided will be available at 'localPath(filename)'.
377          *
378          * Returns empty pathname if E_bad_attachpoint
379          **/
380          Pathname localPath( const Pathname & pathname ) const;
381
382         /**
383          * Use concrete handler to isconnect media.
384          *
385          * This is useful for media which e.g. holds open a connection to a
386          * server like FTP. After calling disconnect() the media object still is
387          * valid and files are present.
388          *
389          * After calling disconnect() it's not possible to call provideFile() or
390          * provideDir() anymore.
391          *
392          * \throws MediaException
393          *
394          **/
395         void disconnect();
396
397         /**
398          * Use concrete handler to release the media.
399          * @param eject if true, physically eject the media * (i.e. CD-ROM)
400          *
401          * \throws MediaException
402          *
403          **/
404         void release( bool eject = false );
405
406         /**
407          * Use concrete handler to provide file denoted by path below
408          * 'localRoot'. Filename is interpreted relative to the
409          * attached url and a path prefix is preserved.
410          *
411          * \throws MediaException
412          *
413          **/
414         void provideFile( Pathname filename ) const;
415
416         /**
417          * Call concrete handler to provide a copy of a file under a different place
418          * in the file system (usually not under attach point) as a copy.
419          * Media must be attached before by callee.
420          *
421          * @param srcFilename    Filename of source file on the media
422          * @param targetFilename Filename for the target in the file system
423          *
424          * \throws MediaException
425          *
426          **/
427         void provideFileCopy( Pathname srcFilename, Pathname targetFilename) const;
428
429         /**
430          * Use concrete handler to provide directory denoted
431          * by path below 'localRoot' (not recursive!).
432          * dirname is interpreted relative to the
433          * attached url and a path prefix is preserved.
434          *
435          * \throws MediaException
436          *
437          **/
438         void provideDir( Pathname dirname ) const;
439
440         /**
441          * Use concrete handler to provide directory tree denoted
442          * by path below 'localRoot' (recursive!!).
443          * dirname is interpreted relative to the
444          * attached url and a path prefix is preserved.
445          *
446          * \throws MediaException
447          *
448          **/
449         void provideDirTree( Pathname dirname ) const;
450
451         /**
452          * Remove filename below localRoot IFF handler downloads files
453          * to the local filesystem. Never remove anything from media.
454          *
455          * \throws MediaException
456          *
457          **/
458         void releaseFile( const Pathname & filename ) const { return releasePath( filename ); }
459
460         /**
461          * Remove directory tree below localRoot IFF handler downloads files
462          * to the local filesystem. Never remove anything from media.
463          *
464          * \throws MediaException
465          *
466          **/
467         void releaseDir( const Pathname & dirname ) const { return releasePath( dirname ); }
468
469         /**
470          * Remove pathname below localRoot IFF handler downloads files
471          * to the local filesystem. Never remove anything from media.
472          *
473          * If pathname denotes a directory it is recursively removed.
474          * If pathname is empty or '/' everything below the localRoot
475          * is recursively removed.
476          * If pathname denotes a file it is unlinked.
477          *
478          * \throws MediaException
479          *
480          **/
481         void releasePath( Pathname pathname ) const;
482
483     public:
484
485         /**
486          * Return content of directory on media via retlist. If dots is false
487          * entries starting with '.' are not reported.
488          *
489          * The request is forwarded to the concrete handler,
490          * which may atempt to retieve the content e.g. via 'readdir'
491          *
492          * <B>Caution:</B> This is not supported by all media types.
493          * Be prepared to handle E_not_supported_by_media.
494          *
495          * \throws MediaException
496          *
497          **/
498         void dirInfo( std::list<std::string> & retlist,
499                       const Pathname & dirname, bool dots = true ) const;
500
501         /**
502          * Basically the same as dirInfo above. The content is returned as
503          * filesystem::DirContent, which includes name and filetype of each directory
504          * entry. Retrieving the filetype usg. requires an additional ::stat call for
505          * each entry, thus it's more expensive than a simple readdir.
506          *
507          * <B>Caution:</B> This is not supported by all media types.
508          * Be prepared to handle E_not_supported_by_media.
509          *
510          * \throws MediaException
511          *
512          **/
513         void dirInfo( filesystem::DirContent & retlist,
514                       const Pathname & dirname, bool dots = true ) const;
515 };
516
517 ///////////////////////////////////////////////////////////////////
518
519 #define MEDIA_HANDLER_API                                               \
520     protected:                                                          \
521         virtual void attachTo (bool next = false);                      \
522         virtual void releaseFrom( bool eject );                 \
523         virtual void getFile( const Pathname & filename ) const;        \
524         virtual void getDir( const Pathname & dirname, bool recurse_r ) const;  \
525         virtual void getDirInfo( std::list<std::string> & retlist,      \
526                                     const Pathname & dirname, bool dots = true ) const; \
527         virtual void getDirInfo( filesystem::DirContent & retlist,      \
528                                     const Pathname & dirname, bool dots = true ) const;
529
530   } // namespace media
531 } // namespace zypp
532
533
534 #endif // ZYPP_MEDIA_MEDIAHANDLERL_H
535
536