- Renamed private MediaManager::forceMediaRelease
[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         static bool setAttachPrefix(const Pathname &attach_prefix);
51
52     private:
53         /**
54          * User defined default attach point prefix.
55          */
56         static Pathname _attachPrefix;
57
58         /**
59          * The attached media source description reference.
60          */
61         mutable
62         MediaSourceRef  _mediaSource;
63
64         /**
65          * This is where the media will be actually attached ("mounted").
66          * All files are provided bellow this + _relativeRoot directory.
67          **/
68         AttachPointRef  _attachPoint;
69
70         /**
71          * The user provided attach preferred point. It may contain
72          * following values:
73          *
74          *      "",  true  => create temporary attach point bellow of
75          *                    _attachPrefix or a built-in default and
76          *                    remove it if not needed any more.
77          *
78          *      dir, false => user specified attach point (not removed)
79          */
80         AttachPoint     _AttachPointHint;
81
82         /**
83          * The relative root directory of the data on the media.
84          * See also localRoot() and urlpath_below_attachpoint_r
85          * constructor argument.
86          */
87         Pathname        _relativeRoot;
88
89         /**
90          * True if concrete handler downloads files to the local
91          * filesystem. If true releaseFile/Dir will delete them.
92          **/
93         bool            _does_download;
94
95         /** timestamp of the the last attach verification */
96         mutable time_t  _attach_mtime;
97
98     protected:
99         /**
100          * Url to handle
101          **/
102         const Url        _url;
103
104         /**
105          * Access Id of media handler we depend on.
106          */
107         MediaAccessId    _parentId;
108
109         /**
110          * MediaAccess (MediaManager) needs access to the attachedMedia()
111          * function to deliver a shared media source and its attach point
112          * to the media manager and then to other media handler instances.
113          * Further, is needs to be able to forward the dependsOnParent()
114          * and resetParentId() functions to the media manager.
115          */
116         friend class MediaAccess;
117
118         /**
119          * Check if the current media handler depends on an
120          * another handler specified by media access id.
121          * \param parentId The id of the parent handler to check against.
122          * \return true if it depends, false if not.
123          */
124         bool             dependsOnParent(MediaAccessId parentId,
125                                          bool exactIdMatch);
126         bool             dependsOnParent();
127
128         /**
129          * Called in case, where the media manager takes over the
130          * destruction of the parent id (e.g. while destruction
131          * of the media manager).
132          */
133         void             resetParentId();
134
135         /**
136          * Return the currently used attach point.
137          **/
138         Pathname         attachPoint() const;
139
140         /**
141          * Set a new attach point.
142          * \param path  The attach point directory path.
143          * \param temp  If to remove the attach point while cleanup.
144          */
145         void             setAttachPoint(const Pathname &path, bool temp);
146
147         /**
148          * Set a (shared) attach point.
149          * \param ref New attach point reference.
150          */
151         void             setAttachPoint(const AttachPointRef &ref);
152
153         /**
154          * Get the actual attach point hint.
155          */
156         AttachPoint      attachPointHint() const;
157
158         /**
159          * Set the attach point hint as specified by the user.
160          * \param path  The attach point directory path.
161          * \param temp  If to remove the attach point while cleanup.
162          */
163         void             attachPointHint(const Pathname &path, bool temp);
164
165         /**
166          * Try to create a default / temporary attach point.
167          * It trys to create it in attachPrefix if avaliable,
168          * then in built-in directories.
169          * \return The name of the new attach point or empty path name.
170          */
171         Pathname         createAttachPoint() const;
172         /**
173          * Try to create a temporary attach point in specified root.
174          * \param attach_root The attach root dir where to create the
175          *                    attach point in.
176          * \return The name of the new attach point or empty path name.
177          */
178         Pathname         createAttachPoint(const Pathname &attach_root) const;
179
180         /**
181          * Remove unused attach point. If the attach point is temporary,
182          * the attach point directory and all it content will be removed.
183          */
184         void             removeAttachPoint();
185
186         /**
187          * Verify if the specified directory as attach point (root)
188          * as requires by the particular media handler implementation.
189          * \param apoint The directory to check.
190          * \return True, if the directory checks succeeded.
191          */
192         virtual bool     checkAttachPoint(const Pathname &apoint) const;
193
194         /**
195          * Verify if the specified directory as attach point (root)
196          * using requested checks.
197          * \param apoint The directory to check.
198          * \param empty_dir Check if the directory is empty.
199          * \param writeable Check if the directory is writeable.
200          * \return True, if the directory checks succeeded.
201          */
202         static bool      checkAttachPoint(const Pathname &apoint,
203                                           bool            empty_dir,
204                                           bool            writeable);
205
206         /**
207          * Ask media manager, if the specified path is already used
208          * as attach point or if there are another attach points
209          * bellow of it.
210          * \param path The attach point path to check.
211          * \return True, if the path can be used as attach point.
212          */
213         bool             isUseableAttachPoint(const Pathname &path) const;
214
215         /**
216          * Get the media source name or an empty string.
217          * \return media source name or empty string.
218          */
219         std::string      mediaSourceName() const
220         {
221           return _mediaSource ? _mediaSource->name : "";
222         }
223
224         /**
225          * Set new media source reference.
226          * \param ref The new reference.
227          */
228         void             setMediaSource(const MediaSourceRef &ref);
229
230         /**
231          * Ask the media manager if specified media source
232          * is already attached.
233          */
234         AttachedMedia
235         findAttachedMedia(const MediaSourceRef &media) const;
236
237         /**
238          * Returns the attached media. Used by MediaManager
239          * to find other handlers using the same source.
240          * \note This function increments reference counters
241          *       on the mediaSource and attachPoint references
242          *       it contains, for the life time of the returned
243          *       object. That is, it enables a (temporary) sharing
244          *       of them.
245          * \return The AttachedMedia struct containing (shared)
246          *         references to media source and attach point.
247          */
248         AttachedMedia    attachedMedia() const;
249
250         /**
251          * Returns a hint if the media is shared or not.
252          * \return true, if media is shared.
253          */
254         bool             isSharedMedia() const;
255
256         /**
257          * Check actual mediaSource attachment against the current
258          * mount table of the system. Used to implement isAttached().
259          * \param matchMountFs If to use the filesystem type from the
260          *        mount table (nfs, smb and cifs) or from mediaSource
261          *        while compare of a mount entry with mediaSource.
262          * \return true, if the media appears in the mount table.
263          */
264         bool             checkAttached(bool matchMountFs) const;
265
266         /**
267          * Call to this function will try to release all media matching
268          * the currenlty attached media source, that it is able to find
269          * in the mount table. This means also foreign (user) mounts!
270          * \param matchMountFs If to use the filesystem type from the
271          *        mount table (nfs, smb and cifs) or from mediaSource
272          *        while compare of a mount entry with mediaSource.
273          */
274         void             forceRelaseAllMedia(bool matchMountFs);
275
276     protected:
277
278         ///////////////////////////////////////////////////////////////////
279         //
280         // Real action interface to be overloaded by concrete handler.
281         //
282         ///////////////////////////////////////////////////////////////////
283
284         /**
285          * Call concrete handler to attach the media.
286          *
287          * Asserted that not already attached, and attachPoint is a directory.
288          *
289          * @param next try next available device in turn until end of device
290          * list is reached (for media which are accessible through multiple
291          * devices like cdroms).
292          *
293          * \throws MediaException
294          *
295          **/
296         virtual void attachTo(bool next = false) = 0;
297
298         /**
299          * Call concrete handler to disconnect media.
300          *
301          * Asserted that media is attached.
302          *
303          * This is useful for media which e.g. holds open a connection to a
304          * server like FTP. After calling disconnect() the media object still is
305          * valid and files are present.
306          *
307          * After calling disconnect() it's not possible to call provideFile() or
308          * provideDir() anymore.
309          *
310          * \throws MediaException
311          *
312          **/
313         virtual void disconnectFrom() { return; }
314
315         /**
316          * Call concrete handler to release the media.
317          *
318          * If eject is true, and the media is used in one handler
319          * instance only, physically eject the media (i.e. CD-ROM).
320          *
321          * Asserted that media is attached.
322          *
323          * \throws MediaException
324          *
325          **/
326         virtual void releaseFrom( bool eject ) = 0;
327
328         /**
329          * Call concrete handler to physically eject the media (i.e. CD-ROM)
330          * in case the media is not attached..
331          *
332          * Asserted that media is not attached.
333          **/
334         virtual void forceEject() {}
335
336         /**
337          * Call concrete handler to provide file below attach point.
338          *
339          * Default implementation provided, that returns whether a file
340          * is located at 'localRoot + filename'.
341          *
342          * Asserted that media is attached.
343          *
344          * \throws MediaException
345          *
346          **/
347         virtual void getFile( const Pathname & filename ) const = 0;
348
349         /**
350          * Call concrete handler to provide a file under a different place
351          * in the file system (usually not under attach point) as a copy.
352          * Media must be attached before by callee.
353          *
354          * Default implementation provided that calls getFile(srcFilename)
355          * and copies the result around.
356          *
357          * \throws MediaException
358          *
359          **/
360         virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename ) const;
361
362
363         /**
364          * Call concrete handler to provide directory content (not recursive!)
365          * below attach point.
366          *
367          * Return E_not_supported_by_media if media does not support retrieval of
368          * directory content.
369          *
370          * Default implementation provided, that returns whether a directory
371          * is located at 'localRoot + dirname'.
372          *
373          * Asserted that media is attached.
374          *
375          * \throws MediaException
376          *
377          **/
378         virtual void getDir( const Pathname & dirname, bool recurse_r ) const = 0;
379
380         /**
381          * Call concrete handler to provide a content list of directory on media
382          * via retlist. If dots is false entries starting with '.' are not reported.
383          *
384          * Return E_not_supported_by_media if media does not support retrieval of
385          * directory content.
386          *
387          * Default implementation provided, that returns the content of a
388          * directory at 'localRoot + dirnname' retrieved via 'readdir'.
389          *
390          * Asserted that media is attached and retlist is empty.
391          *
392          * \throws MediaException
393          *
394          **/
395         virtual void getDirInfo( std::list<std::string> & retlist,
396                                  const Pathname & dirname, bool dots = true ) const = 0;
397
398         /**
399          * Basically the same as getDirInfo above. The content list is returned as
400          * filesystem::DirContent, which includes name and filetype of each directory
401          * entry. Retrieving the filetype usg. requires an additional ::stat call for
402          * each entry, thus it's more expensive than a simple readdir.
403          *
404          * Asserted that media is attached and retlist is empty.
405          *
406          * \throws MediaException
407          *
408          **/
409         virtual void getDirInfo( filesystem::DirContent & retlist,
410                                  const Pathname & dirname, bool dots = true ) const = 0;
411
412   protected:
413
414         /**
415          * Retrieve and if available scan dirname/directory.yast.
416          *
417          * Asserted that media is attached.
418          *
419          * \throws MediaException
420          *
421          **/
422         void getDirectoryYast( std::list<std::string> & retlist,
423                                const Pathname & dirname, bool dots = true ) const;
424
425         /**
426          * Retrieve and if available scan dirname/directory.yast.
427          *
428          * Asserted that media is attached.
429          *
430          * \throws MediaException
431          *
432          **/
433         void getDirectoryYast( filesystem::DirContent & retlist,
434                                const Pathname & dirname, bool dots = true ) const;
435
436   public:
437
438         /**
439          * If the concrete media handler provides a nonempty
440          * attach_point, it must be an existing directory.
441          *
442          * On an empty attach_point, MediaHandler will create
443          * a temporay directory, which will be erased from
444          * destructor.
445          *
446          * On any error, the attach_point is set to an empty Pathname,
447          * which should lead to E_bad_attachpoint.
448          **/
449         MediaHandler ( const Url&       url_r,
450                        const Pathname & attach_point_r,
451                        const Pathname & urlpath_below_attachpoint_r,
452                        const bool       does_download_r );
453
454         /**
455          * Contolling MediaAccess takes care, that attached media is released
456          * prior to deleting this.
457          **/
458         virtual ~MediaHandler();
459
460     public:
461
462
463         ///////////////////////////////////////////////////////////////////
464         //
465         // MediaAccess interface. Does common checks and logging.
466         // Invokes real action if necessary.
467         //
468         ///////////////////////////////////////////////////////////////////
469
470         /**
471          * Hint if files are downloaded or not.
472          */
473         bool        downloads() const { return _does_download; }
474
475         /**
476          * Protocol hint for MediaAccess.
477          **/
478         std::string protocol() const { return _url.getScheme(); }
479
480         /**
481          * Url used.
482          **/
483         Url url() const { return _url; }
484
485         /**
486          * Use concrete handler to attach the media.
487          *
488          * @param next try next available device in turn until end of device
489          * list is reached (for media which are accessible through multiple
490          * devices like cdroms).
491          *
492          * \throws MediaException
493          *
494          **/
495         void attach(bool next);
496
497         /**
498          * True if media is attached.
499          **/
500         virtual bool isAttached() const { return _mediaSource; }
501
502         /**
503          * Return the local directory that corresponds to medias url,
504          * no matter if media isAttached or not. Files requested will
505          * be available at 'localRoot() + filename' or better
506          * 'localPath( filename )'.
507          *
508          * Returns empty pathname if E_bad_attachpoint
509          **/
510         Pathname localRoot() const;
511
512         /**
513          * Files provided will be available at 'localPath(filename)'.
514          *
515          * Returns empty pathname if E_bad_attachpoint
516          **/
517          Pathname localPath( const Pathname & pathname ) const;
518
519         /**
520          * Use concrete handler to isconnect media.
521          *
522          * This is useful for media which e.g. holds open a connection to a
523          * server like FTP. After calling disconnect() the media object still is
524          * valid and files are present.
525          *
526          * After calling disconnect() it's not possible to call provideFile() or
527          * provideDir() anymore.
528          *
529          * \throws MediaException
530          *
531          **/
532         void disconnect();
533
534         /**
535          * Use concrete handler to release the media.
536          * @param eject if true, physically eject the media * (i.e. CD-ROM)
537          *
538          * \throws MediaException
539          *
540          **/
541         void release( bool eject = false );
542
543         /**
544          * Use concrete handler to provide file denoted by path below
545          * 'localRoot'. Filename is interpreted relative to the
546          * attached url and a path prefix is preserved.
547          *
548          * \throws MediaException
549          *
550          **/
551         void provideFile( Pathname filename ) const;
552
553         /**
554          * Call concrete handler to provide a copy of a file under a different place
555          * in the file system (usually not under attach point) as a copy.
556          * Media must be attached before by callee.
557          *
558          * @param srcFilename    Filename of source file on the media
559          * @param targetFilename Filename for the target in the file system
560          *
561          * \throws MediaException
562          *
563          **/
564         void provideFileCopy( Pathname srcFilename, Pathname targetFilename) const;
565
566         /**
567          * Use concrete handler to provide directory denoted
568          * by path below 'localRoot' (not recursive!).
569          * dirname is interpreted relative to the
570          * attached url and a path prefix is preserved.
571          *
572          * \throws MediaException
573          *
574          **/
575         void provideDir( Pathname dirname ) const;
576
577         /**
578          * Use concrete handler to provide directory tree denoted
579          * by path below 'localRoot' (recursive!!).
580          * dirname is interpreted relative to the
581          * attached url and a path prefix is preserved.
582          *
583          * \throws MediaException
584          *
585          **/
586         void provideDirTree( Pathname dirname ) const;
587
588         /**
589          * Remove filename below localRoot IFF handler downloads files
590          * to the local filesystem. Never remove anything from media.
591          *
592          * \throws MediaException
593          *
594          **/
595         void releaseFile( const Pathname & filename ) const { return releasePath( filename ); }
596
597         /**
598          * Remove directory tree below localRoot IFF handler downloads files
599          * to the local filesystem. Never remove anything from media.
600          *
601          * \throws MediaException
602          *
603          **/
604         void releaseDir( const Pathname & dirname ) const { return releasePath( dirname ); }
605
606         /**
607          * Remove pathname below localRoot IFF handler downloads files
608          * to the local filesystem. Never remove anything from media.
609          *
610          * If pathname denotes a directory it is recursively removed.
611          * If pathname is empty or '/' everything below the localRoot
612          * is recursively removed.
613          * If pathname denotes a file it is unlinked.
614          *
615          * \throws MediaException
616          *
617          **/
618         void releasePath( Pathname pathname ) const;
619
620     public:
621
622         /**
623          * Return content of directory on media via retlist. If dots is false
624          * entries starting with '.' are not reported.
625          *
626          * The request is forwarded to the concrete handler,
627          * which may atempt to retieve the content e.g. via 'readdir'
628          *
629          * <B>Caution:</B> This is not supported by all media types.
630          * Be prepared to handle E_not_supported_by_media.
631          *
632          * \throws MediaException
633          *
634          **/
635         void dirInfo( std::list<std::string> & retlist,
636                       const Pathname & dirname, bool dots = true ) const;
637
638         /**
639          * Basically the same as dirInfo above. The content is returned as
640          * filesystem::DirContent, which includes name and filetype of each directory
641          * entry. Retrieving the filetype usg. requires an additional ::stat call for
642          * each entry, thus it's more expensive than a simple readdir.
643          *
644          * <B>Caution:</B> This is not supported by all media types.
645          * Be prepared to handle E_not_supported_by_media.
646          *
647          * \throws MediaException
648          *
649          **/
650         void dirInfo( filesystem::DirContent & retlist,
651                       const Pathname & dirname, bool dots = true ) const;
652 };
653
654 ///////////////////////////////////////////////////////////////////
655
656 #define MEDIA_HANDLER_API                                               \
657     protected:                                                          \
658         virtual void attachTo (bool next = false);                      \
659         virtual void releaseFrom( bool eject );                 \
660         virtual void getFile( const Pathname & filename ) const;        \
661         virtual void getDir( const Pathname & dirname, bool recurse_r ) const;  \
662         virtual void getDirInfo( std::list<std::string> & retlist,      \
663                                     const Pathname & dirname, bool dots = true ) const; \
664         virtual void getDirInfo( filesystem::DirContent & retlist,      \
665                                     const Pathname & dirname, bool dots = true ) const;
666
667   } // namespace media
668 } // namespace zypp
669
670
671 #endif // ZYPP_MEDIA_MEDIAHANDLERL_H
672
673