4bf4af2b601f1b00e72c63aca23f7d66f9aed690
[platform/upstream/libzypp.git] / zypp / media / MediaAccess.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/media/MediaAccess.h
10  *
11 */
12 #ifndef ZYPP_MEDIA_MEDIAACCESS_H
13 #define ZYPP_MEDIA_MEDIAACCESS_H
14
15 #include <iosfwd>
16 #include <map>
17 #include <list>
18 #include <string>
19
20 #include "zypp/base/ReferenceCounted.h"
21 #include "zypp/base/NonCopyable.h"
22 #include "zypp/base/PtrTypes.h"
23 #include "zypp/APIConfig.h"
24
25 #include "zypp/Pathname.h"
26 #include "zypp/PathInfo.h"
27
28 #include "zypp/media/MediaException.h"
29 #include "zypp/media/MediaSource.h"
30
31 #include "zypp/Url.h"
32
33 namespace zypp {
34   namespace media {
35
36     class MediaHandler;
37
38     ///////////////////////////////////////////////////////////////////
39     //
40     //  CLASS NAME : MediaAccess
41     /**
42      * @short Handle access to a medium
43      *
44      * The concrete @ref MediaHandler for a certain url is created
45      * on @ref open and deleted on @close.
46      *
47      * The inteface here basically checks whether the handler exists,
48      * then forwards the request to @ref MediaHandler.
49      **/
50     class MediaAccess : public base::ReferenceCounted, private base::NonCopyable
51     {
52     public:
53         typedef intrusive_ptr<MediaAccess> Ptr;
54         typedef intrusive_ptr<const MediaAccess> constPtr;
55
56     private:
57
58         static const Pathname _noPath;
59
60         /**
61          * handler for 'physical' media
62          * == 0 if not open
63          **/
64         MediaHandler * _handler;
65
66         friend class MediaManager;
67         friend class MediaManager_Impl;
68
69         AttachedMedia        attachedMedia() const;
70
71         bool                 isSharedMedia() const;
72
73         void                 resetParentId();
74         bool                 dependsOnParent() const;
75
76         bool                 dependsOnParent(MediaAccessId parentId,
77                                              bool exactIdMatch) const;
78     public:
79
80        /**
81         * constructor
82         **/
83         MediaAccess();
84
85         /**
86          * open url. If preferred_attach_point is given,
87          * try to use it as attach point.
88          *
89          * <b>Caution:</b> The medium can choose a different attach point.
90          * Only getAttachPoint() knows the real attach point.
91          *
92          * \throws MediaException
93          *
94          **/
95         void open( const Url& url, const Pathname & preferred_attach_point = "" );
96
97         /**
98          * True if media is open.
99          **/
100         bool isOpen() const { return( _handler != 0 ); }
101
102         /**
103          * Hint if files are downloaded or not.
104          * @return True, if the files are downloaded.
105          */
106         bool        downloads() const;
107
108         /**
109          * Used Protocol if media is opened, otherwise 'unknown'.
110          **/
111         std::string protocol() const;
112
113         /**
114          * Url if media is opened, otherwise empty.
115          **/
116         Url url() const;
117
118         /**
119          * close url
120          *
121          * \throws MediaException
122          *
123          **/
124         void close();
125
126     public:
127
128         /**
129          * Use concrete handler to attach the media.
130          *
131          * @param next try next available device in turn until end of device
132          * list is reached (for media which are accessible through multiple
133          * devices like cdroms).
134          *
135          * \throws MediaException
136          *
137          **/
138         void attach(bool next = false);
139
140         /**
141          * True if media is attached.
142          *
143          * \throws MediaException
144          *
145          **/
146         bool isAttached() const;
147
148         bool hasMoreDevices() const;
149
150         /**
151          * Fill in a vector of detected ejectable devices and the index of the
152          * currently attached device within the vector. The contents of the vector
153          * are the device names (/dev/cdrom and such).
154          *
155          * \param devices  vector to load with the device names
156          * \param index    index of the currently used device in the devices vector
157          */
158         virtual void
159         getDetectedDevices(std::vector<std::string> & devices,
160                            unsigned int & index) const;
161
162
163         /**
164          * Return the local directory that corresponds to medias url,
165          * no matter if media isAttached or not. Files requested will
166          * be available at 'localRoot() + filename' or better
167          * 'localPath( filename )'.
168          *
169          * If media is not open an empty pathname is returned.
170          **/
171         Pathname localRoot() const;
172
173         /**
174          * Short for 'localRoot() + pathname', but returns an empty
175          * pathname if media is not open.
176          *
177          * Files provided will be available at 'localPath(filename)'.
178          **/
179         Pathname localPath( const Pathname & pathname ) const;
180
181         /**
182           Use concrete handler to disconnect the media.
183
184           This is useful for media which e.g. holds open a connection to a
185           server like FTP. After calling disconnect() the media object still is
186           valid and files are present.
187
188           After calling disconnect() it's not possible to call provideFile() or
189           provideDir() anymore.
190          *
191          * \throws MediaException
192          *
193         */
194         void disconnect();
195
196         /**
197          * Use concrete handler to release the media.
198          * @param ejectDev Device to eject. None if empty.
199          *
200          * \throws MediaException
201          *
202          **/
203         void release( const std::string & ejectDev = "" );
204
205         /**
206          * Use concrete handler to provide file denoted by path below
207          * 'attach point'. Filename is interpreted relative to the
208          * attached url and a path prefix is preserved.
209          *
210          * @param cached  If cached is set to true, the function checks, if
211          *                the file already exists and doesn't download it again
212          *                if it does. Currently only the existence is checked,
213          *                no other file attributes.
214          * @param checkonly If this and 'cached' are set to true only the
215          *                  existence of the file is checked but it's not
216          *                  downloaded. If 'cached' is unset an errer is
217          *                  returned always.
218          *
219          * \throws MediaException
220          *
221          **/
222         void provideFile( const Pathname & filename, const ByteCount &expectedFileSize ) const;
223
224         /**
225          * Remove filename below attach point IFF handler downloads files
226          * to the local filesystem. Never remove anything from media.
227          *
228          * \throws MediaException
229          *
230          **/
231         void releaseFile( const Pathname & filename ) const;
232
233         /**
234          * Use concrete handler to provide directory denoted
235          * by path below 'attach point' (not recursive!).
236          * 'dirname' is interpreted relative to the
237          * attached url and a path prefix is preserved.
238          *
239          * \throws MediaException
240          *
241          **/
242         void provideDir( const Pathname & dirname ) const;
243
244         /**
245          * Use concrete handler to provide directory tree denoted
246          * by path below 'attach point' (recursive!!).
247          * 'dirname' is interpreted relative to the
248          * attached url and a path prefix is preserved.
249          *
250          * \throws MediaException
251          *
252          **/
253         void provideDirTree( const Pathname & dirname ) const;
254
255         /**
256          * Remove directory tree below attach point IFF handler downloads files
257          * to the local filesystem. Never remove anything from media.
258          *
259          * \throws MediaException
260          *
261          **/
262         void releaseDir( const Pathname & dirname ) const;
263
264         /**
265          * Remove pathname below attach point IFF handler downloads files
266          * to the local filesystem. Never remove anything from media.
267          *
268          * If pathname denotes a directory it is recursively removed.
269          * If pathname is empty or '/' everything below the attachpoint
270          * is recursively removed.
271          *
272          * \throws MediaException
273          *
274          **/
275         void releasePath( const Pathname & pathname ) const;
276
277         /**
278          * set a deltafile to be used in the next download
279          */
280         void setDeltafile( const Pathname & filename ) const;
281
282     public:
283
284         /**
285          * Return content of directory on media via retlist. If dots is false
286          * entries starting with '.' are not reported.
287          *
288          * The request is forwarded to the concrete handler,
289          * which may atempt to retieve the content e.g. via 'readdir'
290          *
291          * <B>Caution:</B> This is not supported by all media types.
292          * Be prepared to handle E_not_supported_by_media.
293          *
294          * \throws MediaException
295          *
296          **/
297         void dirInfo( std::list<std::string> & retlist,
298                          const Pathname & dirname, bool dots = true ) const;
299
300         /**
301          * Basically the same as dirInfo above. The content is returned as
302          * filesystem::DirContent, which includes name and filetype of each directory
303          * entry. Retrieving the filetype usg. requires an additional ::stat call for
304          * each entry, thus it's more expensive than a simple readdir.
305          *
306          * <B>Caution:</B> This is not supported by all media types.
307          * Be prepared to handle E_not_supported_by_media.
308          *
309          * \throws MediaException
310          *
311          **/
312         void dirInfo( filesystem::DirContent & retlist,
313                       const Pathname & dirname, bool dots = true ) const;
314
315         /**
316          * check if a file exists
317          *
318          * Asserted that url is a file and not a dir.
319          *
320          * \throws MediaException
321          *
322          **/
323         bool doesFileExist( const Pathname & filename ) const;
324
325         /**
326          * Destructor
327          **/
328         virtual ~MediaAccess();
329
330     public:
331
332         virtual std::ostream & dumpOn( std::ostream & str ) const;
333
334     public:
335         /**
336          * Get file from location at specified by URL and copy it to
337          * destination.
338          *
339          * @param from Source URL
340          * @param to   Destination file name
341          *
342          * \throws MediaException
343          *
344          **/
345         void getFile( const Url &from, const Pathname &to );
346
347     public:
348
349       /**
350        * Helper class that provides file on construction
351        * and cleans up on destruction.
352        *
353        * <b>Caution:</b> There's no synchronisation between multiple
354        * FileProvider instances, that provide the same file from the
355        * same media. If the first one goes out of scope, the file is
356        * cleaned. It's just a convenience for 'access and forgett'.
357        *
358        * <b>Caution:</b> We should either store the reference MediaAccess'
359        * MediaHandler here (for this MediaHandler must become a
360        * ref counting pointer class), or we need more info from MediaHandler
361        * (whether he's downloading to the local fs. If not, no releasefile
362        * is necessary).
363        * Currently we can not releaseFile after the media was closed
364        * (it's passed to the handler, which is deleted on close).
365        *
366        * \throws MediaBadFilenameException
367        * \throws MediaException
368        **/
369       class FileProvider {
370         FileProvider( const FileProvider & );             // no copy
371         FileProvider & operator=( const FileProvider & ); // no assign
372         private:
373           MediaAccess::constPtr _media;
374           Pathname              _file;
375           Pathname              _local_file;
376         public:
377           /**
378            * \throws MediaException
379            */
380           FileProvider( MediaAccess::constPtr media_r, const Pathname & file_r )
381             : _media( media_r )
382             , _file( file_r )
383             , _local_file( "" )
384           {
385             if ( _file.empty() ) {
386               ZYPP_THROW(MediaBadFilenameException(_file.asString()));
387             } else if ( _media ) {
388               try {
389                 _media->provideFile( _file, 0 );
390                 _local_file = _media->localPath( _file );
391               }
392               catch (const MediaException & excpt_r)
393               {
394                 ZYPP_CAUGHT(excpt_r);
395                 _media = NULL;
396                 ZYPP_RETHROW(excpt_r);
397               }
398             }
399           }
400
401           ~FileProvider() {
402             if ( _media )
403             {
404               try {
405                 _media->releaseFile( _file );
406               }
407               catch (const MediaException &excpt_r)
408               {
409                 ZYPP_CAUGHT(excpt_r);
410               }
411               catch(...) {} // No exception from dtor!
412             }
413           }
414
415         public:
416
417           /**
418            * If no error, expect operator() to return the local
419            * Pathname of the provided file.
420            **/
421           Pathname localFile() const { return _local_file; }
422
423           /**
424            * Return the local Pathname of the provided file or
425            * an empty Pathname on error.
426            **/
427           Pathname operator()() const {
428             if ( _media )
429               return _media->localPath( _file );
430             return Pathname();
431           }
432       };
433     };
434
435     std::ostream & operator<<( std::ostream & str, const MediaAccess & obj );
436
437 ///////////////////////////////////////////////////////////////////
438
439   } // namespace media
440 } // namespace zypp
441
442 #endif // ZYPP_MEDIA_MEDIAACCESS_H
443