Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
e542ff7ccb45e762df6f7a0bc183cd2b007e45d3
[simgrid.git] / src / gras / Transport / transport_plugin_file.c
1 /* $Id$ */
2
3 /* File transport - send/receive a bunch of bytes from a file               */
4
5 /* Authors: Martin Quinson                                                  */
6 /* Copyright (C) 2004 Martin Quinson.                                       */
7
8 /* This program is free software; you can redistribute it and/or modify it
9    under the terms of the license (GNU LGPL) which comes with this package. */
10
11 #include <errno.h>
12 #include <sys/time.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17
18 #include "gras_private.h"
19 #include "transport_private.h"
20
21 GRAS_LOG_NEW_DEFAULT_SUBCATEGORY(trp_file,transport,
22         "Pseudo-transport to write to/read from a file");
23
24 /***
25  *** Prototypes 
26  ***/
27 void         gras_trp_file_close(gras_socket_t *sd);
28   
29 gras_error_t gras_trp_file_chunk_send(gras_socket_t *sd,
30                                       const char *data,
31                                       long int size);
32
33 gras_error_t gras_trp_file_chunk_recv(gras_socket_t *sd,
34                                       char *data,
35                                       long int size);
36
37
38 /***
39  *** Specific plugin part
40  ***/
41
42 typedef struct {
43   fd_set incoming_socks;
44 } gras_trp_file_plug_data_t;
45
46 /***
47  *** Specific socket part
48  ***/
49
50
51
52 /***
53  *** Code
54  ***/
55 gras_error_t
56 gras_trp_file_setup(gras_trp_plugin_t *plug) {
57
58   gras_trp_file_plug_data_t *file = gras_new(gras_trp_file_plug_data_t,1);
59
60   FD_ZERO(&(file->incoming_socks));
61
62   plug->socket_close = gras_trp_file_close;
63   plug->chunk_send   = gras_trp_file_chunk_send;
64   plug->chunk_recv   = gras_trp_file_chunk_recv;
65   plug->data         = (void*)file;
66
67   return no_error;
68 }
69
70 /**
71  * gras_socket_client_from_file:
72  *
73  * Create a client socket from a file path.
74  *
75  * This only possible in RL, and is mainly for debugging.
76  */
77 gras_error_t
78 gras_socket_client_from_file(const char*path,
79                              /* OUT */ gras_socket_t **dst) {
80   gras_error_t errcode;
81   gras_trp_plugin_t *trp;
82
83   gras_assert0(gras_if_RL(),
84                "Cannot use file as socket in the simulator");
85
86   gras_trp_socket_new(0,dst);
87
88   TRY(gras_trp_plugin_get_by_name("file",&trp));
89   (*dst)->plugin=trp;
90
91   if (strcmp("-", path)) {
92     (*dst)->sd = open(path, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP );
93     
94     if ( (*dst)->sd < 0) {
95       RAISE2(system_error,
96              "Cannot create a client socket from file %s: %s",
97              path, strerror(errno));
98     }
99   } else {
100     (*dst)->sd = 1; /* stdout */
101   }
102
103   DEBUG5("sock_client_from_file(%s): sd=%d in=%c out=%c accept=%c",
104          path,
105          (*dst)->sd,
106          (*dst)->incoming?'y':'n', 
107          (*dst)->outgoing?'y':'n',
108          (*dst)->accepting?'y':'n');
109    
110   return no_error;
111 }
112
113 /**
114  * gras_socket_server_from_file:
115  *
116  * Create a server socket from a file path.
117  *
118  * This only possible in RL, and is mainly for debugging.
119  */
120 gras_error_t
121 gras_socket_server_from_file(const char*path,
122                              /* OUT */ gras_socket_t **dst) {
123   gras_error_t errcode;
124   gras_trp_plugin_t *trp;
125
126   gras_assert0(gras_if_RL(),
127                "Cannot use file as socket in the simulator");
128
129   gras_trp_socket_new(1,dst);
130
131   TRY(gras_trp_plugin_get_by_name("file",&trp));
132   (*dst)->plugin=trp;
133
134
135   if (strcmp("-", path)) {
136     (*dst)->sd = open(path, O_RDONLY );
137
138     if ( (*dst)->sd < 0) {
139       RAISE2(system_error,
140              "Cannot create a server socket from file %s: %s",
141              path, strerror(errno));
142     }
143   } else {
144     (*dst)->sd = 0; /* stdin */
145   }
146
147   DEBUG4("sd=%d in=%c out=%c accept=%c",
148          (*dst)->sd,
149          (*dst)->incoming?'y':'n', 
150          (*dst)->outgoing?'y':'n',
151          (*dst)->accepting?'y':'n');
152
153   return no_error;
154 }
155
156 void gras_trp_file_close(gras_socket_t *sock){
157   gras_trp_file_plug_data_t *data;
158   
159   if (!sock) return; /* close only once */
160   data=sock->plugin->data;
161
162   if (sock->sd == 0) {
163     DEBUG0("Do not close stdin");
164   } else if (sock->sd == 1) {
165     DEBUG0("Do not close stdout");
166   } else {
167     DEBUG1("close file connection %d", sock->sd);
168
169     /* forget about the socket */
170     FD_CLR(sock->sd, &(data->incoming_socks));
171
172     /* close the socket */
173     if(close(sock->sd) < 0) {
174       WARN2("error while closing file %d: %s", 
175                sock->sd, strerror(errno));
176     }
177   }
178 }
179
180 /**
181  * gras_trp_file_chunk_send:
182  *
183  * Send data on a file pseudo-socket
184  */
185 gras_error_t 
186 gras_trp_file_chunk_send(gras_socket_t *sock,
187                          const char *data,
188                          long int size) {
189   
190   gras_assert0(sock->outgoing, "Cannot write on client file socket");
191   gras_assert0(size >= 0, "Cannot send a negative amount of data");
192
193   while (size) {
194     int status = 0;
195     
196     DEBUG3("write(%d, %p, %ld);", sock->sd, data, (long int)size);
197     status = write(sock->sd, data, (long int)size);
198     
199     if (status == -1) {
200       RAISE4(system_error,"write(%d,%p,%d) failed: %s",
201              sock->sd, data, (int)size,
202              strerror(errno));
203     }
204     
205     if (status) {
206       size  -= status;
207       data  += status;
208     } else {
209       RAISE0(system_error,"file descriptor closed");
210     }
211   }
212
213   return no_error;
214 }
215 /**
216  * gras_trp_file_chunk_recv:
217  *
218  * Receive data on a file pseudo-socket.
219  */
220 gras_error_t 
221 gras_trp_file_chunk_recv(gras_socket_t *sock,
222                         char *data,
223                         long int size) {
224
225   gras_assert0(sock, "Cannot recv on an NULL socket");
226   gras_assert0(sock->incoming, "Cannot recv on client file socket");
227   gras_assert0(size >= 0, "Cannot receive a negative amount of data");
228   
229   while (size) {
230     int status = 0;
231     
232     status = read(sock->sd, data, (long int)size);
233     DEBUG3("read(%d, %p, %ld);", sock->sd, data, size);
234     
235     if (status == -1) {
236       RAISE4(system_error,"read(%d,%p,%d) failed: %s",
237              sock->sd, data, (int)size,
238              strerror(errno));
239     }
240     
241     if (status) {
242       size  -= status;
243       data  += status;
244     } else {
245       RAISE0(system_error,"file descriptor closed");
246     }
247   }
248   
249   return no_error;
250 }
251