]> git.sesse.net Git - vlc/blob - modules/access/file.c
* ./Makefile.am: fixed rc compilation under mingw32/cygwin.
[vlc] / modules / access / file.c
1 /*****************************************************************************
2  * file.c: file input (file: access plug-in)
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: file.c,v 1.3 2002/11/12 13:57:12 sam Exp $
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  * 
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <fcntl.h>
33
34 #include <vlc/vlc.h>
35 #include <vlc/input.h>
36
37 #ifdef HAVE_UNISTD_H
38 #   include <unistd.h>
39 #elif defined( _MSC_VER ) && defined( _WIN32 ) && !defined( UNDER_CE )
40 #   include <io.h>
41 #endif
42
43 /*****************************************************************************
44  * Exported prototypes
45  *****************************************************************************/
46 static int     Open   ( vlc_object_t * );
47 static void    Close  ( vlc_object_t * );
48
49 static void    Seek   ( input_thread_t *, off_t );
50 static ssize_t Read   ( input_thread_t *, byte_t *, size_t );
51
52 /*****************************************************************************
53  * Module descriptor
54  *****************************************************************************/
55 vlc_module_begin();
56     set_description( _("Standard filesystem file reading") );
57     set_capability( "access", 50 );
58     add_shortcut( "file" );
59     add_shortcut( "stream" );
60     set_callbacks( Open, Close );
61 vlc_module_end();
62  
63 /*****************************************************************************
64  * Open: open the file
65  *****************************************************************************/
66 static int Open( vlc_object_t *p_this )
67 {
68     input_thread_t *    p_input = (input_thread_t *)p_this;
69     char *              psz_name = p_input->psz_name;
70     int                 i_stat;
71     struct stat         stat_info;                                              
72     input_socket_t *    p_access_data;
73     vlc_bool_t          b_stdin;
74
75     p_input->i_mtu = 0;
76
77     b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
78
79     if( !b_stdin && (i_stat = stat( psz_name, &stat_info )) == (-1) )
80     {
81         msg_Err( p_input, "cannot stat() file `%s' (%s)",
82                           psz_name, strerror(errno));
83         return VLC_EGENERIC;
84     }
85
86     p_input->pf_read = Read;
87     p_input->pf_set_program = input_SetProgram;
88     p_input->pf_set_area = NULL;
89     p_input->pf_seek = Seek;
90
91     vlc_mutex_lock( &p_input->stream.stream_lock );
92
93     if( *p_input->psz_access && !strncmp( p_input->psz_access, "stream", 7 ) )
94     {
95         /* stream:%s */
96         p_input->stream.b_pace_control = 0;
97         p_input->stream.b_seekable = 0;
98         p_input->stream.p_selected_area->i_size = 0;
99     }
100     else
101     {
102         /* file:%s or %s */
103         p_input->stream.b_pace_control = 1;
104
105         if( b_stdin )
106         {
107             p_input->stream.b_seekable = 0;
108             p_input->stream.p_selected_area->i_size = 0;
109         }
110         else if( S_ISREG(stat_info.st_mode) || S_ISCHR(stat_info.st_mode)
111                   || S_ISBLK(stat_info.st_mode) )
112         {
113             p_input->stream.b_seekable = 1;
114             p_input->stream.p_selected_area->i_size = stat_info.st_size;
115         }
116         else if( S_ISFIFO(stat_info.st_mode)
117 #if !defined( SYS_BEOS ) && !defined( WIN32 )
118                   || S_ISSOCK(stat_info.st_mode)
119 #endif
120                )
121         {
122             p_input->stream.b_seekable = 0;
123             p_input->stream.p_selected_area->i_size = 0;
124         }
125         else
126         {
127             vlc_mutex_unlock( &p_input->stream.stream_lock );
128             msg_Err( p_input, "unknown file type for `%s'", psz_name );
129             return VLC_EGENERIC;
130         }
131     }
132  
133     p_input->stream.p_selected_area->i_tell = 0;
134     p_input->stream.i_method = INPUT_METHOD_FILE;
135     vlc_mutex_unlock( &p_input->stream.stream_lock );
136  
137     msg_Dbg( p_input, "opening file `%s'", psz_name );
138     p_access_data = malloc( sizeof(input_socket_t) );
139     p_input->p_access_data = (void *)p_access_data;
140     if( p_access_data == NULL )
141     {
142         msg_Err( p_input, "out of memory" );
143         return VLC_ENOMEM;
144     }
145
146     if( b_stdin )
147     {
148         p_access_data->i_handle = 0;
149     }
150     else if( (p_access_data->i_handle = open( psz_name,
151                                    /*O_NONBLOCK | O_LARGEFILE*/ 0 )) == (-1) )
152     {
153         msg_Err( p_input, "cannot open file %s (%s)", psz_name,
154                           strerror(errno) );
155         free( p_access_data );
156         return VLC_EGENERIC;
157     }
158
159     return VLC_SUCCESS;
160 }
161
162 /*****************************************************************************
163  * Close: close the target
164  *****************************************************************************/
165 static void Close( vlc_object_t * p_this )
166 {
167     input_thread_t * p_input = (input_thread_t *)p_this;
168     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
169
170     msg_Info( p_input, "closing `%s/%s://%s'", 
171               p_input->psz_access, p_input->psz_demux, p_input->psz_name );
172  
173 #ifdef UNDER_CE
174     CloseHandle( (HANDLE)p_access_data->i_handle );
175 #else
176     close( p_access_data->i_handle );
177 #endif
178
179     free( p_access_data );
180 }
181
182 /*****************************************************************************
183  * Read: standard read on a file descriptor.
184  *****************************************************************************/
185 static ssize_t Read( input_thread_t * p_input, byte_t * p_buffer, size_t i_len )
186 {
187     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
188     ssize_t i_ret;
189  
190 #ifdef UNDER_CE
191     if( !ReadFile( (HANDLE)p_access_data->i_handle, p_buffer, i_len,
192                    (LPWORD)&i_ret, NULL ) )
193     {
194         i_ret = -1;
195     }
196 #else
197     i_ret = read( p_access_data->i_handle, p_buffer, i_len );
198 #endif
199  
200     if( i_ret < 0 )
201     {
202 #   ifdef HAVE_ERRNO_H
203         msg_Err( p_input, "read failed (%s)", strerror(errno) );
204 #   else
205         msg_Err( p_input, "read failed" );
206 #   endif
207     }
208  
209     return i_ret;
210 }
211
212 /*****************************************************************************
213  * Seek: seek to a specific location in a file
214  *****************************************************************************/
215 static void Seek( input_thread_t * p_input, off_t i_pos )
216 {
217 #define S p_input->stream
218     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
219
220     lseek( p_access_data->i_handle, i_pos, SEEK_SET );
221
222     vlc_mutex_lock( &S.stream_lock );
223     S.p_selected_area->i_tell = i_pos;
224     if( S.p_selected_area->i_tell > S.p_selected_area->i_size )
225     {
226         msg_Err( p_input, "seeking too far" );
227         S.p_selected_area->i_tell = S.p_selected_area->i_size;
228     }
229     else if( S.p_selected_area->i_tell < 0 )
230     {
231         msg_Err( p_input, "seeking too early" );
232         S.p_selected_area->i_tell = 0;
233     }
234     vlc_mutex_unlock( &S.stream_lock );
235 #undef S
236 }
237