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