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