Imported Upstream version 16.3.2
[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 tries to create it in attachPrefix if avaliable,
176          * then in built-in directories.
177          * \throws MediaBadAttachPointException if no attach point can be created
178          * \return The name of the new attach point
179          */
180         Pathname         createAttachPoint() const;
181         /**
182          * Try to create a temporary attach point in specified root.
183          * \param attach_root The attach root dir where to create the
184          *                    attach point in.
185          * \return The name of the new attach point or empty path name.
186          */
187         Pathname         createAttachPoint(const Pathname &attach_root) const;
188
189         /**
190          * Remove unused attach point. If the attach point is temporary,
191          * the attach point directory and all it content will be removed.
192          */
193         void             removeAttachPoint();
194
195         /**
196          * Verify if the specified directory as attach point (root)
197          * as requires by the particular media handler implementation.
198          * \param apoint The directory to check.
199          * \return True, if the directory checks succeeded.
200          */
201         virtual bool     checkAttachPoint(const Pathname &apoint) const;
202
203         /**
204          * Verify if the specified directory as attach point (root)
205          * using requested checks.
206          * \param apoint The directory to check.
207          * \param empty_dir Check if the directory is empty.
208          * \param writeable Check if the directory is writeable.
209          * \return True, if the directory checks succeeded.
210          */
211         static bool      checkAttachPoint(const Pathname &apoint,
212                                           bool            empty_dir,
213                                           bool            writeable);
214
215         /**
216          * Ask media manager, if the specified path is already used
217          * as attach point or if there are another attach points
218          * bellow of it.
219          * \param path The attach point path to check.
220          * \param mtab Whether to check against the mtab, too.
221          * \return True, if the path can be used as attach point.
222          */
223         bool             isUseableAttachPoint(const Pathname &path,
224                                               bool            mtab=true) const;
225
226         /**
227          * Get the media source name or an empty string.
228          * \return media source name or empty string.
229          */
230         std::string      mediaSourceName() const
231         {
232           return _mediaSource ? _mediaSource->name : "";
233         }
234
235         /**
236          * Set new media source reference.
237          * \param ref The new reference.
238          */
239         void             setMediaSource(const MediaSourceRef &ref);
240
241         /**
242          * Ask the media manager if specified media source
243          * is already attached.
244          */
245         AttachedMedia
246         findAttachedMedia(const MediaSourceRef &media) const;
247
248         /**
249          * Returns the attached media. Used by MediaManager
250          * to find other handlers using the same source.
251          * \note This function increments reference counters
252          *       on the mediaSource and attachPoint references
253          *       it contains, for the life time of the returned
254          *       object. That is, it enables a (temporary) sharing
255          *       of them.
256          * \return The AttachedMedia struct containing (shared)
257          *         references to media source and attach point.
258          */
259         AttachedMedia    attachedMedia() const;
260
261         /**
262          * Returns a hint if the media is shared or not.
263          * \return true, if media is shared.
264          */
265         bool             isSharedMedia() const;
266
267         /**
268          * Check actual mediaSource attachment against the current
269          * mount table of the system. Used to implement isAttached().
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          * \return true, if the media appears in the mount table.
274          */
275         bool             checkAttached(bool matchMountFs) const;
276
277         /**
278          * Call to this function will try to release all media matching
279          * the currenlty attached media source, that it is able to find
280          * in the mount table. This means also foreign (user) mounts!
281          * \param matchMountFs If to use the filesystem type from the
282          *        mount table (nfs, smb and cifs) or from mediaSource
283          *        while compare of a mount entry with mediaSource.
284          */
285         void             forceRelaseAllMedia(bool matchMountFs);
286         void             forceRelaseAllMedia(const MediaSourceRef &ref,
287                                              bool matchMountFs);
288
289     protected:
290
291         ///////////////////////////////////////////////////////////////////
292         //
293         // Real action interface to be overloaded by concrete handler.
294         //
295         ///////////////////////////////////////////////////////////////////
296
297         /**
298          * Call concrete handler to attach the media.
299          *
300          * Asserted that not already attached, and attachPoint is a directory.
301          *
302          * @param next try next available device in turn until end of device
303          * list is reached (for media which are accessible through multiple
304          * devices like cdroms).
305          *
306          * \throws MediaException
307          *
308          **/
309         virtual void attachTo(bool next = false) = 0;
310
311         /**
312          * Call concrete handler to disconnect media.
313          *
314          * Asserted that media is attached.
315          *
316          * This is useful for media which e.g. holds open a connection to a
317          * server like FTP. After calling disconnect() the media object still is
318          * valid and files are present.
319          *
320          * After calling disconnect() it's not possible to call provideFile() or
321          * provideDir() anymore.
322          *
323          * \throws MediaException
324          *
325          **/
326         virtual void disconnectFrom() { return; }
327
328         /**
329          * Call concrete handler to release the media.
330          *
331          * If eject is true, and the media is used in one handler
332          * instance only, physically eject the media (i.e. CD-ROM).
333          *
334          * Asserted that media is attached.
335          * \param ejectDev Device to eject. None if empty.
336          *
337          * \throws MediaException
338          *
339          **/
340         virtual void releaseFrom( const std::string & ejectDev = "" ) = 0;
341
342         /**
343          * Call concrete handler to physically eject the media (i.e. CD-ROM)
344          * in case the media is not attached..
345          *
346          * Asserted that media is not attached.
347          **/
348         virtual void forceEject( const std::string & device ) {}
349
350         /**
351          * Call concrete handler to provide file below attach point.
352          *
353          * Default implementation provided, that returns whether a file
354          * is located at 'localRoot + filename'.
355          *
356          * Asserted that media is attached.
357          *
358          * \throws MediaException
359          *
360          **/
361         virtual void getFile( const Pathname & filename ) const = 0;
362
363         /**
364          * Call concrete handler to provide a file under a different place
365          * in the file system (usually not under attach point) as a copy.
366          * Media must be attached before by callee.
367          *
368          * Default implementation provided that calls getFile(srcFilename)
369          * and copies the result around.
370          *
371          * \throws MediaException
372          *
373          **/
374         virtual void getFileCopy( const Pathname & srcFilename, const Pathname & targetFilename ) const;
375
376
377         /**
378          * Call concrete handler to provide directory content (not recursive!)
379          * below attach point.
380          *
381          * Return E_not_supported_by_media if media does not support retrieval of
382          * directory content.
383          *
384          * Default implementation provided, that returns whether a directory
385          * is located at 'localRoot + dirname'.
386          *
387          * Asserted that media is attached.
388          *
389          * \throws MediaException
390          *
391          **/
392         virtual void getDir( const Pathname & dirname, bool recurse_r ) const = 0;
393
394         /**
395          * Call concrete handler to provide a content list of directory on media
396          * via retlist. If dots is false entries starting with '.' are not reported.
397          *
398          * Return E_not_supported_by_media if media does not support retrieval of
399          * directory content.
400          *
401          * Default implementation provided, that returns the content of a
402          * directory at 'localRoot + dirnname' retrieved via 'readdir'.
403          *
404          * Asserted that media is attached and retlist is empty.
405          *
406          * \throws MediaException
407          *
408          **/
409         virtual void getDirInfo( std::list<std::string> & retlist,
410                                  const Pathname & dirname, bool dots = true ) const = 0;
411
412         /**
413          * Basically the same as getDirInfo above. The content list is returned as
414          * filesystem::DirContent, which includes name and filetype of each directory
415          * entry. Retrieving the filetype usg. requires an additional ::stat call for
416          * each entry, thus it's more expensive than a simple readdir.
417          *
418          * Asserted that media is attached and retlist is empty.
419          *
420          * \throws MediaException
421          *
422          **/
423         virtual void getDirInfo( filesystem::DirContent & retlist,
424                                  const Pathname & dirname, bool dots = true ) const = 0;
425
426         /**
427          * check if a file exists
428          *
429          * Asserted that url is a file and not a dir.
430          *
431          * \throws MediaException
432          *
433          **/
434         virtual bool getDoesFileExist( const Pathname & filename ) const = 0;
435
436   protected:
437
438         /**
439          * Retrieve and if available scan dirname/directory.yast.
440          *
441          * Asserted that media is attached.
442          *
443          * \throws MediaException
444          *
445          **/
446         void getDirectoryYast( std::list<std::string> & retlist,
447                                const Pathname & dirname, bool dots = true ) const;
448
449         /**
450          * Retrieve and if available scan dirname/directory.yast.
451          *
452          * Asserted that media is attached.
453          *
454          * \throws MediaException
455          *
456          **/
457         void getDirectoryYast( filesystem::DirContent & retlist,
458                                const Pathname & dirname, bool dots = true ) const;
459
460   public:
461
462         /**
463          * If the concrete media handler provides a nonempty
464          * attach_point, it must be an existing directory.
465          *
466          * On an empty attach_point, MediaHandler will create
467          * a temporay directory, which will be erased from
468          * destructor.
469          *
470          * On any error, the attach_point is set to an empty Pathname,
471          * which should lead to E_bad_attachpoint.
472          **/
473         MediaHandler ( const Url&       url_r,
474                        const Pathname & attach_point_r,
475                        const Pathname & urlpath_below_attachpoint_r,
476                        const bool       does_download_r );
477
478         /**
479          * Contolling MediaAccess takes care, that attached media is released
480          * prior to deleting this.
481          **/
482         virtual ~MediaHandler();
483
484     public:
485
486
487         ///////////////////////////////////////////////////////////////////
488         //
489         // MediaAccess interface. Does common checks and logging.
490         // Invokes real action if necessary.
491         //
492         ///////////////////////////////////////////////////////////////////
493
494         /**
495          * Hint if files are downloaded or not.
496          */
497         bool        downloads() const { return _does_download; }
498
499         /**
500          * Protocol hint for MediaAccess.
501          **/
502         std::string protocol() const { return _url.getScheme(); }
503
504         /**
505          * Url used.
506          **/
507         Url url() const { return _url; }
508
509         /**
510          * Use concrete handler to attach the media.
511          *
512          * @param next try next available device in turn until end of device
513          * list is reached (for media which are accessible through multiple
514          * devices like cdroms).
515          *
516          * \throws MediaException
517          *
518          **/
519         void attach(bool next);
520
521         /**
522          * True if media is attached.
523          **/
524         virtual bool isAttached() const { return _mediaSource != nullptr; }
525
526         /**
527          * Return the local directory that corresponds to medias url,
528          * no matter if media isAttached or not. Files requested will
529          * be available at 'localRoot() + filename' or better
530          * 'localPath( filename )'.
531          *
532          * Returns empty pathname if E_bad_attachpoint
533          **/
534         Pathname localRoot() const;
535
536         /**
537          * Files provided will be available at 'localPath(filename)'.
538          *
539          * Returns empty pathname if E_bad_attachpoint
540          **/
541          Pathname localPath( const Pathname & pathname ) const;
542
543         /**
544          * Use concrete handler to isconnect media.
545          *
546          * This is useful for media which e.g. holds open a connection to a
547          * server like FTP. After calling disconnect() the media object still is
548          * valid and files are present.
549          *
550          * After calling disconnect() it's not possible to call provideFile() or
551          * provideDir() anymore.
552          *
553          * \throws MediaException
554          *
555          **/
556         void disconnect();
557
558         /**
559          * Use concrete handler to release the media.
560          * @param eject Device to physically eject. None if empty.
561          *
562          * \throws MediaException
563          **/
564         void release( const std::string & ejectDev = "" );
565
566         /**
567          * Use concrete handler to provide file denoted by path below
568          * 'localRoot'. Filename is interpreted relative to the
569          * attached url and a path prefix is preserved.
570          *
571          * \throws MediaException
572          *
573          **/
574         void provideFile( Pathname filename ) const;
575
576         /**
577          * Call concrete handler to provide a copy of a file under a different place
578          * in the file system (usually not under attach point) as a copy.
579          * Media must be attached before by callee.
580          *
581          * @param srcFilename    Filename of source file on the media
582          * @param targetFilename Filename for the target in the file system
583          *
584          * \throws MediaException
585          *
586          **/
587         void provideFileCopy( Pathname srcFilename, Pathname targetFilename) const;
588
589         /**
590          * Use concrete handler to provide directory denoted
591          * by path below 'localRoot' (not recursive!).
592          * dirname is interpreted relative to the
593          * attached url and a path prefix is preserved.
594          *
595          * \throws MediaException
596          *
597          **/
598         void provideDir( Pathname dirname ) const;
599
600         /**
601          * Use concrete handler to provide directory tree denoted
602          * by path below 'localRoot' (recursive!!).
603          * dirname is interpreted relative to the
604          * attached url and a path prefix is preserved.
605          *
606          * \throws MediaException
607          *
608          **/
609         void provideDirTree( Pathname dirname ) const;
610
611         /**
612          * Remove filename below localRoot IFF handler downloads files
613          * to the local filesystem. Never remove anything from media.
614          *
615          * \throws MediaException
616          *
617          **/
618         void releaseFile( const Pathname & filename ) const { return releasePath( filename ); }
619
620         /**
621          * Remove directory tree below localRoot IFF handler downloads files
622          * to the local filesystem. Never remove anything from media.
623          *
624          * \throws MediaException
625          *
626          **/
627         void releaseDir( const Pathname & dirname ) const { return releasePath( dirname ); }
628
629         /**
630          * Remove pathname below localRoot IFF handler downloads files
631          * to the local filesystem. Never remove anything from media.
632          *
633          * If pathname denotes a directory it is recursively removed.
634          * If pathname is empty or '/' everything below the localRoot
635          * is recursively removed.
636          * If pathname denotes a file it is unlinked.
637          *
638          * \throws MediaException
639          *
640          **/
641         void releasePath( Pathname pathname ) const;
642
643         /*
644          * set a deltafile to be used in the next download
645          */
646         void setDeltafile( const Pathname &filename = Pathname()) const;
647
648         /*
649          * return the deltafile set with setDeltafile()
650          */
651         Pathname deltafile () const;
652
653     public:
654
655         /**
656          * Return content of directory on media via retlist. If dots is false
657          * entries starting with '.' are not reported.
658          *
659          * The request is forwarded to the concrete handler,
660          * which may atempt to retieve the content e.g. via 'readdir'
661          *
662          * <B>Caution:</B> This is not supported by all media types.
663          * Be prepared to handle E_not_supported_by_media.
664          *
665          * \throws MediaException
666          *
667          **/
668         void dirInfo( std::list<std::string> & retlist,
669                       const Pathname & dirname, bool dots = true ) const;
670
671         /**
672          * Basically the same as dirInfo above. The content is returned as
673          * filesystem::DirContent, which includes name and filetype of each directory
674          * entry. Retrieving the filetype usg. requires an additional ::stat call for
675          * each entry, thus it's more expensive than a simple readdir.
676          *
677          * <B>Caution:</B> This is not supported by all media types.
678          * Be prepared to handle E_not_supported_by_media.
679          *
680          * \throws MediaException
681          *
682          **/
683         void dirInfo( filesystem::DirContent & retlist,
684                       const Pathname & dirname, bool dots = true ) const;
685
686         /**
687          * check if a file exists
688          *
689          * Asserted that url is a file and not a dir.
690          *
691          * \throws MediaException
692          *
693          **/
694         bool doesFileExist( const Pathname & filename ) const;
695
696         /**
697          * Check if the media has one more device available for attach(true).
698          */
699         virtual bool hasMoreDevices();
700
701         /**
702          * Fill in a vector of detected ejectable devices and the index of the
703          * currently attached device within the vector. The contents of the vector
704          * are the device names (/dev/cdrom and such).
705          *
706          * \param devices  vector to load with the device names
707          * \param index    index of the currently used device in the devices vector
708          */
709         virtual void
710         getDetectedDevices(std::vector<std::string> & devices,
711                            unsigned int & index) const;
712 };
713
714 ///////////////////////////////////////////////////////////////////
715
716   } // namespace media
717 } // namespace zypp
718
719
720 #endif // ZYPP_MEDIA_MEDIAHANDLERL_H
721
722