source: abuse/tags/pd/macabuse/src/net/unix/netfile.c @ 49

Last change on this file since 49 was 49, checked in by Sam Hocevar, 12 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 11.5 KB
Line 
1#include "indian.hpp"
2#include "netfile.hpp"
3#include "../inc/netface.hpp"
4#include "engine.hpp"
5
6
7nfs_client *first_nfs_client=NULL;
8remote_file *remote_file_list=NULL;
9char default_fs_name[256];    // default file server name (set with parm -fs)
10
11nfs_client::nfs_client(net_socket *sock, int file_fd, nfs_client *next) :
12  sock(sock),file_fd(file_fd),next(next),size_to_read(0)
13{
14  sock->read_selectable();
15
16
17
18nfs_client::~nfs_client()
19{
20  delete sock;
21  if (file_fd>=0)
22    close(file_fd);
23}
24
25void secure_filename(char *filename, char *mode)
26{
27  if (!no_security)
28  {   
29    if (filename[0]=='/') { filename[0]=0; return ; }
30    int level=0;
31    char *f=filename;
32    while (*f)
33    {
34      if (*f=='/') { f++; level++; }
35      else if (*f=='.' && f[1]=='.')
36      {
37        if (f[3]=='.') while (*f!='.') f++;
38        else
39        {
40          f+=2;
41          level--;
42        }
43      } else f++;
44     
45    }
46    if (level<0)
47      filename[0]=0;
48  }
49}
50
51
52int local_address(char *server_name)    // returns 1 if server name is ourself
53{
54  struct hostent *hn=gethostbyname(server_name);    // first check to see if this address is 127.0.0.1
55  if (!hn) return 0;                                // if bad server_name, return false
56  char **ip_address=hn->h_addr_list;
57  while (*ip_address)
58  {
59    char *a=*ip_address;
60    if (a[0]==127 && a[1]==0 && a[2]==0 && a[3]==1)
61      return 1;
62    ip_address++;
63  }
64  char server_ip[4];
65  memcpy(server_ip,hn->h_addr_list,4);
66
67  char my_name[100];                              // now check to see if this address is 'hostname'
68  gethostname(my_name,100);
69  struct hostent *l_hn=gethostbyname(my_name); 
70  char **l_ip_address=l_hn->h_addr_list;
71
72  while (*l_ip_address)  // local ip_address
73  {
74    char *a=*l_ip_address;         // scan through all local ip's
75    ip_address=hn->h_addr_list;
76    while (*ip_address)            // scan through all ip's for server_name
77    {
78      char *b=server_ip;
79      if (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3])    // check for match
80        return 1;
81      ip_address++;
82    }
83    l_ip_address++;
84  }
85  return 0;       // didn't match localhost nor hostname, must be somewhere else
86}
87
88int nfs_client::send_read()   // return 0 if failure on socket, not failure to read
89{
90  if (file_fd>=0 && socket_fd>=0)
91  {
92    // first make sure the socket isn't 'full'
93
94    struct timeval tv={0,0};     // don't wait
95    fd_set write_check; 
96    FD_ZERO(&write_check); 
97    FD_SET(socket_fd,&write_check);     
98    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
99
100    if (FD_ISSET(socket_fd,&write_check))            // ready to write?
101    {
102      char buf[READ_PACKET_SIZE];   
103      short read_total;
104      short actual;
105
106      do
107      {     
108        read_total=size_to_read>(READ_PACKET_SIZE-2) ? (READ_PACKET_SIZE-2) : size_to_read;
109        actual=read(file_fd,buf,read_total);
110        actual=lstl(actual);
111        if (write(socket_fd,&actual,sizeof(actual))!=sizeof(actual))
112        {
113          fprintf(stderr,"write failed\n");
114          return 0;
115        }
116        actual=lstl(actual);
117
118        int write_amount=write(socket_fd,buf,actual);
119        if (write_amount!=actual)
120        {
121          fprintf(stderr,"write failed\n");
122          return 0;
123        }
124
125        size_to_read-=actual;
126
127        FD_ZERO(&write_check); 
128        FD_SET(socket_fd,&write_check);     
129        select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
130
131        if (!FD_ISSET(socket_fd,&write_check))
132        {
133          FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
134          FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
135          return 1;    // not ok to write anymore, try again latter
136        }
137
138      } while (size_to_read && actual==read_total);
139      size_to_read=0;
140      FD_CLR(socket_fd,&master_write_set);       // don't check this socket for write ok
141      FD_SET(socket_fd,&master_set);             // check it for reading
142      return 1;
143    } else
144    {
145      FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
146      FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
147      return 1;
148    }
149  }
150  return 0;
151}
152
153
154int process_nfs_command(nfs_client *c)
155{
156  char cmd;
157  if (read(c->socket_fd,&cmd,1)!=1) return 0;
158  switch (cmd)
159  {
160    case NFCMD_READ :
161    {
162      long size;
163      if (read(c->socket_fd,&size,sizeof(size))!=sizeof(size)) return 0;
164      size=lltl(size);
165
166      c->size_to_read=size;
167      return c->send_read();
168    } break;
169    case NFCMD_CLOSE :
170    {
171      return 0;
172    } break;
173    case NFCMD_SEEK :
174    {
175      long offset;
176      if (read(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
177      offset=lltl(offset);
178      offset=lseek(c->file_fd,offset,0);
179      offset=lltl(offset);
180      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
181      return 1;
182    } break;
183    case NFCMD_TELL :
184    {
185      long offset=lseek(c->file_fd,0,SEEK_CUR);
186      offset=lltl(offset);
187      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
188      return 1;
189    } break;
190   
191    default :
192    { fprintf(stderr,"net driver : bad command from nfs client\n");
193      return 0;
194    }
195  }
196}
197
198
199
200void add_nfs_client(int fd)
201{
202  uchar size[2];
203  char filename[300],mode[20],*mp;
204  if (read(fd,size,2)!=2) { close(fd); return ; }
205  if (read(fd,filename,size[0])!=size[0]) { close(fd); return ; }
206  if (read(fd,mode,size[1])!=size[1]) { close(fd); return ; }
207 
208  fprintf(stderr,"remote request for %s ",filename);
209
210  secure_filename(filename,mode);  // make sure this filename isn't a security risk
211  if (filename[0]==0) { fprintf(stderr,"(denied)\n"); close(fd); return ; }
212
213  mp=mode;
214  int flags=0;
215
216  while (*mp)
217  {
218    if (*mp=='w') flags|=O_CREAT|O_RDWR;
219    else if (*mp=='r') flags|=O_RDONLY;
220    mp++;
221  }
222     
223  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
224 
225  if (f<0)
226  {
227    fprintf(stderr,"(not found)\n");
228    f=-1;  // make sure this is -1
229  }
230
231  long ret=lltl(f);
232  if (write(fd,&ret,sizeof(ret))!=sizeof(ret)) { close(fd); return ; }
233
234  if (f<0)    // no file, sorry
235    close(fd);
236  else
237  {
238    long cur_pos=lseek(f,0,SEEK_CUR);
239    long size=lseek(f,0,SEEK_END);
240    lseek(f,cur_pos,SEEK_SET);
241    size=lltl(size);
242    if (write(fd,&size,sizeof(size))!=sizeof(size)) {  close(f); close(fd); return ; }
243
244    first_nfs_client=new nfs_client(fd,f,first_nfs_client);
245    first_nfs_client->size=size;
246  }
247}
248
249void remote_file::r_close(char *reason)
250{
251  if (reason)
252    fprintf(stderr,"remote_file : %s\n",reason);
253  if (socket_fd>=0)
254  {
255    uchar cmd=NFCMD_CLOSE;
256    write(socket_fd,&cmd,1);
257    close(socket_fd);
258  }
259  socket_fd=-1;
260}
261
262remote_file::remote_file(char *filename, char *mode, remote_file *Next)
263{
264  next=Next;
265  open_local=0;
266
267  socket_fd=connect_to_server(filename);
268  if (socket_fd==-1)
269  {
270    fprintf(stderr,"unable to connect\n");
271    return ;
272  }
273
274  uchar sizes[3]={CLIENT_NFS,strlen(filename)+1,strlen(mode)+1};
275  if (write(socket_fd,sizes,3)!=3) { r_close("could not send open info"); return ; }
276  if (write(socket_fd,filename,sizes[1])!=sizes[1]) { r_close("could not send filename"); return ; }
277  if (write(socket_fd,mode,sizes[2])!=sizes[2]) { r_close("could not send mode"); return ; }
278
279  long remote_file_fd;
280  if (read(socket_fd,&remote_file_fd,sizeof(remote_file_fd))!=sizeof(remote_file_fd))
281  { r_close("could not read remote fd"); return ; }   
282  remote_file_fd=lltl(remote_file_fd);
283  if (remote_file_fd<0) { r_close("remote fd is bad"); return ; }
284
285  if (read(socket_fd,&size,sizeof(size))!=sizeof(size)) { r_close("could not read remote filesize"); return ; }
286//  ulong remote_crc;
287//  if (read(socket_fd,&remote_crc,sizeof(remote_crc))!=sizeof(remote_crc)) { r_close("could not read remote checksum"); return ; }
288//  ulong local_crc=
289
290  size=lltl(size);
291}
292
293int remote_file::unbuffered_read(int out_fd, size_t count)
294{
295  if (socket_fd>=0 && count)
296  {
297    uchar cmd=NFCMD_READ;
298    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("read : could not send command"); return 0; }
299
300    long rsize=lltl(count);
301    if (write(socket_fd,&rsize,sizeof(rsize))!=sizeof(rsize)) { r_close("read : could not send size"); return 0; }
302
303    long total_read=0,total;
304    char buf[READ_PACKET_SIZE];
305    ushort size;
306
307    ushort packet_size;   
308    do
309    {
310      if (read(socket_fd,&packet_size,sizeof(packet_size))!=sizeof(packet_size))
311      {
312        fprintf(stderr,"could not read packet size\n");
313        return 0;
314      }
315      packet_size=lstl(packet_size);
316
317      ushort size_read=read(socket_fd,buf+2,packet_size);   
318
319      if (size_read!=packet_size)
320      {
321        if (read(socket_fd,buf+2+size_read,packet_size-size_read)!=packet_size-size_read)
322        {
323          fprintf(stderr,"incomplete packet\n");
324          return 0;
325        }
326      }
327
328      *((short *)buf)=packet_size;
329      if (write(out_fd,buf,packet_size+2)!=packet_size+2) comm_failed();
330
331      total_read+=packet_size;
332      count-=packet_size;
333    } while (packet_size==READ_PACKET_SIZE-2 && count);     
334    return total_read;
335  }
336  return 0;
337}
338
339int remote_file::unbuffered_tell()   // ask server where the offset of the file pointer is
340{
341  if (socket_fd>=0)
342  {
343    uchar cmd=NFCMD_TELL;
344    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("tell : could not send command"); return 0; }
345
346    long offset;
347    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("tell : could not read offset"); return 0; }   
348    return lltl(offset);
349  }   
350  return 0;
351}
352
353int remote_file::unbuffered_seek(long offset)  // tell server to seek to a spot in a file
354{
355  if (socket_fd>=0)
356  {
357    uchar cmd=NFCMD_SEEK;
358    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("seek : could not send command"); return 0; }
359
360    long off=lltl(offset);
361    if (write(socket_fd,&off,sizeof(off))!=sizeof(off)) { r_close("seek : could not send offset"); return 0; }
362
363    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("seek : could not read offset"); return 0; }   
364    return lltl(offset);
365  }   
366  return 0;
367}
368
369int open_file(char *&filename, char *mode)
370{
371  if (filename[0]!='/' && filename[1]!='/' && default_fs_name[0])   // default file server?
372  {
373    char tmp_fn[500]; 
374    sprintf(tmp_fn,"//%s/%s",default_fs_name,filename);
375    strcpy(filename,tmp_fn);
376  }
377
378  if (filename[0]=='/' && filename[1]=='/')   // passive server file reference?
379  {
380    filename+=2;
381    remote_file *rf=new remote_file(filename,mode,remote_file_list);
382    if (rf->open_failure())
383    {
384      delete rf;
385      return -1;
386    }
387    else
388    {
389      remote_file_list=rf;
390      return rf->socket_fd;
391    }     
392  }
393
394  secure_filename(filename,mode);
395  if (filename[0]==0) return -1;
396
397  int flags=0;
398  while (*mode)
399  {
400    if (*mode=='w') flags|=O_CREAT|O_RDWR;
401    else if (*mode=='r') flags|=O_RDONLY;
402    mode++;
403  }
404
405  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
406  if (f>=0)
407  { close(f);
408    return -2;
409  }
410 
411  return -1;
412}
413
414remote_file *find_rfile(int fd)
415{
416  remote_file *r=remote_file_list;
417  for (;r && r->socket_fd!=fd;r=r->next)
418  {
419    if (r->socket_fd==-1)
420    {
421      fprintf(stderr,"bad sock\n");
422    }
423  }
424  return r;
425}
426
427void unlink_remote_file(remote_file *rf)
428{
429  if (rf==remote_file_list)
430    remote_file_list=rf->next;
431  else
432  {
433    remote_file *last=remote_file_list;
434    while (last->next && last->next!=rf) last=last->next;
435    last->next=rf->next;
436  }
437}
438
439remote_file::~remote_file()
440{ r_close(NULL); }
441
442
443int fetch_crcs(char *server)
444{
445  int socket_fd=connect_to_server(server);
446  if (socket_fd==-1)
447  {
448    fprintf(stderr,"unable to connect\n");
449    return 0;
450  }
451
452  uchar cmd=CLIENT_CRC_WAITER;
453  if (write(socket_fd,&cmd,1)!=1)  { close(socket_fd); return 0; }
454  if (read(socket_fd,&cmd,1)!=1)  { close(socket_fd); return 0; }
455  close(socket_fd);
456  return cmd;
457 
458}
459
460
Note: See TracBrowser for help on using the repository browser.