Masanobu Yasui authored on 2008/10/03 03:30:00
Showing 9 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,5 @@
0
+all: makuosan.c minit.c msend.c mrecv.c mexec.c common.c
1
+	gcc -g -lssl -lpthread -o makuosan makuosan.c minit.c msend.c mrecv.c mexec.c common.c
2
+
3
+clean:
4
+	rm -f makuosan
0 5
new file mode 100644
... ...
@@ -0,0 +1,604 @@
0
+/*
1
+ *  common.c
2
+ */
3
+#include "makuosan.h"
4
+
5
+mopt moption;
6
+mfile *mftop[2] = {NULL,NULL};
7
+mhost *members  = NULL;
8
+int loop_flag   = 1;
9
+char TZ[256];
10
+struct timeval curtime;
11
+BF_KEY EncKey;
12
+
13
+int md5sum(int fd, unsigned char *digest)
14
+{
15
+  int  rd;
16
+  char buff[1024];
17
+  MD5_CTX ctx;
18
+
19
+  MD5_Init(&ctx);
20
+  while(rd = read(fd, buff, sizeof(buff))){
21
+    if(rd == -1){
22
+      return(-1);
23
+    }
24
+    MD5_Update(&ctx, buff, rd);
25
+  }
26
+  MD5_Final(digest, &ctx);
27
+  return(0);
28
+}
29
+
30
+/*
31

                
32

                
33

                
34
+ */
35
+int mtimeout(struct timeval *tf, uint32_t msec)
36
+{
37
+  struct timeval tv;
38
+  struct timeval tr;
39
+  tv.tv_sec  = msec / 1000;
40
+  tv.tv_usec = (msec % 1000) * 1000;
41
+  timeradd(tf, &tv, &tr);
42
+  return(timercmp(&tr, &curtime, <));
43
+}
44
+
45
+/*
46

                
47

                
48
+ */
49
+int mtimeget(struct timeval *tv)
50
+{
51
+  memcpy(tv, &curtime, sizeof(curtime));
52
+  return(0);
53
+}
54
+
55
+/*
56

                
57

                
58

                
59
+ */
60
+excludeitem *mfnmatch(char *str, excludeitem *exclude)
61
+{
62
+  char *p;
63
+  excludeitem *e;
64
+  for(e=exclude;e;e=e->next){
65
+    p=str;
66
+    while(*p){
67
+      if(strlen(p) < strlen(e->pattern)){
68
+        break;
69
+      }
70
+      if(!fnmatch(e->pattern, p, FNM_PATHNAME)){
71
+        return(e);
72
+      }
73
+      while(*p){
74
+        if(*(p++) == '/'){
75
+          break;
76
+        }
77
+      }
78
+    }
79
+  }
80
+  return(NULL);
81
+}
82
+
83
+int atomic_write(int fd, void *buff, size_t size)
84
+{
85
+  int s = 0;
86
+  int r = 0;
87
+  int w = 0;
88
+  struct pollfd pf;
89
+
90
+  while(size){
91
+    pf.fd      = fd;
92
+    pf.events  = POLLOUT;
93
+    pf.revents = 0;
94
+    s = poll(&pf,1,1000);
95
+    if(s == -1){
96
+      if(errno == EINTR){
97
+        continue;
98
+      }else{
99
+        break;
100
+      }
101
+    }
102
+    if(s){
103
+      w = write(fd,buff,size);
104
+      if(w <= 0){
105
+        return(-1);
106
+      }else{
107
+        size -= w;
108
+        buff += w;
109
+        r    += w;
110
+      }
111
+    }
112
+  }
113
+  return(r);
114
+}
115
+
116
+void fdprintf(int s, char *fmt, ...)
117
+{
118
+  char m[2048];
119
+  va_list arg;
120
+  if(s != -1){
121
+    va_start(arg, fmt);
122
+    vsprintf(m, fmt, arg);
123
+    va_end(arg);
124
+    write(s, m, strlen(m));
125
+  }
126
+}
127
+
128
+void lprintf(int l, char *fmt, ...)
129
+{
130
+  va_list arg;
131
+  char msg[512];
132
+  if(moption.loglevel >= l){
133
+    va_start(arg, fmt);
134
+    vsprintf(msg, fmt, arg);
135
+    va_end(arg);
136
+    if(moption.dontfork){
137
+      fprintf(stderr, msg);
138
+    }
139
+    syslog(LOG_ERR, "%s: %s", moption.user_name, msg);
140
+  }
141
+}
142
+
143
+void cprintf(int l, mcomm *c, char *fmt, ...)
144
+{
145
+  char m[2048];
146
+  va_list arg;
147
+  if(!c)
148
+    return;
149
+  if(c->fd[0] == -1)
150
+    return;
151
+  if(c->loglevel >= l){
152
+    va_start(arg, fmt);
153
+    vsprintf(m, fmt, arg);
154
+    va_end(arg);
155
+    write(c->fd[0], m, strlen(m));
156
+    fsync(c->fd[0]);
157
+  }
158
+}
159
+
160
+int getrid()
161
+{
162
+  static int rid=0;
163
+  return(rid++);
164
+}
165
+
166
+int workend(mcomm *c)
167
+{
168
+  if(c){
169
+    if(c->working && !c->cpid){
170
+      c->working = 0;
171
+      if(moption.commpass && !c->authchk){
172
+        cprintf(0, c, "Password: \x1b]E");
173
+      }else{
174
+        cprintf(0,c,"> ");
175
+      }
176
+    }
177
+  }
178
+  return(0);
179
+}
180
+
181
+void mfdel(mfile *m)
182
+{
183
+  mfile *p;
184
+  mfile *n;
185
+  if(m){
186
+    if(p = (mfile *)m->prev)
187
+      p->next = m->next;
188
+    if(n = (mfile *)m->next)
189
+      n->prev = m->prev;
190
+    if(mftop[0] == m)
191
+      mftop[0] = n;
192
+    if(mftop[1] == m)
193
+      mftop[1] = n;
194
+    free(m);
195
+  }
196
+}
197
+
198
+mfile *mfnew()
199
+{
200
+  mfile *m;
201
+  if(m = (mfile *)malloc(sizeof(mfile))){
202
+    memset(m, 0, sizeof(mfile));
203
+    m->mdata.head.vproto = PROTOCOL_VERSION;
204
+    m->fd = -1;
205
+    m->retrycnt = MAKUO_SEND_RETRYCNT;
206
+    memcpy(&(m->addr), &(moption.maddr), sizeof(m->addr));
207
+  }
208
+  return(m);
209
+}
210
+
211
+mfile *mfadd(int n)
212
+{
213
+  mfile *m;
214
+  if(m = mfnew()){
215
+    if(!mftop[n]){
216
+      mftop[n] =m;
217
+    }else{
218
+      mfile *l;
219
+      for(l=mftop[n];l->next;l=l->next);
220
+      l->next = (void *)m;
221
+      m->prev = (void *)l;
222
+      m->next = NULL;
223
+    }
224
+  }
225
+  return(m);
226
+}
227
+
228
+mfile *mfins(int n)
229
+{
230
+  mfile *m;
231
+  if(m = mfnew()){
232
+    if(mftop[n]){
233
+      mftop[n]->prev = m;
234
+      m->next = mftop[n];
235
+    }
236
+    mftop[n] =m;
237
+  }
238
+  return(m);
239
+}
240
+
241
+mhost *member_add(struct in_addr *addr, mdata *data)
242
+{
243
+  int    f = 1;
244
+  int    l = 0;
245
+  mhost *t = NULL;
246
+  mping *p = NULL;
247
+  for(t=members;t;t=t->next)
248
+    if(!(f=memcmp(&t->ad, addr, sizeof(t->ad))))
249
+      break;
250
+  if(!t){
251
+    t = malloc(sizeof(mhost));
252
+    if(!t){
253
+      lprintf(0,"member_add: out of memory\n");
254
+      return(NULL);
255
+    }
256
+    memcpy(&t->ad, addr, sizeof(t->ad));
257
+    t->state = 0;
258
+    t->prev  = NULL;
259
+    t->next  = NULL;
260
+    if(members){
261
+      members->prev = t;
262
+      t->next = members;
263
+    }
264
+    members = t;
265
+    t->hostname[0] = 0;
266
+  }
267
+  if(data){
268
+    if(data->head.opcode == MAKUO_OP_PING || data->head.opcode == MAKUO_OP_PONG){
269
+      p = (mping *)data->data;
270
+      l = ntohs(p->hostnamelen);
271
+      data->p = p->data;
272
+      memcpy(t->hostname, data->p, l);
273
+      t->hostname[l] = 0;
274
+      data->p += l;
275
+      l = ntohs(p->versionlen);
276
+      memcpy(t->version,  data->p, l);
277
+      t->version[l] = 0;
278
+    }
279
+  }
280
+  if(f){
281
+    lprintf(0,"member_add: %s (%s)\n", inet_ntoa(t->ad), t->hostname);
282
+  }
283
+  mtimeget(&(t->lastrecv));
284
+  return(t);
285
+}
286
+
287
+void member_del(mhost *t)
288
+{
289
+  mfile *m;
290
+  mhost *p;
291
+  mhost *n;
292
+  if(!t)
293
+    return;
294
+  lprintf(0,"member_del: %s (%s)\n", inet_ntoa(t->ad), t->hostname);
295
+  if(p = (mhost *)t->prev)
296
+    p->next = t->next;
297
+  if(n = (mhost *)t->next)
298
+    n->prev = t->prev;
299
+  if(members == t)
300
+    members = n;
301
+  do{
302
+    for(m=mftop[1];m;m=m->next){
303
+      if(!memcmp(&(m->addr.sin_addr), &(t->ad), sizeof(m->addr.sin_addr))){
304
+        if(m->mdata.head.nstate == MAKUO_RECVSTATE_OPEN){
305
+          if(m->fd != -1){
306
+            close(m->fd);
307
+          }
308
+          m->fd = -1;
309
+          if(S_ISREG(m->fs.st_mode)){
310
+            mremove(moption.base_dir,m->tn);
311
+          }
312
+        }
313
+        lprintf(0,"member_del: mfile break %s\n", m->fn);
314
+        mfdel(m);
315
+        break;
316
+      }
317
+    }
318
+  }while(m);
319
+  free(t);
320
+}
321
+
322
+int seq_addmark(mfile *m, uint32_t lseq, uint32_t useq)
323
+{
324
+  int i,j;
325
+  int size;
326
+  void *n;
327
+
328
+  if(!m->mark){
329
+    m->markcount = 0;
330
+    m->marksize  = 512;
331
+    m->mark = malloc(sizeof(uint32_t) * m->marksize);
332
+  }
333
+  size = m->marksize;
334
+  while(size < m->markcount + useq - lseq)
335
+    size += 512;
336
+  if(size != m->marksize){
337
+    n = malloc(sizeof(uint32_t) * size);
338
+    memcpy(n, m->mark, sizeof(uint32_t) * m->marksize);
339
+    free(m->mark);
340
+    m->mark = n;
341
+    m->marksize = size;
342
+  }
343
+  for(i=lseq;i<useq;i++){
344
+    for(j=0;j<m->markcount;j++)
345
+      if(i == m->mark[j])
346
+        break;
347
+    if(j == m->markcount){
348
+      m->mark[m->markcount++] = i;
349
+    }
350
+  }
351
+  return(0);
352
+}
353
+
354
+int seq_delmark(mfile *m, uint32_t seq)
355
+{
356
+  int i;
357
+  int r = 0;
358
+  for(i=0;i<m->markcount;i++){
359
+    if(m->mark[i] == seq){
360
+      r = 1;
361
+      m->markcount--;
362
+      m->mark[i] = m->mark[m->markcount];
363
+    }
364
+  }
365
+  return(r);
366
+}
367
+
368
+int seq_popmark(mfile *m, int n)
369
+{
370
+  char *s;
371
+  char *d;
372
+  int size = m->markcount - n;
373
+  if(size > 0){
374
+    s = (char *)(m->mark + n);
375
+    d = (char *)(m->mark + 0);
376
+   memmove(d, s, size * sizeof(uint32_t));
377
+    m->markcount = size;
378
+  }else{
379
+    m->markcount = 0;
380
+  }
381
+}
382
+
383
+int ack_clear(mfile *m, int state)
384
+{
385
+  mhost *h;
386
+  for(h=members;h;h=h->next){
387
+    if(!m->sendto){
388
+      if(state == -1 || h->state == state)
389
+        h->state = MAKUO_RECVSTATE_NONE;
390
+    }else{
391
+      if(!memcmp(&(m->addr.sin_addr), &(h->ad), sizeof(m->addr.sin_addr))){
392
+        if(state == -1 || h->state == state){
393
+          h->state = MAKUO_RECVSTATE_NONE;
394
+          return(1);
395
+        }else{
396
+          return(0);
397
+        }
398
+      }
399
+    }
400
+  }
401
+  if(m->sendto)
402
+    return(-1);
403
+  return(0);
404
+}
405
+
406

                
407

                
408

                
409

                
410
+ *
411

                
412

                
413

                
414

                
415
+ *
416
+*/
417
+int ack_check(mfile *m, int state)
418
+{
419
+  mhost *h;
420
+  for(h=members;h;h=h->next){
421
+    if(!m->sendto){
422
+      if(h->state == state){
423
+        return(1);
424
+      }
425
+    }else{
426
+      if(!memcmp(&(m->addr.sin_addr), &(h->ad), sizeof(m->addr.sin_addr))){
427
+        if(h->state == state){
428
+          return(1);
429
+        }else{
430
+          return(0);
431
+        }
432
+      }
433
+    }
434
+  }
435
+  if(m->sendto)
436
+    return(-1);
437
+  return(0);
438
+}
439
+
440
+int linkcmp(mfile *m)
441
+{
442
+  ssize_t size;
443
+  char ln[PATH_MAX];
444
+  if(m){
445
+    size = readlink(m->fn, ln, PATH_MAX);
446
+    if(size != -1 && size < PATH_MAX){
447
+      ln[size] = 0;
448
+      if(!strcmp(m->ln, ln)){
449
+        return(MAKUO_RECVSTATE_SKIP);
450
+      }
451
+    }
452
+  }
453
+  return(MAKUO_RECVSTATE_UPDATE);
454
+}
455
+
456
+int statcmp(struct stat *s1, struct stat *s2)
457
+{
458
+  mode_t s1mode;
459
+  mode_t s2mode;
460
+
461
+  if((S_ISDIR(s1->st_mode)) && (S_ISDIR(s2->st_mode))){
462
+    s1mode = s1->st_mode & 0xFFF;
463
+    s2mode = s2->st_mode & 0xFFF;
464
+    if(s1mode != s2mode)
465
+      return(MAKUO_RECVSTATE_UPDATE);
466
+    if(s1->st_mtime != s2->st_mtime)
467
+      return(MAKUO_RECVSTATE_UPDATE);
468
+    return(MAKUO_RECVSTATE_SKIP);
469
+  }
470
+  if((S_ISREG(s1->st_mode)) && (S_ISREG(s2->st_mode))){
471
+    if(s1->st_size != s2->st_size)
472
+      return(MAKUO_RECVSTATE_UPDATE);
473
+    if(s1->st_mtime != s2->st_mtime)
474
+      return(MAKUO_RECVSTATE_UPDATE);
475
+    return(MAKUO_RECVSTATE_SKIP);
476
+  }
477
+  return(MAKUO_RECVSTATE_UPDATE);
478
+} 
479
+
480
+int is_dir(char *path)
481
+{
482
+  struct stat mstat;
483
+  if(!lstat(path,&mstat))
484
+    return(S_ISDIR(mstat.st_mode));
485
+  return(0);
486
+}
487
+
488
+int is_reg(char *path)
489
+{
490
+  struct stat mstat;
491
+  if(!lstat(path,&mstat))
492
+    return(S_ISREG(mstat.st_mode));
493
+  return(0);
494
+}
495
+
496
+void mtempname(char *base, char *fn, char *tn)
497
+{
498
+  struct stat  st;
499
+  struct timeb tb;
500
+  char path[PATH_MAX];
501
+  do{
502
+    ftime(&tb);
503
+    sprintf(tn, "%s.makuo%03u%03u", fn, getrid() % 1000,  (int)tb.millitm);
504
+    sprintf(path, "%s/%s", base, tn);
505
+  }while(lstat(tn, &st) != -1);
506
+}
507
+
508
+int mremove(char *base, char *name)
509
+{
510
+  DIR *d;
511
+  struct dirent *dent;
512
+  char path[PATH_MAX];
513
+  if(!base){
514
+    strcpy(path,name);
515
+  }else{
516
+    sprintf(path,"%s/%s", base, name);
517
+    lprintf(0,"mremove: %s\n",  path);
518
+  }
519
+  if(is_dir(path)){
520
+    if(d = opendir(path)){
521
+      while(dent=readdir(d)){
522
+        if(!strcmp(dent->d_name, "."))
523
+          continue;
524
+        if(!strcmp(dent->d_name, ".."))
525
+          continue;
526
+        mremove(path, dent->d_name);
527
+      }
528
+      closedir(d);
529
+    }
530
+  }
531
+  return(remove(path));
532
+}
533
+
534
+int mrename(char *base, char *oldname, char *newname)
535
+{
536
+  char oldpath[PATH_MAX];
537
+  char newpath[PATH_MAX];
538
+  char tmppath[PATH_MAX];
539
+  sprintf(oldpath,"%s/%s", base, oldname);
540
+  sprintf(newpath,"%s/%s", base, newname);
541
+  mtempname(base, newname, tmppath);
542
+  rename(newpath,tmppath);
543
+  if(rename(oldpath,newpath) == -1){
544
+    rename(tmppath, newpath);
545
+    return(-1);
546
+  }
547
+  mremove(NULL,tmppath);
548
+  return(0);
549
+}
550
+
551
+int mcreatedir(char *base, char *name, mode_t mode)
552
+{
553
+  char *p;
554
+  char buff[PATH_MAX];
555
+  char path[PATH_MAX];
556
+  strcpy(buff, name);
557
+  strcpy(path, base);
558
+  p = strtok(buff, "/");
559
+  while(p){
560
+    strcat(path, "/");
561
+    strcat(path, p);
562
+    if(p = strtok(NULL,"/")){
563
+      if(!is_dir(path)){
564
+        remove(path);
565
+        if(mkdir(path,mode) == -1){
566
+          return(-1);
567
+        }
568
+      }
569
+    }
570
+  }
571
+  return(0);
572
+}
573
+
574
+int mcreate(char *base, char *name, mode_t mode)
575
+{
576
+  int fd = -1;
577
+  char path[PATH_MAX];
578
+  if(!mcreatedir(base,name,0755)){
579
+    sprintf(path,"%s/%s",base,name);
580
+    fd = open(path, O_RDWR | O_CREAT | O_TRUNC, mode & 0xFFF);
581
+  }
582
+  return(fd);
583
+}
584
+
585
+int space_escape(char *str)
586
+{
587
+  int  r = 0;
588
+  char buff[PATH_MAX];
589
+  char *s = str;
590
+  char *d = buff;
591
+  
592
+  while(*s){
593
+    if(*s == ' '){
594
+      r++;
595
+      *(d++) = '\\';
596
+    }
597
+    *(d++) = *(s++);
598
+  }
599
+  *d = 0;
600
+  strcpy(str, buff);
601
+  return(r);
602
+}
603
+
0 604
new file mode 100644
... ...
@@ -0,0 +1,342 @@
0
+/*
1
+ * makuosan.c
2
+ * Multicast file translate system
3
+ *
4
+ */
5
+#include "makuosan.h"
6
+
7
+void usage()
8
+{
9
+  printf("makuosan (Multicast Advance Keep Update Overwrite Synchronization Always Network)\n");
10
+  printf("version %s\n\n", MAKUOSAN_VERSION);
11
+  printf("usage: makuosan [OPTION]\n");
12
+  printf("  -d num   # loglevel(0-9)\n");
13
+  printf("  -u uid   # user\n");
14
+  printf("  -g gid   # group\n");
15
+  printf("  -b dir   # base dir\n");
16
+  printf("  -p port  # port number       (default: 5000)\n");
17
+  printf("  -m addr  # multicast address (default: 224.0.0.108)\n");
18
+  printf("  -l addr  # listen address    (default: 0.0.0.0)\n");
19
+  printf("  -U path  # unix domain socket\n");
20
+  printf("  -k file  # key file (data encrypt)\n");
21
+  printf("  -K file  # key file (data encrypt and console password)\n");
22
+  printf("  -c       # chroot to base dir\n");
23
+  printf("  -n       # don't fork\n");
24
+  printf("  -r       # don't recv\n");
25
+  printf("  -s       # don't send\n");
26
+  printf("  -o       # don't listen (console off mode)\n");
27
+  printf("  -h       # help\n\n"); 
28
+  exit(0);
29
+}
30
+
31
+int chexit()
32
+{
33
+  char cwd[PATH_MAX];
34
+  if(moption.chroot){
35
+    /*----- chroot exit -----*/
36
+    mtempname("",".MAKUOWORK",cwd);
37
+    mkdir(cwd,0700);
38
+    chroot(cwd);
39
+    rmdir(cwd);
40
+    chdir("..");
41
+    getcwd(cwd,PATH_MAX);
42
+    while(strcmp("/", cwd)){
43
+      chdir("..");
44
+      getcwd(cwd,PATH_MAX);
45
+    }
46
+    chroot(".");
47
+  }
48
+  return(0);
49
+}
50
+
51
+int setguid(int uid, int gid)
52
+{
53
+  /*----- setgid -----*/
54
+  if(gid != getegid()){
55
+    if(setgroups(1, &gid) == -1){
56
+      return(-1);
57
+    }
58
+    if(setegid(gid) == -1){
59
+      return(-1);
60
+    }
61
+  }
62
+  /*----- setuid -----*/
63
+  if(uid != geteuid()){
64
+    if(seteuid(uid) == -1){
65
+      return(-1);
66
+    }
67
+  }  
68
+  return(0);
69
+}
70
+
71
+int restoreguid()
72
+{
73
+  if(getuid() != geteuid())
74
+    seteuid(getuid());
75
+  if(getgid() != getegid())
76
+    setegid(getgid());
77
+  return(0);
78
+}
79
+
80
+void recv_timeout(mfile *m)
81
+{
82
+  mhost *h;
83
+  if(m){
84
+    m->retrycnt = MAKUO_SEND_RETRYCNT;
85
+    do{
86
+      for(h=members;h;h=h->next){
87
+        if(h->state == MAKUO_RECVSTATE_NONE){
88
+          lprintf(0,"recv_timeout: %s(%s) timeout\n", inet_ntoa(h->ad), h->hostname);
89
+          member_del(h);
90
+          break;
91
+        }
92
+      }
93
+    }while(h); 
94
+  }
95
+}
96
+
97
+struct timeval *pingpong(int n)
98
+{
99
+  static struct timeval tv;
100
+  mfile *m = mfins(0);
101
+  mping *p = NULL;
102
+  char buff[HOST_NAME_MAX + 1];
103
+
104
+  if(!m){
105
+    lprintf(0, "pingpong: out of memmory\r\n");
106
+    return(0);
107
+  }
108
+  switch(n){
109
+    case 0:
110
+      m->mdata.head.opcode = MAKUO_OP_PING;
111
+      break;
112
+    case 1:
113
+      m->mdata.head.opcode = MAKUO_OP_PONG;
114
+      break;
115
+    case 2:
116
+      m->mdata.head.opcode = MAKUO_OP_EXIT;
117
+      break;
118
+  } 
119
+  m->mdata.head.reqid  = getrid();
120
+  m->mdata.head.seqno  = 0;
121
+  m->mdata.head.szdata = 0;
122
+  m->sendwait          = 0;
123
+  if(gethostname(buff, sizeof(buff)) == -1){
124
+    buff[0] = 0;
125
+  }
126
+  p = (mping *)(m->mdata.data);
127
+  p->hostnamelen = strlen(buff);
128
+  p->versionlen  = strlen(MAKUOSAN_VERSION);
129
+  m->mdata.head.szdata = sizeof(mping) + p->hostnamelen + p->versionlen;
130
+  m->mdata.p = p->data;
131
+  memcpy(m->mdata.p, buff, p->hostnamelen);
132
+  m->mdata.p += p->hostnamelen;
133
+  memcpy(m->mdata.p, MAKUOSAN_VERSION, p->versionlen);
134
+  m->mdata.p += p->versionlen;
135
+  p->hostnamelen = htons(p->hostnamelen);
136
+  p->versionlen  = htons(p->versionlen);
137
+  gettimeofday(&tv,NULL);
138
+  return(&tv);
139
+}
140
+
141
+int cleanup()
142
+{
143
+  mfile *m;
144
+  socklen_t namelen;
145
+  struct sockaddr_un addr;
146
+
147
+  /*----- send object -----*/
148
+  while(m=mftop[0])
149
+    mfdel(m);
150
+
151
+  /*----- recv object -----*/
152
+  while(m=mftop[1]){
153
+    if(m->mdata.head.nstate == MAKUO_RECVSTATE_OPEN){
154
+      if(m->fd != -1){
155
+        close(m->fd);
156
+        m->fd = -1;
157
+      }
158
+      if(S_ISREG(m->fs.st_mode)){
159
+        mremove(moption.base_dir,m->tn);
160
+      }
161
+    }
162
+    mfdel(m);
163
+  }
164
+
165
+  /*----- exit notify -----*/
166
+  pingpong(2);
167
+  msend(moption.mcsocket, mftop[0]);
168
+
169
+  /*----- unlink unix domain socket -----*/
170
+  namelen=sizeof(addr);
171
+  if(!getsockname(moption.lisocket, (struct sockaddr *)&addr, &namelen)){
172
+    if(addr.sun_family == AF_UNIX){
173
+      unlink(addr.sun_path);
174
+    }
175
+  }
176
+
177
+  /*----- close -----*/
178
+  close(moption.mcsocket);
179
+  close(moption.lisocket);
180
+  return(0);
181
+}
182
+
183
+int mcomm_accept(mcomm *c, fd_set *fds, int s)
184
+{
185
+  int i;
186
+  if(s == -1)
187
+    return(0);
188
+  if(!FD_ISSET(s,fds))
189
+    return(0);
190
+  for(i=0;i<MAX_COMM;i++)
191
+    if(c[i].fd[0] == -1)
192
+      break;
193
+  if(i==MAX_COMM){
194
+    close(accept(s, NULL, 0)); 
195
+    return(0);
196
+  }
197
+  c[i].addrlen = sizeof(c[i].addr);
198
+  c[i].fd[0] = accept(s, (struct sockaddr *)(&c[i].addr), &(c[i].addrlen));
199
+  lprintf(2, "mcomm_accept: accept from %s i=%d fd=%d\n", inet_ntoa(c[i].addr.sin_addr), i, c[i].fd[0]);
200
+  /*cprintf(0, &(c[i]),"\xff\xfd\x18\r");*/
201
+  c[i].working = 1;
202
+  return(0);
203
+}
204
+
205
+int mcomm_read(mcomm *c, fd_set *fds){
206
+  int i, j;
207
+  mfile *m;
208
+  for(i=0;i<MAX_COMM;i++){
209
+    for(j=0;j<2;j++){
210
+      if(c[i].fd[j] != -1){
211
+        if(FD_ISSET(c[i].fd[j], fds) || c[i].check[j]){
212
+          mexec(&c[i], j);
213
+        }
214
+      }
215
+    }
216
+    if(c[i].fd[1] == -1){
217
+      for(m=mftop[0];m;m=m->next){
218
+        if(m->comm == &c[i]){
219
+          break;
220
+        }
221
+      }
222
+      if(!m){
223
+        if(c[i].working && !c[i].cpid){
224
+          lprintf(9,"************* work end **************\n"); 
225
+          workend(&c[i]);
226
+        }
227
+      }
228
+    }
229
+  }
230
+  return(0);
231
+}
232
+
233
+int mcomm_fdset(mcomm *c, fd_set *fds)
234
+{
235
+  int i;
236
+  for(i=0;i<MAX_COMM;i++){
237
+    if(c[i].fd[0] != -1){
238
+      FD_SET(c[i].fd[0], fds);
239
+    }
240
+    if(c[i].fd[1] != -1){
241
+      FD_SET(c[i].fd[1], fds);
242
+    }else{
243
+      if(c[i].cpid){
244
+        if(waitpid(c[i].cpid, NULL, WNOHANG) == c[i].cpid){
245
+          lprintf(0,"mcomm_fdset: send complete\n");
246
+          c[i].cpid = 0;
247
+        }
248
+      }
249
+    }
250
+  }
251
+  return(0);
252
+}
253
+
254
+int ismsend(mfile *m)
255
+{
256
+  int r;
257
+
258
+  if(!m)
259
+    return(0);
260
+  if(!m->sendwait){
261
+    return(1);
262
+  }
263
+  r = ack_check(m,MAKUO_RECVSTATE_NONE);
264
+  if(r == -1){
265
+    m->mdata.head.seqno  = 0;
266
+    m->mdata.head.nstate = MAKUO_SENDSTATE_BREAK;
267
+    return(1);
268
+  }
269
+  if(!r){
270
+    m->sendwait = 0;
271
+    return(1);
272
+  }
273
+  if(mtimeout(&(m->lastsend), MAKUO_SEND_TIMEOUT)){
274
+    if(m->retrycnt){
275
+      return(1);
276
+    }else{
277
+      recv_timeout(m);
278
+    }
279
+  }
280
+  return(0);
281
+}
282
+
283
+/***** main loop *****/
284
+int mloop()
285
+{
286
+  fd_set rfds;
287
+  fd_set wfds;
288
+  struct timeval *lastpong;
289
+  struct timeval tv;
290
+  
291
+  gettimeofday(&curtime,NULL);
292
+  lastpong = pingpong(0);
293
+  while(loop_flag){
294
+    tv.tv_sec  = 1;
295
+    tv.tv_usec = 0;
296
+    FD_ZERO(&rfds);
297
+    FD_ZERO(&wfds);
298
+    gettimeofday(&curtime,NULL);
299
+    if(mtimeout(lastpong, MAKUO_PONG_INTERVAL))
300
+      lastpong = pingpong(1);
301
+    FD_SET(moption.mcsocket, &rfds);
302
+    if(moption.lisocket != -1)
303
+      FD_SET(moption.lisocket, &rfds);
304
+    if(mftop[0]){
305
+      tv.tv_sec  = 0;
306
+      tv.tv_usec = 10000;
307
+      if(ismsend(mftop[0]))
308
+        FD_SET(moption.mcsocket, &wfds);
309
+    }
310
+    mcomm_fdset(moption.comm, &rfds);
311
+    if(select(1024, &rfds, &wfds, NULL, &tv) < 0)
312
+      continue;
313
+    gettimeofday(&curtime,NULL);
314
+    if(FD_ISSET(moption.mcsocket,&wfds))
315
+      msend(moption.mcsocket, mftop[0]);
316
+    if(FD_ISSET(moption.mcsocket,&rfds))
317
+      mrecv(moption.mcsocket);
318
+    mrecv_gc();
319
+    mcomm_accept(moption.comm, &rfds, moption.lisocket);
320
+    mcomm_read(moption.comm, &rfds);
321
+  }
322
+  return(0);
323
+}
324
+
325
+void mexit()
326
+{
327
+  lprintf(0, "mexit: shutdown start\n");
328

                
329

                
330

                
331
+  lprintf(0, "mexit: shutdown complete\n");
332
+}
333
+
334
+int main(int argc, char *argv[])
335
+{
336
+  minit(argc,argv);
337
+  mloop();
338
+  mexit();
339
+  return(0);
340
+}
341
+
0 342
new file mode 100644
... ...
@@ -0,0 +1,272 @@
0
+#define MAKUOSAN_VERSION "0.8.5"
1
+#define PROTOCOL_VERSION 3
2
+#define _GNU_SOURCE
3
+#define _FILE_OFFSET_BITS 64
4
+#include <stdio.h>
5
+#include <unistd.h>
6
+#include <stdlib.h>
7
+#include <limits.h>
8
+#include <string.h>
9
+#include <fcntl.h>
10
+#include <time.h>
11
+#include <utime.h>
12
+#include <errno.h>
13
+#include <signal.h>
14
+#include <dirent.h>
15
+#include <getopt.h>
16
+#include <pwd.h>
17
+#include <grp.h>
18
+#include <poll.h>
19
+#include <libgen.h>
20
+#include <fnmatch.h>
21
+#include <stdarg.h>
22
+#include <syslog.h>
23
+#include <pthread.h>
24
+#include <sys/stat.h>
25
+#include <sys/types.h>
26
+#include <sys/socket.h>
27
+#include <sys/un.h>
28
+#include <sys/time.h>
29
+#include <sys/timeb.h>
30
+#include <arpa/inet.h>
31
+#include <netinet/in.h>
32
+#include <openssl/md5.h>
33
+#include <openssl/blowfish.h>
34
+
35
+/*----- limit -----*/
36
+#define MAX_COMM          8
37
+#define MAKUO_BUFFER_SIZE 1024
38
+
39
+/*----- default -----*/
40
+#define MAKUO_MCAST_ADDR  "224.0.0.108"
41
+#define MAKUO_MCAST_PORT  5000
42
+
43
+/*----- timeout -----*/
44

                
45

                
46

                
47

                
48
+#define MAKUO_RECV_GCWAIT   300000
49
+
50
+/*----- operation -----*/
51
+#define MAKUO_OP_PING 0
52
+#define MAKUO_OP_PONG 1
53
+#define MAKUO_OP_EXIT 2
54
+#define MAKUO_OP_ACK  3
55
+#define MAKUO_OP_FILE 4
56
+#define MAKUO_OP_MD5  5
57
+
58
+/*----- flags -----*/
59
+#define MAKUO_FLAG_CRYPT 1
60
+
61
+/*----- sendstatus -----*/
62
+#define MAKUO_SENDSTATE_STATINIT  0
63
+#define MAKUO_SENDSTATE_STAT      1
64
+#define MAKUO_SENDSTATE_OPENINIT  2
65
+#define MAKUO_SENDSTATE_OPEN      3
66
+#define MAKUO_SENDSTATE_MARKINIT  4
67
+#define MAKUO_SENDSTATE_MARK      5
68
+#define MAKUO_SENDSTATE_CLOSEINIT 6
69
+#define MAKUO_SENDSTATE_CLOSE     7
70
+#define MAKUO_SENDSTATE_ERROR     8
71
+#define MAKUO_SENDSTATE_BREAK     9
72
+
73
+/*----- recvstatus -----*/
74
+#define MAKUO_RECVSTATE_NONE       0
75
+#define MAKUO_RECVSTATE_UPDATE     1
76
+#define MAKUO_RECVSTATE_SKIP       2
77
+#define MAKUO_RECVSTATE_OPEN       3
78
+#define MAKUO_RECVSTATE_MARK       4
79
+#define MAKUO_RECVSTATE_CLOSE      5
80
+#define MAKUO_RECVSTATE_IGNORE     6
81
+#define MAKUO_RECVSTATE_READONLY   7
82
+#define MAKUO_RECVSTATE_MD5OK      10
83
+#define MAKUO_RECVSTATE_MD5NG      11
84
+#define MAKUO_RECVSTATE_OPENERROR  90
85
+#define MAKUO_RECVSTATE_READERROR  91
86
+#define MAKUO_RECVSTATE_WRITEERROR 92
87
+#define MAKUO_RECVSTATE_CLOSEERROR 93
88
+
89
+/*----- mexec mode -----*/
90
+#define MAKUO_MEXEC_SEND 0
91
+#define MAKUO_MEXEC_DRY  1
92
+#define MAKUO_MEXEC_MD5  2
93
+
94
+/*----- struct -----*/
95
+typedef struct
96
+{
97
+  uint8_t  vproto;
98
+  uint8_t  opcode;
99
+  uint8_t  nstate;
100
+  uint8_t  ostate;
101
+  uint16_t szdata;
102
+  uint16_t flags;
103
+  uint32_t reqid;
104
+  uint32_t seqno;
105
+  uint8_t  hash[16];
106
+}__attribute__((packed)) mhead;
107
+
108
+typedef struct
109
+{
110
+  uint32_t mode;
111
+  uint16_t uid; 
112
+  uint16_t gid;
113
+  uint32_t sizel;
114
+  uint32_t sizeh;
115
+  uint32_t mtime; 
116
+  uint32_t ctime;
117
+  uint16_t fnlen;
118
+  uint16_t lnlen; 
119
+}__attribute__((packed)) mstat;
120
+
121
+typedef struct
122
+{
123
+  uint8_t  hash[16];
124
+  uint16_t fnlen;
125
+  uint8_t  filename[0];
126
+}__attribute__((packed)) mhash;
127
+
128
+typedef struct
129
+{
130
+  uint16_t hostnamelen;
131
+  uint16_t versionlen;
132
+  uint8_t  data[0];
133
+}__attribute__((packed)) mping;
134
+
135
+typedef struct
136
+{
137
+  mhead head;
138
+  char  data[MAKUO_BUFFER_SIZE];
139
+  char *p;
140
+}__attribute__((packed)) mdata;
141
+
142
+typedef struct
143
+{
144
+  char *pattern;
145
+  void *prev;
146
+  void *next;
147
+} excludeitem;
148
+
149
+typedef struct
150
+{
151
+  int cpid;
152
+  int fd[2];
153
+  int size[2];
154
+  int argc[2];
155
+  int check[2];
156
+  int loglevel;
157
+  int working;
158
+  int authchk;
159
+  char cmdline[2][MAKUO_BUFFER_SIZE];
160
+  char parse[2][8][MAKUO_BUFFER_SIZE];
161
+  char readbuff[2][MAKUO_BUFFER_SIZE];
162
+  struct sockaddr_in addr;
163
+  socklen_t addrlen;
164
+  excludeitem *exclude;
165
+} mcomm;
166
+
167
+typedef struct
168
+{
169
+  int   fd;
170
+  char  fn[PATH_MAX];
171
+  char  tn[PATH_MAX];
172
+  char  ln[PATH_MAX];
173
+  uint32_t sendto;
174
+  uint32_t dryrun;
175
+  uint32_t retrycnt;
176
+  uint32_t sendwait;
177
+  uint32_t lickflag;
178
+  uint32_t recvcount;
179
+  uint32_t markcount;
180
+  uint32_t marksize;
181
+  uint32_t seqnomax;
182
+  mdata mdata;
183
+  mcomm *comm;
184
+  uint32_t *mark;
185
+  void  *prev;
186
+  void  *next;
187
+  struct stat fs;
188
+  struct sockaddr_in addr;
189
+  struct timeval lastsend;
190
+  struct timeval lastrecv;
191
+} mfile;
192
+
193
+typedef struct
194
+{
195
+  int state;
196
+  char hostname[HOST_NAME_MAX];
197
+  char version[32];
198
+  struct in_addr ad;
199
+  struct timeval lastrecv;
200
+  void *prev;
201
+  void *next;
202
+} mhost;
203
+
204
+typedef struct
205
+{
206
+  int chroot;
207
+  int dontrecv;
208
+  int dontsend;
209
+  int dontfork;
210
+  int loglevel;
211
+  int mcsocket;
212
+  int lisocket;
213
+  int cryptena;
214
+  int comm_ena;
215
+  int commpass;
216
+  struct sockaddr_in maddr;
217
+  struct sockaddr_in laddr;
218
+  struct sockaddr_un uaddr;
219
+  char base_dir[PATH_MAX];
220
+  char real_dir[PATH_MAX];
221
+  uid_t uid;
222
+  gid_t gid;
223
+  char group_name[64];
224
+  char user_name[64];
225
+  char password[2][16];
226
+  mcomm comm[MAX_COMM];
227
+} mopt;
228
+
229
+extern mfile *mftop[2];
230
+extern mhost *members;
231
+extern mopt moption;
232
+extern char *optarg;
233
+extern int optind;
234
+extern int opterr;
235
+extern int optopt;
236
+extern int loop_flag;
237
+extern char *tzname[2];
238
+extern long timezone;
239
+extern int daylight;
240
+extern char TZ[256];
241
+extern struct timeval curtime;
242
+extern BF_KEY EncKey;
243
+
244
+/*----- function -----*/
245
+void   lprintf(int l, char *fmt, ...);
246
+void   cprintf(int l, mcomm *c, char *fmt, ...);
247
+void   fdprintf(int s, char *fmt, ...);
248
+int    getrid();
249
+void   mfdel(mfile *m);
250
+mfile *mfadd(int n);
251
+mfile *mfins(int n);
252
+mhost *member_add(struct in_addr *addr, mdata *recvdata);
253
+void   member_del(mhost *h);
254
+void   mrecv(int s);
255
+void   msend(int s, mfile *m);
256
+int    seq_popmark(mfile *m, int n);
257
+int    seq_delmark(mfile *m, uint32_t seq);
258
+int    seq_addmark(mfile *m, uint32_t lseq, uint32_t useq);
259
+int    linkcmp(mfile *m);
260
+int    statcmp(struct stat *s1, struct stat *s2);
261
+int    mremove(char *base, char *name);
262
+int    mcreate(char *base, char *name, mode_t mode);
263
+int    mcreatedir(char *base, char *name, mode_t mode);
264
+int    space_escape(char *str);
265
+int    workend(mcomm *c);
266
+int    ack_clear(mfile *m, int state);
267
+int    ack_check(mfile *m, int state);
268
+int    mtimeget(struct timeval *tv);
269
+int    mtimeout(struct timeval *tf, uint32_t msec);
270
+excludeitem *mfnmatch(char *str, excludeitem *exclude);
271
+
0 272
new file mode 100644
... ...
@@ -0,0 +1,761 @@
0
+#include "makuosan.h"
1
+
2
+char *command_list[]={"quit",     /*  */
3
+                      "exit",     /*  */
4
+                      "bye",      /*  */
5
+                      "send",     /*  */
6
+                      "members",  /*  */
7
+                      "status",   /*  */
8
+                      "md5",      /*  */
9
+                      "echo",     /*  */
10
+                      "exclude",  /*  */
11
+                      "loglevel", /*  */
12
+                      "help",     /*  */
13
+                      NULL};      /*  */
14
+
15
+int mexec_scan_cmd(int fd, char *buff)
16
+{
17
+  int r;
18
+  int size;
19
+  char *cmd;
20
+  fd_set fds;
21
+  struct timeval tv;
22
+
23
+  cmd = buff;
24
+  size = strlen(buff);
25
+  while(loop_flag && size){
26
+    tv.tv_sec  = 1;
27
+    tv.tv_usec = 0;
28
+    FD_ZERO(&fds);
29
+    FD_SET(fd,&fds);
30
+    if(select(1024, NULL, &fds, NULL, &tv)<0)
31
+      continue;
32
+    if(FD_ISSET(fd,&fds)){
33
+      r = write(fd, cmd, size);
34
+      if(r == -1){
35
+        lprintf(0,"mexec_scan_cmd: commend write error! %s", buff);
36
+        return(-1);
37
+      }
38
+      size -= r;
39
+      cmd  += r;
40
+    }
41
+  }
42
+  return(0);
43
+}
44
+
45
+int mexec_scan_echo(int fd, char *fmt, ...)
46
+{
47
+  char buff[MAKUO_BUFFER_SIZE];
48
+  char comm[MAKUO_BUFFER_SIZE];
49
+  va_list arg;
50
+  va_start(arg, fmt);
51
+  vsprintf(buff, fmt, arg);
52
+  va_end(arg);
53
+  sprintf(comm, "echo %s\n", buff);
54
+  mexec_scan_cmd(fd, comm);
55
+  return(0);
56
+}
57
+
58
+int mexec_scan_send(int fd, char *path, char *sendhost, int mode)
59
+{
60
+  char buff[MAKUO_BUFFER_SIZE];
61
+  char comm[MAKUO_BUFFER_SIZE];
62
+
63
+  buff[0] = 0;
64
+  if(sendhost && *sendhost){
65
+    strcat(buff, " -t ");
66
+    strcat(buff, sendhost);
67
+    strcat(buff, " ");
68
+  }
69
+  switch(mode){
70
+    case MAKUO_MEXEC_SEND:
71
+      sprintf(comm, "send %s%s\r\n",    buff, path);
72
+      break;
73
+    case MAKUO_MEXEC_DRY:
74
+      sprintf(comm, "send -n %s%s\r\n", buff, path);
75
+      break;
76
+    case MAKUO_MEXEC_MD5:
77
+      sprintf(comm, "md5 %s%s\r\n",     buff, path);
78
+      break;
79
+  }
80
+  mexec_scan_cmd(fd, comm);
81
+  return(0);
82
+}
83
+
84
+int mexec_scan_dir(int fd, char *base, char *sendhost, int mode, mcomm *c, int baseflag)
85
+{
86
+  DIR *d;
87
+  struct dirent *dent;
88
+  char path[PATH_MAX];
89
+
90
+  d = opendir(base);
91
+  if(!d){
92
+    /* directory open error */
93
+    mexec_scan_echo(fd, "directory open error %s", base);
94
+  }else{
95
+    while(dent=readdir(d)){
96
+      if(!loop_flag)
97
+        break;
98
+      if(!strcmp(dent->d_name, "."))
99
+        continue;
100
+      if(!strcmp(dent->d_name, ".."))
101
+        continue;
102
+      if(baseflag){
103
+        sprintf(path, "%s/%s", base, dent->d_name);
104
+      }else{
105
+        strcpy(path, dent->d_name);
106
+      }
107
+      space_escape(path);
108
+      mexec_scan_child(fd, path, sendhost, mode, c);
109
+    }
110
+    closedir(d);
111
+  }
112
+  return(0);
113
+}
114
+
115
+int mexec_scan_child(int fd, char *base, char *sendhost, int mode, mcomm *c)
116
+{
117
+  char path[PATH_MAX];
118
+  if(*base == 0){
119
+    getcwd(path, PATH_MAX);
120
+    mexec_scan_dir(fd, path, sendhost, mode, c, 0);
121
+  }else{
122
+    /*----- exclude -----*/
123
+    sprintf(path, "%s/%s", moption.real_dir, base);
124
+    if(!mfnmatch(path, c->exclude)){
125
+      if(!is_dir(base)){
126
+        mexec_scan_send(fd, base, sendhost, mode);
127
+      }else{
128
+        /*----- exclude dir -----*/
129
+        strcat(path, "/");
130
+        if(mfnmatch(path, c->exclude))
131
+          return(0);
132
+        mexec_scan_dir(fd, base, sendhost, mode, c, 1);
133
+        if(loop_flag && (mode != MAKUO_MEXEC_MD5)){
134
+          mexec_scan_send(fd, base, sendhost, mode);
135
+        }
136
+      }
137
+    }
138
+  }
139
+  return(0);
140
+}
141
+
142
+int mexec_scan(mcomm *c, char *fn, mhost *h, int mode)
143
+{
144
+  int pid;
145
+  int p[2];
146
+  char sendhost[256];
147
+  char base[PATH_MAX];
148
+
149
+  if(pipe(p) == -1){
150
+    cprintf(0, c, "mexec_scan: pipe error\n");    
151
+    lprintf(0,    "mexec_scan: pipe error\n");    
152
+    return(-1);
153
+  }
154
+
155
+  base[0] = 0;
156
+  sendhost[0] = 0;
157
+  if(h)
158
+    strcpy(sendhost, h->hostname);
159
+  if(fn)
160
+    strcpy(base, fn);
161
+
162
+  pid=fork();
163
+  if(pid == -1){
164
+    close(p[0]);
165
+    close(p[1]);
166
+    cprintf(0, c, "mexec_scan: fork error\n");
167
+    lprintf(0,    "mexec_scan: fork error\n");
168
+    return(-1);
169
+  }
170
+  if(pid){
171
+    /* parent */
172
+    close(p[1]);
173
+    c->cpid  = pid;
174
+    c->fd[1] = p[0];
175
+    return(0);
176
+  }else{
177
+    /* child */
178
+    close(p[0]);
179
+    mexec_scan_child(p[1], base, sendhost, mode, c);
180
+    close(p[1]);
181
+    _exit(0);
182
+  }
183
+  return(0);
184
+}
185
+
186
+int mexec_close(mcomm *c, int n)
187
+{
188
+  mfile *m;
189
+
190
+  lprintf(2,"mexec_close: n=%d\n", n);
191
+  if(c->fd[n] != -1)
192
+    close(c->fd[n]);
193
+  c->fd[n]  = -1;
194
+  c->size[n] = 0;
195
+  c->authchk = 0;
196
+  if(!n){
197
+    c->loglevel = 0;
198
+    if(c->cpid){
199
+      kill(c->cpid, SIGTERM);
200
+      mexec_close(c, 1);
201
+    }
202
+    while(c->exclude){
203
+      mexec_exclude_del(c, c->exclude);
204
+    }
205
+    for(m=mftop[0];m;m=m->next){
206
+      if(m->comm == c){
207
+        m->comm = NULL;
208
+        lprintf(3, "mexec_close: clear %s\n", m->fn);
209
+      }
210
+    }
211
+  }
212
+  return(0);
213
+}
214
+
215
+int mexec_quit(mcomm *c, int n)
216
+{
217
+  mexec_close(c, n);
218
+  return(0);
219
+}
220
+
221
+int mexec_help(mcomm *c, int n)
222
+{
223
+  cprintf(0, c, "COMMAND:\n");
224
+  cprintf(0, c, "  quit\n");
225
+  cprintf(0, c, "  exclude [add|del] pattern\n");
226
+  cprintf(0, c, "  exclude list\n");
227
+  cprintf(0, c, "  exclude clear\n");
228
+  cprintf(0, c, "  send [-n] [-r] [-t host] [filename]\n");
229
+  cprintf(0, c, "  md5 [-r] [-t host] [filename]\n");
230
+  cprintf(0, c, "  loglevel num (0-9)\n");
231
+  cprintf(0, c, "  members\n");
232
+  cprintf(0, c, "  help\n");
233
+  return(0);
234
+}
235
+
236
+int mexec_send(mcomm *c, int n)
237
+{
238
+  int i;
239
+  ssize_t size;
240
+  char *argv[9];
241
+  char *fn = NULL;
242
+  mfile *m = NULL;
243
+  mhost *h = NULL;
244
+  int recursive = 0;
245
+  int mode = MAKUO_MEXEC_SEND;
246
+
247
+  if(moption.dontsend){
248
+    cprintf(0, c, "error: this server can't send\n");
249
+    return(0);
250
+  }
251
+  for(i=0;i<c->argc[n];i++)
252
+    argv[i] = c->parse[n][i];
253
+  argv[i] = NULL;
254
+  optind = 0;
255
+  while((i=getopt(c->argc[n], argv, "t:nr")) != -1){
256
+    switch(i){
257
+      case 'n':
258
+        mode = MAKUO_MEXEC_DRY;
259
+        break;
260
+      case 'r':
261
+        recursive = 1;
262
+        break;
263
+      case 't':
264
+        for(h=members;h;h=h->next)
265
+          if(!strcmp(h->hostname, optarg))
266
+            break;
267
+        if(!h){
268
+          cprintf(0, c, "%s is not contained in members\r\n", optarg);
269
+          return(0);
270
+        }
271
+        break;
272
+      case '?':
273
+        cprintf(0, c, "invalid option -- %c\r\n", optopt);
274
+        return(0); 
275
+    }
276
+  }
277
+
278
+  while(optind < c->argc[n])
279
+    fn = c->parse[n][optind++];
280
+
281
+  /*----- directory scan -----*/
282
+  if(recursive){
283
+    if(c->cpid){
284
+      cprintf(0, c, "recursive process active now!\n");
285
+      return(0);
286
+    }
287
+    lprintf(0, "mexec_send: cmd='%s'\n", c->cmdline[n]);
288
+    return(mexec_scan(c, fn, h, mode));
289
+  }
290
+  /*----- help -----*/
291
+  if(!fn){
292
+    cprintf(0, c, "send [-n] [-r] [-t host] [path]\r\n");
293
+    cprintf(0, c, "  -n  # dryrun\r\n");
294
+    cprintf(0, c, "  -r  # recursive\r\n");
295
+    cprintf(0, c, "  -t  # target host\r\n");
296
+    return(0);
297
+  }
298
+  /*----- send file -----*/
299
+  m = mfadd(0);
300
+  if(!m){
301
+	  lprintf(0, "mfadd: out of memorry\n");
302
+    return(0);
303
+	}
304
+	m->mdata.head.reqid   = getrid();
305
+	m->mdata.head.opcode    = MAKUO_OP_FILE;
306
+	m->mdata.head.seqno = 0;
307
+  m->mdata.head.nstate = MAKUO_SENDSTATE_STATINIT;
308
+	m->comm     = c;
309
+	m->sendwait = 0;
310
+  m->sendto   = 0;
311
+  m->dryrun   = (mode == MAKUO_MEXEC_DRY);
312
+  m->ln[0]    = 0;
313
+	strcpy(m->fn, fn);
314
+	if(lstat(fn, &m->fs) == -1){
315
+	  cprintf(0, c, "mexec_send: lstat() error %s\n", fn);
316
+		lprintf(1,    "mexec_send: lstat() error argc=%d cmd=%s\n", c->argc[n], c->cmdline[n]);
317
+    for(i=0;i<c->argc[n];i++)
318
+		  lprintf(1,    "mexec_send: read error argv[%d]=%s\n", i, c->parse[n][i]);
319
+		lprintf(0,    "mexec_send: read error file=%s\n", fn);
320
+		mfdel(m);
321
+    return(0);
322
+	}
323
+
324
+  /*----- send to address set -----*/
325
+  if(h){
326
+    m->sendto = 1;
327
+    memcpy(&(m->addr.sin_addr), &(h->ad), sizeof(m->addr.sin_addr));
328
+  }
329
+
330
+  /*----- readlink -----*/
331
+  if(S_ISLNK(m->fs.st_mode)){
332
+    size = readlink(m->fn, m->ln, PATH_MAX);
333
+    if(size >= 0 && size < PATH_MAX){
334
+      m->ln[size] = 0;
335
+    }else{
336
+		  cprintf(0, c, "stat: readlink error %s\n", fn);
337
+		  lprintf(0,    "stat: readlink error %s\n", fn);
338
+		  mfdel(m);
339
+    }
340
+  }  
341
+  return(0);
342
+}
343
+
344
+int mexec_members(mcomm *c, int n)
345
+{
346
+  int count = 0;
347
+  mhost *h;
348
+	for(h=members;h;h=h->next){
349
+    cprintf(0, c, "Ver%s: %s (%s)\n", h->version, inet_ntoa(h->ad), h->hostname);
350
+    count++;
351
+  }
352
+  cprintf(0, c, "Total: %d members\n", count);
353
+  return(0);
354
+}
355
+
356
+int mexec_echo(mcomm *c, int n)
357
+{
358
+  int i;
359
+  cprintf(0, c, "%s", c->parse[n][1]);
360
+  for(i=2;i<8;i++){
361
+    if(c->parse[n][i][0]){
362
+      cprintf(0, c, " %s", c->parse[n][i]);
363
+    }
364
+  }
365
+  cprintf(0, c, "\n");
366
+  return(0);
367
+}
368
+
369
+int mexec_loglevel(mcomm *c, int n)
370
+{
371
+  c->loglevel=atoi(c->parse[n][1]);
372
+  return(0);
373
+}
374
+
375
+int mexec_exclude_add(mcomm *c, char *pattern)
376
+{
377
+  excludeitem *e = malloc(sizeof(excludeitem));
378
+  
379
+  e->prev = NULL;
380
+  e->next = NULL;
381
+  if(c->exclude){
382
+    e->next = c->exclude;
383
+    c->exclude->prev = e;
384
+  }
385
+  c->exclude = e;
386
+  e->pattern = malloc(strlen(pattern)+1);
387
+  strcpy(e->pattern, pattern);
388
+  return(0);
389
+}
390
+
391
+int mexec_exclude_del(mcomm *c, excludeitem *e)
392
+{
393
+  excludeitem *p;
394
+  excludeitem *n;
395
+
396
+  if(!e)
397
+    return(0);
398
+  p = e->prev;
399
+  n = e->next;
400
+  if(p)
401
+    p->next=n;
402
+  if(n)
403
+    n->prev=p;
404
+  if(e == c->exclude)
405
+    c->exclude = n; 
406
+  free(e->pattern);
407
+  e->pattern = NULL;
408
+  e->prev = NULL;
409
+  e->next = NULL;
410
+  free(e);
411
+  return(0);
412
+}
413
+
414
+int mexec_exclude(mcomm *c, int n)
415
+{
416
+  excludeitem *e;
417
+  switch(c->argc[n]){
418
+    case 2:
419
+      if(!strcmp("list", c->parse[n][1])){
420
+        for(e=c->exclude;e;e=e->next){
421
+          cprintf(0,c,"%s\n", e->pattern);
422
+        }
423
+        return(0);
424
+      }
425
+      if(!strcmp("clear", c->parse[n][1])){
426
+        while(c->exclude){
427
+          mexec_exclude_del(c, c->exclude);
428
+        }
429
+        return(0);
430
+      }
431
+      break;
432
+
433
+    case 3:
434
+      if(!strcmp("add", c->parse[n][1])){
435
+        for(e=c->exclude;e;e=e->next){
436
+          if(!strcmp(e->pattern, c->parse[n][2])){
437
+            break;
438
+          }
439
+        }
440
+        if(!e){
441
+          mexec_exclude_add(c, c->parse[n][2]);
442
+          return(0);
443
+        }
444
+      }
445
+      if(!strcmp("del", c->parse[n][1])){
446
+        for(e=c->exclude;e;e=e->next){
447
+          if(!strcmp(e->pattern, c->parse[n][2])){
448
+            mexec_exclude_del(c, e);
449
+            return(0);
450
+          }
451
+        }
452
+        cprintf(0,c,"pattern not found %s\n", c->parse[n][2]);
453
+      }
454
+      break;
455
+  }
456
+  cprintf(0,c,"usage: exclude [add|del] pattern\n");
457
+  cprintf(0,c,"       exclude list\n");
458
+  cprintf(0,c,"       exclude clear\n");
459
+  return(0);
460
+}
461
+
462
+int mexec_status(mcomm *c, int n)
463
+{
464
+  int count;
465
+  mfile  *m;
466
+  cprintf(0,c,"MAKUOSAN version %s\n", MAKUOSAN_VERSION);
467
+  
468
+  count = 0;
469
+  for(m=mftop[0];m;m=m->next)
470
+    count++;
471
+  cprintf(0,c,"send object: %d\n", count);
472
+
473
+  count = 0;
474
+  for(m=mftop[1];m;m=m->next)
475
+    count++;
476
+  cprintf(0,c,"recv object: %d\n", count);
477
+  return(0);
478
+}
479
+
480
+int mexec_md5(mcomm *c, int n)
481
+{
482
+  int i;
483
+  int r;
484
+  ssize_t size;
485
+  char *argv[9];
486
+  char *fn = NULL;
487
+  mfile *m = NULL;
488
+  mhost *t = NULL;
489
+  mhash *h = NULL;
490
+  int recursive = 0;
491
+
492
+  for(i=0;i<c->argc[n];i++)
493
+    argv[i] = c->parse[n][i];
494
+  argv[i] = NULL;
495
+  optind = 0;
496
+  while((i=getopt(c->argc[n], argv, "t:r")) != -1){
497
+    switch(i){
498
+      case 'r':
499
+        recursive = 1;
500
+        break;
501
+      case 't':
502
+        for(t=members;t;t=t->next)
503
+          if(!strcmp(t->hostname, optarg))
504
+            break;
505
+        if(!t){
506
+          cprintf(0, c, "%s is not contained in members\r\n", optarg);
507
+          return(0);
508
+        }
509
+        break;
510
+      case '?':
511
+        cprintf(0, c, "invalid option -- %c\r\n", optopt);
512
+        return(0); 
513
+    }
514
+  }
515
+
516
+  while(optind < c->argc[n])
517
+    fn = c->parse[n][optind++];
518
+
519
+  /*----- directory scan -----*/
520
+  if(recursive){
521
+    if(c->cpid){
522
+      cprintf(0, c, "recursive process active now!\n");
523
+      return(0);
524
+    }
525
+    lprintf(0, "mexec_md5: cmd='%s'\n", c->cmdline[n]);
526
+    return(mexec_scan(c, fn, t, MAKUO_MEXEC_MD5));
527
+  }
528
+
529
+  /*----- help -----*/
530
+  if(!fn){
531
+    cprintf(0, c,"usage: md5 [-t host] [-r] [path]\r\n");
532
+    cprintf(0, c, "  -r  # dir recursive\r\n");
533
+    cprintf(0, c, "  -t  # target host\r\n");
534
+    return(0);
535
+  }
536
+
537
+  /*----- create mfile -----*/
538
+  m = mfadd(0);
539
+  if(!m){
540
+	  lprintf(0, "mexec_md5: out of memorry\n");
541
+	  cprintf(0, c, "out of memorry\n");
542
+    return(0);
543
+	}
544
+	m->mdata.head.reqid  = getrid();
545
+	m->mdata.head.seqno  = 0;
546
+	m->mdata.head.opcode = MAKUO_OP_MD5;
547
+  m->mdata.head.nstate = MAKUO_SENDSTATE_OPENINIT;
548
+	m->comm     = c;
549
+	m->sendwait = 0;
550
+  m->sendto   = 0;
551
+  m->dryrun   = 0;
552
+  m->ln[0]    = 0;
553
+	strcpy(m->fn, fn);
554
+
555
+  /*----- open -----*/
556
+  m->fd = open(m->fn, O_RDONLY);
557
+  if(m->fd == -1){
558
+	  lprintf(0, "mexec_md5: file open error %s\n", m->fn);
559
+    cprintf(0, c, "file open error: %s\r\n", m->fn);
560
+    mfdel(m);
561
+    return(0);
562
+  }
563
+
564
+  /*----- md5 -----*/
565
+  h = (mhash *)m->mdata.data;
566
+  h->fnlen = strlen(m->fn);
567
+  r = md5sum(m->fd, h->hash);
568
+  close(m->fd);
569
+  m->fd = -1;
570
+  if(r == -1){
571
+	  lprintf(0, "mexec_md5: file read error %s\n", m->fn);
572
+    cprintf(0, c, "file read error %s\n", m->fn);
573
+    mfdel(m);
574
+    return(0);
575
+  }
576
+  memcpy(h->filename, m->fn, h->fnlen);
577
+  m->mdata.head.szdata = sizeof(mhash) + h->fnlen;
578
+  h->fnlen = htons(h->fnlen);
579
+
580
+  /*----- sendto address -----*/
581
+  if(t){
582
+    m->sendto = 1;
583
+    memcpy(&(m->addr.sin_addr), &(t->ad), sizeof(m->addr.sin_addr));
584
+  }
585
+  return(0);
586
+}
587
+
588
+int mexec_password(char *password)
589
+{
590
+  unsigned char digest[16];
591
+  MD5_CTX ctx;
592
+  MD5_Init(&ctx);
593
+  MD5_Update(&ctx, password, strlen(password));
594
+  MD5_Final(digest, &ctx);
595
+  if(!memcmp(moption.password[0], digest, 16)){ 
596
+    return(1);
597
+  }
598
+  return(0);
599
+}
600
+
601
+int mexec_parse(mcomm *c, int n)
602
+{
603
+  int i;
604
+  int j;
605
+  int l;
606
+  char *p;
607
+  char cmd[MAKUO_BUFFER_SIZE];
608
+
609
+  c->argc[n] = 0;
610
+  p = c->cmdline[n];
611
+  for(i=0;i<8;i++)
612
+    c->parse[n][i][0]=0;
613
+  for(i=0;i<c->size[n];i++){
614
+    *p = c->readbuff[n][i];
615
+    if(c->readbuff[n][i] == '\r')
616
+      *p = 0;
617
+    if(c->readbuff[n][i] == '\n'){
618
+      *p = 0;
619
+      break;
620
+    }
621
+    p++;
622
+  }
623
+  c->check[n] = 0;
624
+  if(i == c->size[n])
625
+    return(-1);
626
+  i++;
627
+  memmove(c->readbuff[n], c->readbuff[n] + i, MAKUO_BUFFER_SIZE - i);
628
+  if(c->size[n] -= i)
629
+    c->check[n] = 1;
630
+  if(moption.commpass && !c->authchk){
631
+    c->authchk = mexec_password(c->cmdline[n]);
632
+    c->cmdline[n][0]=0;
633
+    cprintf(0, c,"\r");
634
+  }else{
635
+    lprintf(8, "mexec_parse: %s\n", c->cmdline[n]);
636
+    strcpy(cmd, c->cmdline[n]);
637
+    p=strtok(cmd, " ");
638
+    for(j=0;j<8;j++){
639
+      if(!p)
640
+        break;
641
+      strcpy(c->parse[n][j], p);
642
+      if(j){
643
+        if(l = strlen(c->parse[n][j-1])){
644
+          if(c->parse[n][j-1][l-1] == '\\'){
645
+            c->parse[n][j-1][l-1] = 0;
646
+            strcat(c->parse[n][j-1], " ");
647
+            strcat(c->parse[n][j-1], p);
648
+            c->parse[n][j][0] = 0;
649
+            j--;
650
+          }
651
+        }
652
+      }
653
+      p = strtok(NULL, " ");
654
+    }
655
+    c->argc[n] = j;
656
+  }
657
+  for(i=0;command_list[i];i++)
658
+    if(!strcmp(c->parse[n][0], command_list[i]))
659
+      break;
660
+  return(i);
661
+}
662
+
663
+int mexec(mcomm *c, int n)
664
+{
665
+  int r;
666
+  int size = MAKUO_BUFFER_SIZE - c->size[n];
667
+  char *buff = c->readbuff[n] + c->size[n];
668
+  mfile *m = NULL;
669
+  int count = 0;
670
+
671
+  if(n == 0 && c->working){
672
+    c->size[n] = 0;
673
+    r = read(c->fd[n], buff, size);
674
+    if(r>0){
675
+    }else{
676
+      if(r == -1){
677
+        lprintf(0, "mexec: read error n=%d\n",n);
678
+      }
679
+      mexec_close(c, n);
680
+    }
681
+    return(-1);
682
+  }
683
+  if(n == 1)
684
+    for(m=mftop[0];m;m=m->next)
685
+      if(m->comm == c)
686
+        if(count++ == 8)
687
+          return(-1);
688
+
689
+  if(!size){
690
+    lprintf(0, "mexec: buffer over fllow n=%d\n",n);
691
+    mexec_close(c, n);
692
+    return(-1);
693
+  }
694
+
695
+  if(!c->check[n]){
696
+    r = read(c->fd[n], buff, size);
697
+    if(r > 0){
698
+      c->size[n] += r;
699
+    }else{
700
+      if(r < 0){
701
+        lprintf(0, "mexec: read error n=%d\n",n);
702
+      }
703
+      mexec_close(c, n);
704
+      return(-1);
705
+    }
706
+  }
707
+
708
+  if((r = mexec_parse(c, n)) == -1)
709
+    return(-1); 
710
+
711
+  if(!command_list[r]){
712
+    if(c->parse[n][0][0]){
713
+      cprintf(0, c, "mexec: command error '%s'\n", c->parse[n][0]);
714
+    }
715
+    if(moption.commpass && !c->authchk){
716
+      cprintf(0,c,"Password: \x1b]E");
717
+    }else{
718
+      cprintf(0, c, "> ");
719
+    }
720
+  }else{
721
+    c->working = 1;
722
+
723
+    if(!strcmp("help",command_list[r]))
724
+      return(mexec_help(c,n));
725
+
726
+    if(!strcmp("quit",command_list[r]))
727
+      return(mexec_quit(c,n));
728
+
729
+    if(!strcmp("exit",command_list[r]))
730
+      return(mexec_quit(c,n));
731
+
732
+    if(!strcmp("bye",command_list[r]))
733
+      return(mexec_quit(c,n));
734
+
735
+    if(!strcmp("send",command_list[r]))
736
+      return(mexec_send(c,n));
737
+
738
+    if(!strcmp("md5",command_list[r]))
739
+      return(mexec_md5(c,n));
740
+
741
+    if(!strcmp("members",command_list[r]))
742
+      return(mexec_members(c,n));
743
+
744
+    if(!strcmp("echo",command_list[r]))
745
+      return(mexec_echo(c,n));
746
+
747
+    if(!strcmp("loglevel",command_list[r]))
748
+      return(mexec_loglevel(c,n));
749
+
750
+    if(!strcmp("exclude",command_list[r]))
751
+      return(mexec_exclude(c,n));
752
+
753
+    if(!strcmp("status",command_list[r]))
754
+      return(mexec_status(c,n));
755
+
756
+    c->working = 0;
757
+  }
758
+  return(r);
759
+}
760
+
0 761
new file mode 100644
... ...
@@ -0,0 +1,473 @@
0
+/*
1
+ *  minit.c
2
+ *  まくお起動時の処理
3
+ *  各関数の役割は最後のminit()関数のコメント参照
4
+ *
5
+ */
6
+#include "makuosan.h"
7
+
8
+void signal_handler(int n)
9
+{
10
+  switch(n){
11
+    case SIGINT:
12
+    case SIGTERM:
13
+      loop_flag = 0;
14
+      break;
15
+    case SIGPIPE:
16
+      break;
17
+    case SIGUSR1:
18
+      if(moption.loglevel<9){
19
+        moption.loglevel++;
20
+        lprintf(0,"signal_handler: loglevel=%d\n", moption.loglevel);
21
+      }
22
+      break;
23
+    case SIGUSR2:
24
+      if(moption.loglevel>0){
25
+        moption.loglevel--;
26
+        lprintf(0,"signal_handler: loglevel=%d\n", moption.loglevel);
27
+      }
28
+      break;
29
+  }
30
+}
31
+
32
+static void minit_option_setdefault()
33
+{
34
+  int i;
35
+  memset(&moption, 0, sizeof(moption));
36
+  moption.maddr.sin_family      = AF_INET;
37
+  moption.maddr.sin_addr.s_addr = inet_addr(MAKUO_MCAST_ADDR);
38
+  moption.maddr.sin_port        = htons(MAKUO_MCAST_PORT);
39
+  moption.laddr.sin_family      = AF_INET;
40
+  moption.laddr.sin_addr.s_addr = INADDR_ANY;
41
+  moption.laddr.sin_port        = htons(MAKUO_MCAST_PORT);
42
+  moption.uaddr.sun_family      = AF_UNIX;
43
+  moption.uaddr.sun_path[0]     = 0;
44
+  moption.loglevel              = 0;
45
+  moption.dontrecv              = 0;
46
+  moption.dontsend              = 0;
47
+  moption.dontfork              = 0;
48
+  moption.cryptena              = 0;
49
+  moption.comm_ena              = 1;
50
+  moption.commpass              = 0;
51
+  moption.chroot                = 0;
52
+  moption.uid                   = geteuid();
53
+  moption.gid                   = getegid();
54
+  getcwd(moption.base_dir, PATH_MAX);
55
+  for(i=0;i<MAX_COMM;i++){
56
+    moption.comm[i].fd[0] = -1;
57
+    moption.comm[i].fd[1] = -1;
58
+  }
59
+}
60
+
61
+static void minit_option_getenv()
62
+{
63
+  char *env;
64
+  struct passwd *pw;
65
+  struct group  *gr;
66
+
67
+  if(env=getenv("MAKUOSAN_PORT")){
68
+    moption.maddr.sin_port = htons(atoi(env));
69
+    moption.laddr.sin_port = htons(atoi(env));
70
+  }
71
+  if(env=getenv("MAKUOSAN_USER")){
72
+    if(*env >= '0' && *env <='9'){
73
+      moption.uid = atoi(env);
74
+    }else{
75
+      if(pw = getpwnam(env)){
76
+        moption.uid = pw->pw_uid;
77
+        moption.gid = pw->pw_gid;
78
+      }else{
79
+        lprintf(0,"minit_option_getenv: getpwnam error %s\n", env);
80
+        exit(1);
81
+      }
82
+    }
83
+  }
84
+  if(env=getenv("MAKUOSAN_GROUP")){
85
+    if(*env >= '0' && *env <='9'){
86
+      moption.gid = atoi(env);
87
+    }else{
88
+      if(gr = getgrnam(env)){
89
+        moption.gid = gr->gr_gid;
90
+      }else{
91
+        lprintf(0,"minit_option_getenv: getgrnam error %s\n", env);
92
+        exit(1);
93
+      }
94
+    }
95
+  }
96
+  if(env=getenv("MAKUOSAN_SOCK")){
97
+    strcpy(moption.uaddr.sun_path, env);
98
+  }
99
+}
100
+
101
+static void minit_signal()
102
+{
103
+  struct sigaction sig;
104
+  memset(&sig, 0, sizeof(sig));
105
+  sig.sa_handler = signal_handler;
106
+  if(sigaction(SIGINT,  &sig, NULL) == -1){
107
+    lprintf(0, "minit_signal: sigaction error SIGINT\n");
108
+    exit(1);
109
+  }
110
+  if(sigaction(SIGTERM, &sig, NULL) == -1){
111
+    lprintf(0, "minit_signal: sigaction error SIGTERM\n");
112
+    exit(1);
113
+  }
114
+  if(sigaction(SIGPIPE, &sig, NULL) == -1){
115
+    lprintf(0, "minit_signal: sigaction error SIGPIPE\n");
116
+    exit(1);
117
+  }
118
+  if(sigaction(SIGUSR1, &sig, NULL) == -1){
119
+    lprintf(0, "minit_signal: sigaction error SIGUSR1\n");
120
+    exit(1);
121
+  }
122
+  if(sigaction(SIGUSR2, &sig, NULL) == -1){
123
+    lprintf(0, "minit_signal: sigaction error SIGUSR2\n");
124
+    exit(1);
125
+  }
126
+}
127
+
128
+static void minit_password(char *filename, int n)
129
+{
130
+  int i;
131
+  int f;
132
+  char buff[64];
133
+  MD5_CTX ctx;
134
+
135
+  f = open(filename, O_RDONLY);
136
+  if(f == -1){
137
+    lprintf(0, "minit_password: file open error %s\n", optarg);
138
+    exit(1);
139
+  }
140
+  memset(buff, 0, sizeof(buff));
141
+  i = read(f, buff, sizeof(buff) - 1);
142
+  if(i == -1){
143
+    lprintf(0, "minit_password: file read error %s\n", optarg);
144
+    exit(1);
145
+  }
146
+  if(i < 4){
147
+    lprintf(0, "minit_password: password too short %s\n", optarg);
148
+    exit(1);
149
+  }
150
+  while(i--){
151
+    if(buff[i] == '\r')
152
+      buff[i] = 0;
153
+    if(buff[i] == '\n')
154
+      buff[i] = 0;
155
+  }
156
+  MD5_Init(&ctx);
157
+  MD5_Update(&ctx, buff, strlen(buff));
158
+  MD5_Final(moption.password[n], &ctx);
159
+  if(read(f, buff, sizeof(buff))){
160
+    lprintf(0, "minit_password: password too long %s\n", optarg);
161
+    exit(1);
162
+  }
163
+  close(f);
164
+}
165
+
166
+static void minit_getopt(int argc, char *argv[])
167
+{
168
+  int r;
169
+  struct passwd *pw;
170
+  struct group  *gr;
171
+
172
+  while((r=getopt(argc, argv, "u:g:d:b:p:m:l:U:k:K:hnsroc")) != -1){
173
+    switch(r){
174
+      case 'h':
175
+        usage();
176
+
177
+      case 'n':
178
+        moption.dontfork = 1;
179
+        break;
180
+
181
+      case 's':
182
+        moption.dontsend = 1;
183
+        break;
184
+
185
+      case 'r':
186
+        moption.dontrecv = 1;
187
+        break;
188
+
189
+      case 'o':
190
+        moption.comm_ena = 0;
191
+        break;
192
+
193
+      case 'c':
194
+        moption.chroot = 1;
195
+        break;
196
+
197
+      case 'd':
198
+        moption.loglevel = atoi(optarg);
199
+        break;
200
+
201
+      case 'u':
202
+        if(*optarg >= '0' && *optarg <='9'){
203
+          moption.uid = atoi(optarg);
204
+        }else{
205
+          if(pw = getpwnam(optarg)){
206
+            moption.uid = pw->pw_uid;
207
+            moption.gid = pw->pw_gid;
208
+          }
209
+        }
210
+        break;
211
+
212
+      case 'g':
213
+        if(*optarg >= '0' && *optarg <='9'){
214
+          moption.gid = atoi(optarg);
215
+        }else{
216
+         if(gr = getgrnam(optarg)){
217
+            moption.gid = gr->gr_gid;
218
+          }
219
+        }
220
+        break;
221
+
222
+      case 'b':
223
+        realpath(optarg, moption.base_dir);
224
+        break;
225
+
226
+      case 'm':
227
+        moption.maddr.sin_addr.s_addr = inet_addr(optarg);
228
+        break;
229
+
230
+      case 'l':
231
+        moption.laddr.sin_addr.s_addr = inet_addr(optarg);
232
+        break;
233
+
234
+      case 'U':
235
+        strcpy(moption.uaddr.sun_path, optarg);
236
+        break;
237
+
238
+      case 'p':
239
+        moption.laddr.sin_port = htons(atoi(optarg));
240
+        moption.maddr.sin_port = htons(atoi(optarg));
241
+        break;
242
+
243
+      case 'K':
244
+        moption.commpass = 1;
245
+        minit_password(optarg, 0);
246
+        break;
247
+
248
+      case 'k':
249
+        moption.cryptena = 1;
250
+        minit_password(optarg, 1);
251
+        break;
252
+
253
+      case '?':
254
+        exit(1);
255
+    }
256
+  }
257
+  if(pw=getpwuid(moption.uid)){
258
+    strcpy(moption.user_name, pw->pw_name);
259
+  }
260
+  if(gr=getgrgid(moption.gid)){
261
+    strcpy(moption.group_name,gr->gr_name);
262
+  }
263
+}
264
+
265
+static void minit_syslog()
266
+{
267
+  openlog("makuosan", LOG_NDELAY, LOG_DAEMON);
268
+}
269
+
270
+static void minit_socket()
271
+{
272
+  int  s;
273
+  int  reuse =  1;
274
+  char lpen  =  0;
275
+  char mttl  =  1;
276
+  struct ip_mreq mg;
277
+  struct sockaddr_in addr;
278
+  mg.imr_multiaddr.s_addr = moption.maddr.sin_addr.s_addr;
279
+  mg.imr_interface.s_addr = INADDR_ANY;
280
+  addr.sin_family         = AF_INET;
281
+  addr.sin_port           = moption.maddr.sin_port; 
282
+  addr.sin_addr.s_addr    = INADDR_ANY;
283
+
284
+  s=socket(AF_INET, SOCK_DGRAM, 0);
285
+  if(s == -1){
286
+    lprintf(0, "minit_socket: can't create multicast socket\n");
287
+    exit(1);
288
+  }
289
+  if(bind(s, (struct sockaddr*)&addr, sizeof(addr)) == -1){
290
+    lprintf(0, "minit_socket: bind error\n");
291
+    exit(1);
292
+  }
293
+  if(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&mg, sizeof(mg)) == -1){
294
+    lprintf(0, "minit_socket: IP_ADD_MEMBERSHIP error\n");
295
+    exit(1);
296
+  }
297
+  if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,   (void *)&mg.imr_interface.s_addr, sizeof(mg.imr_interface.s_addr)) == -1){
298
+    lprintf(0, "minit_socket: IP_MULTICAST_IF error\n");
299
+    exit(1);
300
+  }
301
+  if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, (void *)&lpen, sizeof(lpen)) == -1){
302
+    lprintf(0, "minit_socket: IP_MULTICAST_LOOP error\n");
303
+    exit(1);
304
+  }
305
+  if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,  (void *)&mttl, sizeof(mttl)) == -1){
306
+    lprintf(0, "minit_socket: IP_MULTICAST_TTL error\n");
307
+    exit(1);
308
+  }
309
+  moption.mcsocket = s;
310
+}
311
+
312
+static void minit_console()
313
+{
314
+  int s;
315
+  int reuse = 1;
316
+
317
+  if(!moption.comm_ena){
318
+    moption.lisocket = -1;
319
+    return;
320
+  }
321
+
322
+  if(moption.uaddr.sun_path[0]){
323
+    s=socket(AF_UNIX,SOCK_STREAM,0);
324
+    if(!connect(s, (struct sockaddr*)&moption.uaddr, sizeof(moption.uaddr))){
325
+      lprintf(0, "minit_console: can't create %s\n", moption.uaddr.sun_path);
326
+      exit(1);
327
+    }
328
+    close(s);
329
+    unlink(moption.uaddr.sun_path);
330
+    s=socket(AF_UNIX,SOCK_STREAM,0);
331
+    if(s == -1){
332
+      lprintf(0, "minit_console: can't create listen socket\n");
333
+      exit(1);
334
+    }
335
+    if(bind(s, (struct sockaddr*)&moption.uaddr, sizeof(moption.uaddr)) == -1){
336
+      lprintf(0, "minit_console: bind error\n");
337
+      exit(1);
338
+    }
339
+    chmod(moption.uaddr.sun_path , S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
340
+    chown(moption.uaddr.sun_path , moption.uid, moption.gid);
341
+  }else{
342
+    s=socket(AF_INET,SOCK_STREAM,0);
343
+    if(s == -1){
344
+      lprintf(0, "minit_console: can't create listen socket\n");
345
+      exit(1);
346
+    }
347
+    if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) == -1){
348
+      lprintf(0, "minit_console: SO_REUSEADDR error\n");
349
+      exit(1);
350
+    }
351
+    if(bind(s, (struct sockaddr*)&moption.laddr, sizeof(moption.laddr)) == -1){
352
+      lprintf(0, "minit_console: bind error\n");
353
+      exit(1);
354
+    }
355
+  }
356
+  if(listen(s,5) == -1){
357
+    lprintf(0, "minit_console: listen error\n");
358
+    exit(1);
359
+  }
360
+  moption.lisocket = s;
361
+}
362
+
363
+static void minit_chdir()
364
+{
365
+  if(chdir(moption.base_dir) == -1){
366
+    lprintf(0, "minit_chdir: can't chdir %s\n", moption.base_dir);
367
+    exit(1);
368
+  }
369
+  getcwd(moption.real_dir, PATH_MAX);
370
+}
371
+
372
+static void minit_chroot()
373
+{
374
+  if(moption.chroot){
375
+    tzset();
376
+    sprintf(TZ,"%s%d",tzname[0],timezone/3600);
377
+    setenv("TZ",TZ,0);
378
+    if(chroot(moption.base_dir) == -1){
379
+      lprintf(0, "minit_chroot: can't chroot %s\n", moption.base_dir);
380
+      exit(0);
381
+    }
382
+  }
383
+  getcwd(moption.base_dir, PATH_MAX);
384
+}
385
+
386
+static void minit_setguid()
387
+{
388
+  if(setguid(moption.uid, moption.gid) == -1){
389
+    lprintf(0, "minit_setguid: can't setguid %d:%d\n", moption.uid, moption.gid);
390
+    exit(0);
391
+  }
392
+}
393
+
394
+static void minit_daemonize()
395
+{
396
+  int pid;
397
+  if(moption.dontfork)
398
+    return;
399
+
400
+  pid = fork();
401
+  if(pid == -1){
402
+    lprintf(0,"minit_daemonize: can't fork()\n");
403
+    exit(1); 
404
+  }
405
+  if(pid)
406
+    _exit(0);
407
+  setsid();
408
+  pid=fork();
409
+  if(pid == -1){
410
+    lprintf(0,"minit_daemonize: can't fork()\n");
411
+    exit(1); 
412
+  }
413
+  if(pid)
414
+    _exit(0);
415
+
416
+  /*----- daemon process -----*/
417
+  close(2);
418
+  close(1);
419
+  close(0);
420
+  open("/dev/null",O_RDWR); /* new stdin  */
421
+  dup(0);                   /* new stdout */
422
+  dup(0);                   /* new stderr */
423
+}
424
+
425
+static void minit_bootlog()
426
+{
427
+  char *yesno[2]={"No","Yes"};
428
+  lprintf(0,"makuosan version %s\n",MAKUOSAN_VERSION);
429
+  lprintf(0,"loglevel  : %d\n", moption.loglevel);
430
+if(moption.chroot)
431
+  lprintf(0,"chroot    : %s\n", moption.real_dir);
432
+  lprintf(0,"base dir  : %s\n", moption.base_dir);
433
+  lprintf(0,"multicast : %s\n", inet_ntoa(moption.maddr.sin_addr));
434
+  lprintf(0,"port      : %d\n", ntohs(moption.maddr.sin_port));
435
+  lprintf(0,"uid       : %d\n", geteuid());
436
+  lprintf(0,"gid       : %d\n", getegid());
437
+  lprintf(0,"don't recv: %s\n", yesno[moption.dontrecv]);
438
+  lprintf(0,"don't send: %s\n", yesno[moption.dontsend]);
439
+  lprintf(0,"don't fork: %s\n", yesno[moption.dontfork]);
440
+  lprintf(0,"encrypt   : %s\n", yesno[moption.cryptena]);
441
+  lprintf(0,"console   : %s\n", yesno[moption.comm_ena]);
442
+  lprintf(0,"passwoed  : %s\n", yesno[moption.commpass]);
443
+  if(moption.comm_ena){
444
+    if(moption.uaddr.sun_path[0]){
445
+      lprintf(0,"listen    : %s\n", moption.uaddr.sun_path);
446
+    }else{
447
+      lprintf(0,"listen    : %s\n", inet_ntoa(moption.laddr.sin_addr));
448
+    }
449
+  }
450
+}
451
+
452
+/*
453
+ *  まくお初期化関数
454
+ *  main関数から呼び出される
455
+ */
456
+void minit(int argc, char *argv[])
457
+{
458
+  minit_option_setdefault(); /* 各オプションのデフォルト値を設定 */
459
+  minit_option_getenv();     /* 環境変数からオプションを読み込む */
460
+  minit_getopt(argc, argv);  /* コマンドラインパラメータを解析   */
461
+  minit_syslog();            /* syslogの使用を開始(openlog)      */
462
+  minit_socket();            /* マルチキャストソケットの初期化   */
463
+  minit_console();           /* コンソールソケットの初期化       */
464
+  minit_signal();            /* シグナルハンドラを設定           */
465
+  minit_chdir();             /* カレントディレクトリを変更       */
466
+  minit_chroot();            /*                                  */
467
+  minit_setguid();           /*                                  */
468
+  minit_daemonize();         /*                                  */
469
+  minit_bootlog();           /* ブートメッセージを出力する       */
470
+}
471
+
472
+
0 473
new file mode 100644
... ...
@@ -0,0 +1,701 @@
0
+/*
1
+ *  mrecv.c
2
+ */
3
+#include "makuosan.h"
4
+
5
+/*
6

                
7

                
8
+ */
9
+static mfile *mrecv_mfdel(mfile *m)
10
+{
11
+  mfile *r;
12
+  if(!m)
13
+    return(NULL);
14
+  r = m->next;
15
+  if(m->fd != -1){
16
+    close(m->fd);
17
+    m->fd = -1;
18
+    if(S_ISREG(m->fs.st_mode))
19
+      mremove(moption.base_dir, m->tn);
20
+  }
21
+  if(m->mark){
22
+    free(m->mark);
23
+    m->mark = NULL;
24
+  }
25
+  mfdel(m);
26
+  return(r);
27
+}
28
+
29
+static void mrecv_ping(mdata *data, struct sockaddr_in *addr)
30
+{
31
+  mping *p;
32
+  mfile *m;
33
+  char buff[HOST_NAME_MAX + 1];
34
+  member_add(&addr->sin_addr, data);
35
+  m = mfadd(0);
36
+  if(!m){
37
+    return;
38
+  }
39
+  m->mdata.head.opcode    = MAKUO_OP_PONG;
40
+  m->mdata.head.reqid   = getrid();
41
+  m->mdata.head.seqno = 0;
42
+  m->mdata.head.szdata  = 0;
43
+  memcpy(&(m->addr), addr, sizeof(m->addr));
44
+  if(gethostname(buff, sizeof(buff)) == -1){
45
+    buff[0] = 0;
46
+  }
47
+  p = (mping *)(m->mdata.data);
48
+  p->hostnamelen = strlen(buff);
49
+  p->versionlen  = strlen(MAKUOSAN_VERSION);
50
+  m->mdata.head.szdata = sizeof(mping) + p->hostnamelen + p->versionlen;
51
+  m->mdata.p = p->data;
52
+  memcpy(m->mdata.p, buff, p->hostnamelen);
53
+  m->mdata.p += p->hostnamelen;
54
+  memcpy(m->mdata.p, MAKUOSAN_VERSION, p->versionlen);
55
+  m->mdata.p += p->versionlen;
56
+  p->hostnamelen = htons(p->hostnamelen);
57
+  p->versionlen  = htons(p->versionlen);
58
+}
59
+
60
+static void mrecv_pong(mdata *data, struct sockaddr_in *addr)
61
+{
62
+  member_add(&addr->sin_addr, data);
63
+}
64
+
65
+static void mrecv_exit(mdata *data, struct sockaddr_in *addr)
66
+{
67
+  mhost *h;
68
+  for(h=members;h;h=h->next)
69
+    if(!memcmp(&(h->ad), &(addr->sin_addr), sizeof(h->ad)))
70
+      break;
71
+  member_del(h);
72
+}
73
+
74
+/*
75

                
76
+ */
77
+static int mrecv_file_data(mfile *m,  mdata *r)
78
+{
79
+  if(m->mdata.head.nstate != MAKUO_RECVSTATE_OPEN)
80
+    return(0);
81
+
82
+  if(m->lickflag){
83
+    if(!seq_delmark(m, r->head.seqno)){
84
+      return(0);
85
+    }
86
+  }else{
87
+    if(r->head.seqno < m->mdata.head.seqno){
88
+      seq_delmark(m, r->head.seqno);
89
+    }else{
90
+      m->mdata.head.seqno++;
91
+      if(m->mdata.head.seqno < r->head.seqno){
92
+        seq_addmark(m, m->mdata.head.seqno, r->head.seqno);
93
+        m->mdata.head.seqno = r->head.seqno;
94
+      }
95
+    }
96
+  }
97
+  if(lseek(m->fd, (r->head.seqno - 1) * MAKUO_BUFFER_SIZE, SEEK_SET) == -1){
98
+    lprintf(0, "mrecv_file_data: seek error seq=%d size=%d fd=%d err=%d\n", (int)r->head.seqno, r->head.szdata, m->fd, errno);
99
+    m->mdata.head.nstate = MAKUO_RECVSTATE_WRITEERROR;
100
+  }else{
101
+    if(write(m->fd, r->data, r->head.szdata) != -1){
102
+      m->recvcount++;
103
+    }else{
104
+      lprintf(0, "mrecv_file_data: write error seqno=%d size=%d fd=%d err=%d\n", (int)r->head.seqno, r->head.szdata, m->fd, errno);
105
+      m->mdata.head.nstate = MAKUO_RECVSTATE_WRITEERROR;
106
+    }
107
+  }
108
+  return(0);
109
+}
110
+
111
+/*
112

                
113
+ */
114
+static int mrecv_file_break(mfile *m, mdata *r)
115
+{
116
+  mrecv_mfdel(m);
117
+  return(0);
118
+}
119
+
120
+/*
121

                
122
+ */
123
+static int mrecv_file_open(mfile *m, mdata *r)
124
+{
125
+  char fpath[PATH_MAX];
126
+  char tpath[PATH_MAX];
127
+
128
+  if(m->mdata.head.nstate != MAKUO_RECVSTATE_UPDATE)
129
+    return(0);
130
+
131
+  sprintf(fpath, "%s/%s", moption.base_dir, m->fn);
132
+  sprintf(tpath, "%s/%s", moption.base_dir, m->tn);
133
+
134
+  mfile *a = mfins(0);
135
+  a->mdata.head.opcode = MAKUO_OP_ACK;
136
+  a->mdata.head.reqid = r->head.reqid;
137
+  a->mdata.head.seqno = r->head.seqno;
138
+  a->mdata.head.ostate = m->mdata.head.nstate;
139
+  a->mdata.head.nstate = MAKUO_RECVSTATE_OPEN;
140
+  m->mdata.head.nstate = MAKUO_RECVSTATE_OPEN;
141
+  memcpy(&(a->addr), &(m->addr), sizeof(a->addr));
142
+  if(S_ISLNK(m->fs.st_mode)){
143
+    mtempname(moption.base_dir, m->fn, m->tn);
144
+    sprintf(tpath, "%s/%s", moption.base_dir, m->tn);
145
+    if(symlink(m->ln, m->tn) != -1){
146
+      lprintf(2, "mrecv_file: open %s -> %s\n", m->ln, m->fn);
147
+    }else{
148
+      lprintf(0, "mrecv_file: symlink error %s\n", m->fn);
149
+      m->mdata.head.nstate = MAKUO_RECVSTATE_OPENERROR;
150
+      a->mdata.head.nstate = m->mdata.head.nstate;
151
+    }
152
+  }else{
153
+    if(S_ISDIR(m->fs.st_mode)){
154
+      if(!is_dir(fpath)){
155
+        mcreatedir(moption.base_dir, m->fn, m->fs.st_mode & 0xFFF);
156
+        mkdir(fpath, m->fs.st_mode & 0xFFF);
157
+      }else{
158
+        chmod(fpath, m->fs.st_mode & 0xFFF);
159
+      }
160
+      if(!is_dir(fpath)){
161
+        lprintf(0,"mrecv_file: mkdir error %s\n", m->fn);
162
+        m->mdata.head.nstate = MAKUO_RECVSTATE_OPENERROR;
163
+        a->mdata.head.nstate = m->mdata.head.nstate;
164
+      }
165
+    }
166
+    if(S_ISREG(m->fs.st_mode)){
167
+      mtempname(moption.base_dir, m->fn, m->tn);
168
+      sprintf(tpath, "%s/%s", moption.base_dir, m->tn);
169
+      m->fd = mcreate(moption.base_dir, m->tn, m->fs.st_mode);
170
+      if(m->fd == -1){
171
+        lprintf(0, "mrecv_file: open error %s\n", m->fn);
172
+        m->mdata.head.nstate = MAKUO_RECVSTATE_OPENERROR;
173
+        a->mdata.head.nstate = m->mdata.head.nstate;
174
+      }
175
+    }
176
+  }
177
+  return(0);
178
+}
179
+
180
+/*
181

                
182
+ */
183
+static int mrecv_file_close(mfile *m, mdata *r)
184
+{
185
+  struct utimbuf mftime;
186
+  char  fpath[PATH_MAX];
187
+  char  tpath[PATH_MAX];
188
+  sprintf(fpath, "%s/%s", moption.base_dir, m->fn);
189
+  sprintf(tpath, "%s/%s", moption.base_dir, m->tn);
190
+
191
+  if(m->mdata.head.nstate == MAKUO_RECVSTATE_OPEN  ||
192
+     m->mdata.head.nstate == MAKUO_RECVSTATE_UPDATE){
193
+    mfile *a = mfins(0);
194
+    a->mdata.head.opcode = MAKUO_OP_ACK;
195
+    a->mdata.head.reqid = r->head.reqid;
196
+    a->mdata.head.seqno = r->head.seqno;
197
+    a->mdata.head.ostate = m->mdata.head.nstate;
198
+    a->mdata.head.nstate = MAKUO_RECVSTATE_CLOSE;
199
+    memcpy(&(a->addr), &(m->addr), sizeof(a->addr));
200
+    if(m->mdata.head.nstate == MAKUO_RECVSTATE_OPEN){
201
+      if(m->fd != -1){
202
+        fstat(m->fd, &(a->fs));
203
+        close(m->fd);
204
+      }
205
+      m->fd = -1;
206
+      mftime.actime  = m->fs.st_ctime; 
207
+      mftime.modtime = m->fs.st_mtime;
208
+      if(S_ISLNK(m->fs.st_mode)){
209
+        if(!mrename(moption.base_dir, m->tn, m->fn)){
210
+          lprintf(2, "mrecv_file: close %s -> %s\n", m->ln, m->fn);
211
+        }else{
212
+          a->mdata.head.nstate = MAKUO_RECVSTATE_CLOSEERROR;
213
+          mremove(moption.base_dir, m->tn);
214
+          lprintf(0, "mrecv_file: close error %s -> %s\n", m->ln, m->fn);
215
+        }
216
+      }else{
217
+        if(S_ISDIR(m->fs.st_mode)){
218
+          utime(fpath, &mftime);
219
+        }else{
220
+          utime(tpath, &mftime);
221
+          if(a->fs.st_size != m->fs.st_size){
222
+            a->mdata.head.nstate = MAKUO_RECVSTATE_CLOSEERROR;
223
+            mremove(moption.base_dir, m->tn);
224
+            lprintf(0, "mrecv_file: close error %s (file size mismatch %d != %d)\n", m->fn, (int)(a->fs.st_size), (int)(m->fs.st_size));
225
+            lprintf(0, "mrecv_file: seq=%d max=%d markcnt=%d\n",m->mdata.head.seqno, m->seqnomax, m->markcount);
226
+          }else{
227
+            if(!mrename(moption.base_dir, m->tn, m->fn)){
228
+              lprintf(2, "mrecv_file: close %s recv=%d mark=%d\n", m->fn , m->recvcount, m->markcount);
229
+            }else{
230
+              a->mdata.head.nstate = MAKUO_RECVSTATE_CLOSEERROR;
231
+              mremove(moption.base_dir, m->tn);
232
+              lprintf(0, "mrecv_file: close error %s\n", m->fn);
233
+            }
234
+          }
235
+        }
236
+        if(!geteuid()){
237
+          chown(fpath, m->fs.st_uid, m->fs.st_gid);
238
+        }
239
+      }
240
+    }
241
+  }
242
+  mrecv_mfdel(m);
243
+  return(0);
244
+}
245
+
246
+/*
247

                
248
+ */
249
+static int mrecv_file_mark(mfile *m, mdata *r)
250
+{
251
+  if(m->mdata.head.nstate != MAKUO_RECVSTATE_OPEN)
252
+    return(0);
253
+
254
+  mfile *a = mfins(0);
255
+  a->mdata.head.opcode    = MAKUO_OP_ACK;
256
+  a->mdata.head.reqid   = r->head.reqid;
257
+  a->mdata.head.seqno = r->head.seqno;
258
+  a->mdata.head.nstate = m->mdata.head.nstate;
259
+  a->mdata.head.szdata  = 0;
260
+  memcpy(&(a->addr), &(m->addr), sizeof(a->addr));
261
+  m->lickflag = 1;
262
+  a->lickflag = 1;
263
+  if(m->mdata.head.seqno < m->seqnomax){
264
+    seq_addmark(m, m->mdata.head.seqno, m->seqnomax + 1);
265
+    m->mdata.head.seqno = m->seqnomax;
266
+  }
267
+  if(m->markcount){
268
+    if(MAKUO_BUFFER_SIZE < m->markcount * sizeof(uint32_t)){
269
+      a->marksize = MAKUO_BUFFER_SIZE / sizeof(uint32_t);
270
+    }else{
271
+      a->marksize = m->markcount;
272
+    }
273
+    a->markcount = a->marksize;
274
+    a->mark = malloc(a->marksize * sizeof(uint32_t));
275
+    memcpy(a->mark, m->mark, a->marksize * sizeof(uint32_t));
276
+    lprintf(3, "mrecv_file: retry %s recv=%d mark=%d reqest=%d\n", m->fn , m->recvcount, m->markcount, a->markcount);
277
+  }
278
+  return(0);
279
+}
280
+
281
+/*
282

                
283
+ *
284
+ */
285
+static int mrecv_file_next(mfile *m,  mdata *r)
286
+{
287
+  if(r->head.seqno){
288
+    return(mrecv_file_data(m, r));
289
+  }
290
+  switch(r->head.nstate){
291
+    case MAKUO_SENDSTATE_BREAK:
292
+      lprintf(9,"mrecv_file: MAKUO_SENDSTATE_BREAK: state=%d %s\n", m->mdata.head.nstate, m->fn);
293
+      return(mrecv_file_break(m, r));
294
+    case MAKUO_SENDSTATE_OPEN:
295
+      lprintf(9,"mrecv_file: MAKUO_SENDSTATE_OPEN : state=%d %s\n", m->mdata.head.nstate, m->fn);
296
+      return(mrecv_file_open(m, r));
297
+    case MAKUO_SENDSTATE_MARK:
298
+      lprintf(9,"mrecv_file: MAKUO_SENDSTATE_MARK : state=%d seqno=%d max=%d cnt=%d %s\n", 
299
+             m->mdata.head.nstate, m->mdata.head.seqno, m->seqnomax, m->markcount, m->fn);
300
+      return(mrecv_file_mark(m, r));
301
+    case MAKUO_SENDSTATE_CLOSE:
302
+      lprintf(9,"mrecv_file: MAKUO_SENDSTATE_CLOSE: state=%d %s\n", m->mdata.head.nstate, m->fn);
303
+      return(mrecv_file_close(m, r));
304
+  }
305
+  return(0);
306
+}
307
+
308
+/*
309

                
310

                
311

                
312
+*/
313
+static mfile *mrecv_file_stat(mdata *data, struct sockaddr_in *addr)
314
+{
315
+  mstat fs;
316
+  uint16_t  fnlen;
317
+  uint16_t  lnlen;
318
+  mfile *m = NULL;
319
+  mfile *a = NULL;
320
+  struct utimbuf mftime;
321
+
322

                
323
+  if(data->head.seqno)
324
+    return(NULL);
325
+
326
+  a = mfins(0);
327
+  a->mdata.head.opcode    = MAKUO_OP_ACK;
328
+  a->mdata.head.reqid   = data->head.reqid;
329
+  a->mdata.head.szdata  = 0;
330
+  a->mdata.head.seqno = data->head.seqno;
331
+  a->mdata.head.nstate = MAKUO_RECVSTATE_IGNORE;
332
+  memcpy(&(a->addr), addr, sizeof(a->addr));
333
+  if(data->head.nstate == MAKUO_SENDSTATE_STAT){
334
+    m = mfadd(1);
335
+    mtimeget(&(m->lastrecv));
336
+    data->p = data->data;
337
+    memcpy(&(m->addr), addr, sizeof(m->addr));
338
+    memcpy(&(m->mdata.head), &(data->head), sizeof(m->mdata.head));
339
+
340
+    /* read mstat */
341
+    memcpy(&fs, data->p, sizeof(fs));
342
+    data->p += sizeof(fs);
343
+
344
+    /* stat = mstat */
345
+    m->fs.st_mode  = ntohl(fs.mode);
346
+    m->fs.st_uid   = ntohs(fs.uid);
347
+    m->fs.st_gid   = ntohs(fs.gid);
348
+    m->fs.st_size  = ((off_t)ntohl(fs.sizeh) << 32) + (off_t)ntohl(fs.sizel);
349
+    m->fs.st_mtime = ntohl(fs.mtime);
350
+    m->fs.st_ctime = ntohl(fs.ctime);
351
+    fnlen = ntohs(fs.fnlen);
352
+    lnlen = ntohs(fs.lnlen);
353
+
354
+    /* read filename */
355
+    memcpy(m->fn, data->p, fnlen);
356
+    m->fn[fnlen] = 0;
357
+    data->p += fnlen;
358
+
359
+    /* read linkname */
360
+    memcpy(m->ln, data->p, lnlen);    
361
+    m->ln[lnlen] = 0;
362
+    data->p += lnlen;
363
+
364
+    m->seqnomax = m->fs.st_size / MAKUO_BUFFER_SIZE;
365
+    if(m->fs.st_size % MAKUO_BUFFER_SIZE){
366
+      m->seqnomax++; 
367
+    }
368
+    if(moption.dontrecv){
369
+      m->mdata.head.nstate = MAKUO_RECVSTATE_READONLY;
370
+    }else{
371
+      if(S_ISLNK(m->fs.st_mode)){
372
+        m->mdata.head.nstate = linkcmp(m);
373
+      }else{
374
+        if(lstat(m->fn, &(a->fs)) == -1){
375
+          m->mdata.head.nstate = MAKUO_RECVSTATE_UPDATE;
376
+        }else{
377
+          m->mdata.head.nstate = statcmp(&(m->fs), &(a->fs));
378
+        }
379
+      }
380
+    }
381
+    a->mdata.head.nstate = m->mdata.head.nstate;
382
+    lprintf(9,"mrecv_file: MAKUO_SENDSTATE_STAT : state=%d %s\n", m->mdata.head.nstate, m->fn);
383
+  }
384
+  return(m);
385
+}
386
+
387
+static void mrecv_file(mdata *data, struct sockaddr_in *addr)
388
+{
389
+  mfile *m = mftop[1]; 
390
+  while(m){
391
+    if(!memcmp(&m->addr, addr, sizeof(m->addr)) && m->mdata.head.reqid == data->head.reqid){
392
+      mtimeget(&m->lastrecv);
393
+      break;
394
+    }
395
+    m = m->next;
396
+  }
397
+  if(!m){
398
+    mrecv_file_stat(data, addr);
399
+  }else{
400
+    mtimeget(&(m->lastrecv));
401
+    mrecv_file_next(m, data);
402
+  }
403
+}
404
+
405
+static void mrecv_ack_file(mfile *m, mhost *h, mdata *data)
406
+{
407
+  uint32_t *d;
408
+
409
+  if(data->head.nstate == MAKUO_RECVSTATE_IGNORE){
410
+    cprintf(4, m->comm, "%s: file update ignore %s\n", h->hostname, m->fn);
411
+    lprintf(0,          "mrecv_ack: file update ignore rid=%06d state=%02d %s(%s) %s\n", 
412
+      data->head.reqid, data->head.nstate, inet_ntoa(h->ad), h->hostname, m->fn);
413
+  }
414
+  if(data->head.nstate == MAKUO_RECVSTATE_OPEN){
415
+    d = (uint32_t *)(data->data);
416
+    while(d < (uint32_t *)&data->data[data->head.szdata]){
417
+      seq_addmark(m, *d, (*d) + 1);
418
+      d++;
419
+    }
420
+  }
421
+}
422
+
423
+static void mrecv_ack_md5(mfile *m, mhost *h, mdata *data)
424
+{
425
+  if(h->state != data->head.nstate){
426
+    if(data->head.nstate == MAKUO_RECVSTATE_MD5OK){
427
+      cprintf(1, m->comm, "%s: OK %s\r\n", h->hostname, m->fn);
428
+      lprintf(1,          "mrecv_ack_md5: OK %s\n", m->fn);
429
+    }
430
+    if(data->head.nstate == MAKUO_RECVSTATE_MD5NG){
431
+      cprintf(0, m->comm, "%s: NG %s\r\n", h->hostname, m->fn);
432
+      lprintf(0,          "mrecv_ack_md5: NG %s\n", m->fn);
433
+    }
434
+  }
435
+}
436
+
437
+/*
438

                
439
+ */
440
+static void mrecv_ack(mdata *data, struct sockaddr_in *addr)
441
+{
442
+  mfile *m;
443
+  mhost *h;
444
+
445
+  h = member_add(&addr->sin_addr, NULL);
446
+  if(!h){
447
+    lprintf(0, "mrecv_ack: member not found %s\n", inet_ntoa(addr->sin_addr));
448
+    return;
449
+  }
450
+  for(m=mftop[0];m;m=m->next)
451
+    if(m->mdata.head.reqid == data->head.reqid)
452
+      break;
453
+  if(!m){
454
+    lprintf(4, "mrecv_ack: mfile not found rid=%06d state=%02d %s(%s)\n", 
455
+      data->head.reqid, data->head.nstate, inet_ntoa(addr->sin_addr), h->hostname);
456
+    return;
457
+  }
458
+  mtimeget(&m->lastrecv);
459
+  switch(m->mdata.head.opcode){
460
+    case MAKUO_OP_FILE:
461
+      mrecv_ack_file(m,h,data);
462
+      break;
463
+    case MAKUO_OP_MD5:
464
+      mrecv_ack_md5(m,h,data);
465
+      break;
466
+  }
467
+  if(data->head.nstate == MAKUO_RECVSTATE_OPENERROR){
468
+    cprintf(0, m->comm, "%s: file open error %s\n", h->hostname, m->fn);
469
+    lprintf(0,          "mrecv_ack: file open error rid=%06d state=%02d %s(%s) %s\n", 
470
+      data->head.reqid, data->head.nstate, inet_ntoa(h->ad), h->hostname, m->fn);
471
+  }
472
+  if(data->head.nstate == MAKUO_RECVSTATE_WRITEERROR){
473
+    cprintf(0, m->comm, "%s: file write error %s\n", h->hostname, m->fn);
474
+    lprintf(0,          "mrecv_ack: file write error rid=%06d state=%02d %s(%s) %s\n", 
475
+     data->head.reqid, data->head.nstate, inet_ntoa(h->ad), h->hostname, m->fn);
476
+  }
477
+  if(data->head.nstate == MAKUO_RECVSTATE_CLOSEERROR){
478
+    cprintf(0, m->comm, "%s: file close error %s\n", h->hostname, m->fn);
479
+    lprintf(0,          "mrecv_ack: file close error rid=%06d state=%02d %s(%s) %s\n", 
480
+      data->head.reqid, data->head.nstate, inet_ntoa(h->ad), h->hostname, m->fn);
481
+  }
482
+  h->state = data->head.nstate;
483
+  return;
484
+}
485
+
486
+static void mrecv_md5_open(mfile *m, mdata *data, struct sockaddr_in *addr)
487
+{
488
+  int    r;
489
+  int    l;
490
+  mfile *a;
491
+  mhash *h;
492
+
493
+  if(!m){
494
+    m = mfadd(1);
495
+    memcpy(&(m->addr), addr, sizeof(m->addr));
496
+    memcpy(&(m->mdata.head), &(data->head), sizeof(m->mdata.head));
497
+    h = (mhash *)(data->data);
498
+    l = ntohs(h->fnlen);
499
+    memcpy(m->fn, h->filename, l);
500
+    m->fn[l] = 0;
501
+    m->fd = open(m->fn, O_RDONLY);
502
+    if(m->fd == -1){
503
+      m->mdata.head.nstate = MAKUO_RECVSTATE_OPENERROR;
504
+    }else{
505
+      r = md5sum(m->fd, m->mdata.data);
506
+      close(m->fd);
507
+      m->fd = -1;
508
+      if(r == -1){
509
+	      lprintf(0, "mrecv_md5: file read error %s\n", m->fn);
510
+        m->mdata.head.nstate = MAKUO_RECVSTATE_READERROR;
511
+      }else{
512
+        if(!memcmp(m->mdata.data, data->data, 16)){
513
+          m->mdata.head.nstate = MAKUO_RECVSTATE_MD5OK;
514
+        }else{
515
+          m->mdata.head.nstate = MAKUO_RECVSTATE_MD5NG;
516
+        }
517
+      }
518
+    }
519
+  }
520
+  a=mfadd(0);
521
+  a->mdata.head.opcode    = MAKUO_OP_ACK;
522
+  a->mdata.head.reqid   = m->mdata.head.reqid;
523
+  a->mdata.head.seqno = 0;
524
+  a->mdata.head.szdata  = 0;
525
+  a->mdata.head.nstate = m->mdata.head.nstate;
526
+  memcpy(&(a->addr), addr, sizeof(a->addr));
527
+  mtimeget(&(m->lastrecv));
528
+}
529
+
530
+static void mrecv_md5_close(mfile *m, mdata *data, struct sockaddr_in *addr)
531
+{
532
+  mfile *a = mfadd(0);
533
+  a->mdata.head.opcode    = MAKUO_OP_ACK;
534
+  a->mdata.head.reqid   = data->head.reqid;
535
+  a->mdata.head.szdata  = 0;
536
+  a->mdata.head.seqno = 0;
537
+  a->mdata.head.nstate = MAKUO_RECVSTATE_CLOSE;
538
+  memcpy(&(a->addr), addr, sizeof(a->addr));
539
+  mrecv_mfdel(m);
540
+}
541
+
542
+/*
543

                
544

                
545

                
546
+ */
547
+static void mrecv_md5(mdata *data, struct sockaddr_in *addr)
548
+{
549
+  mfile *m = mftop[1];
550
+  while(m){
551
+    if(!memcmp(&m->addr, addr, sizeof(m->addr)) && m->mdata.head.reqid == data->head.reqid){
552
+      mtimeget(&m->lastrecv);
553
+      break;
554
+    }
555
+    m = m->next;
556
+  }
557
+  switch(data->head.nstate){
558
+    case MAKUO_SENDSTATE_OPEN:
559
+      mrecv_md5_open(m, data, addr);
560
+      break;
561
+    case MAKUO_SENDSTATE_CLOSE:
562
+      mrecv_md5_close(m, data, addr);
563
+      break;
564
+  }
565
+}
566
+
567
+static int mrecv_decrypt(mdata *data, struct sockaddr_in *addr)
568
+{
569
+  int i;
570
+  MD5_CTX ctx;
571
+  uint8_t hash[16];
572
+
573
+  if(data->head.flags & MAKUO_FLAG_CRYPT){
574
+    if(!moption.cryptena){
575
+      lprintf(0, "mrecv_decrypt: recv encrypt packet from %s. I have not key!", inet_ntoa(addr->sin_addr));
576
+      return(-1);
577
+    }
578
+    if(data->head.szdata){
579
+      for(i=0;i<data->head.szdata;i+=8){
580
+        BF_decrypt((BF_LONG *)(data->data + i), &EncKey);
581
+      }
582
+      MD5_Init(&ctx);
583
+      MD5_Update(&ctx, data->data, data->head.szdata);
584
+      MD5_Final(hash, &ctx);
585
+      if(memcmp(hash,data->head.hash,16)){
586
+        lprintf(0, "mrecv_decrypt: protocol checksum error from %s\n", inet_ntoa(addr->sin_addr));
587
+        return(-1);
588
+      }
589
+    }
590
+  }
591
+  return(0);
592
+}
593
+
594
+static int mrecv_packet(int s, mdata *data, struct sockaddr_in *addr)
595
+{
596
+  int recvsize;
597
+  socklen_t addr_len;
598
+
599
+  while(1){
600
+    addr_len = sizeof(struct sockaddr_in);
601
+    recvsize = recvfrom(s, data, sizeof(mdata), 0, (struct sockaddr *)addr, &addr_len);
602
+    if(recvsize != -1){
603
+      break;
604
+    }else{
605
+      if(errno == EAGAIN || errno == EINTR){
606
+        continue;
607
+      }else{
608
+        lprintf(0, "mrecv_packets: recv error from %s\n", inet_ntoa(addr->sin_addr));
609
+        return(-1);
610
+      }
611
+    }
612
+  }
613
+  if(recvsize < sizeof(data->head)){
614
+    lprintf(0, "mrecv: recv head size error\n");
615
+    return(-1);
616
+  }
617
+
618

                
619
+  data->head.szdata = ntohs(data->head.szdata);
620
+  data->head.flags  = ntohs(data->head.flags);
621
+  data->head.reqid  = ntohl(data->head.reqid);
622
+  data->head.seqno  = ntohl(data->head.seqno);
623
+
624

                
625
+  if(data->head.vproto != PROTOCOL_VERSION){
626
+    lprintf(0, "mrecv_packet: protocol version error(%d != %d) from %s\n",
627
+       data->head.vproto, PROTOCOL_VERSION, inet_ntoa(addr->sin_addr));
628
+    return(-1);
629
+  }
630
+
631
+  return(mrecv_decrypt(data, addr));
632
+}
633
+
634
+/*
635

                
636
+ */
637
+void mrecv_gc()
638
+{
639
+  mhost *t = members;
640
+  mfile *m = mftop[1]; 
641
+  while(m){
642
+    if(mtimeout(&(m->lastrecv), MAKUO_RECV_GCWAIT)){
643
+      lprintf(0,"mrecv_gc: mfile object GC state=%d %s\n", m->mdata.head.nstate, m->fn);
644
+      m = mrecv_mfdel(m);
645
+      continue;
646
+    }
647
+    m = m->next;
648
+  }
649
+
650
+  /* pong timeout */
651
+  while(t){
652
+    if(!mtimeout(&(t->lastrecv), MAKUO_PONG_TIMEOUT)){
653
+      t = t->next;
654
+    }else{
655
+      lprintf(0,"mrecv_gc: pong timeout %s\n", t->hostname);
656
+      if(t->next){
657
+        t = t->next;
658
+        member_del(t->prev);
659
+      }else{
660
+        member_del(t);
661
+        t = NULL;
662
+     } 
663
+    }      
664
+  }
665
+}
666
+
667
+/*
668

                
669

                
670
+ */
671
+void mrecv(int s)
672
+{
673
+  mdata  data;
674
+  struct sockaddr_in addr;
675
+
676
+  if(mrecv_packet(s, &data, &addr) == -1){
677
+    return;
678
+  }
679
+  switch(data.head.opcode){
680
+    case MAKUO_OP_PING:
681
+      mrecv_ping(&data, &addr);
682
+      break;
683
+    case MAKUO_OP_PONG:
684
+      mrecv_pong(&data, &addr);
685
+      break;
686
+    case MAKUO_OP_EXIT:
687
+      mrecv_exit(&data, &addr);
688
+      break;
689
+    case MAKUO_OP_ACK:
690
+      mrecv_ack(&data, &addr);
691
+      break;
692
+    case MAKUO_OP_FILE:
693
+      mrecv_file(&data, &addr);
694
+      break;
695
+    case MAKUO_OP_MD5:
696
+      mrecv_md5(&data, &addr);
697
+      break;
698
+  }
699
+}
700
+
0 701
new file mode 100644
... ...
@@ -0,0 +1,513 @@
0
+/*
1
+ *  msend.c
2
+ *
3
+ */
4
+#include "makuosan.h"
5
+
6
+/*
7

                
8
+ */
9
+static mfile *msend_mfdel(mfile *m)
10
+{
11
+  mfile *r;
12
+  if(!m)
13
+    return(NULL);
14
+  r = m->next;
15
+  if(m->fd != -1)
16
+    close(m->fd);   
17
+  if(m->mark)
18
+    free(m->mark);
19
+  mfdel(m);
20
+  return(r);
21
+}
22
+
23
+static int msend_encrypt(mdata *data)
24
+{
25
+  int  szdata;
26
+  MD5_CTX ctx;
27
+
28
+  szdata = data->head.szdata;
29
+  if(moption.cryptena && data->head.szdata){
30
+    MD5_Init(&ctx);
31
+    MD5_Update(&ctx, data->data, data->head.szdata);
32
+    MD5_Final(data->head.hash, &ctx);
33
+    for(szdata=0;szdata<data->head.szdata;szdata+=8){
34
+      BF_encrypt((BF_LONG *)(data->data + szdata), &EncKey);
35
+    }
36
+    data->head.flags |= MAKUO_FLAG_CRYPT;
37
+  }
38
+  return(szdata);
39
+}
40
+
41
+/*
42

                
43
+ */
44
+static int msend_packet(int s, mdata *data, struct sockaddr_in *addr)
45
+{
46
+  int r;
47
+  int szdata;
48
+  mdata senddata;
49
+
50
+  memcpy(&senddata, data, sizeof(senddata));
51
+  szdata = msend_encrypt(&senddata);
52
+
53

                
54
+  senddata.head.szdata = htons(senddata.head.szdata);
55
+  senddata.head.flags  = htons(senddata.head.flags);
56
+  senddata.head.reqid  = htonl(senddata.head.reqid);
57
+  senddata.head.seqno  = htonl(senddata.head.seqno);
58
+ 
59
+  while(1){ 
60
+    r = sendto(s, &senddata, sizeof(mhead) + szdata, 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
61
+    if(r == sizeof(mhead) + szdata){
62
+      break;
63
+    }else{
64
+      if(r != -1){
65
+        lprintf(0,"msend_packet: size error sock=%d op=%d rid=%d state=%d size=%d send=%d seqno=%d\n", 
66
+          s, data->head.opcode, data->head.reqid, data->head.nstate, sizeof(mhead) + szdata, r, data->head.seqno);
67
+        return(0);
68
+      }else{
69
+        if(errno == EINTR){
70
+          continue;
71
+        }else{
72
+          lprintf(0,"msend_packet: send error errno=%d sock=%d op=%d rid=%d state=%d size=%d seqno=%d\n", 
73
+            errno, s, data->head.opcode, data->head.reqid, data->head.nstate, sizeof(mhead) + szdata, data->head.seqno);
74
+          return(-1);
75
+        }
76
+      }
77
+    }
78
+  }
79
+  return(1);
80
+}
81
+
82
+static void msend_shot(int s, mfile *m)
83
+{
84
+  msend_packet(s, &(m->mdata), &(m->addr));
85
+  msend_mfdel(m);
86
+}
87
+
88
+static void msend_ack(int s, mfile *m)
89
+{
90
+  if(m->markcount){
91
+    m->mdata.head.szdata = m->marksize * sizeof(uint32_t);
92
+    memcpy(m->mdata.data, m->mark, m->marksize * sizeof(uint32_t));
93
+  }
94
+  msend_packet(s, &(m->mdata), &(m->addr));
95
+  msend_mfdel(m);
96
+  m = NULL;
97
+}
98
+
99
+static void msend_file_break(int s, mfile *m)
100
+{
101
+  lprintf(9, "msend_file: BREAK %s\n", m->fn);
102
+  msend_packet(s, &(m->mdata), &(m->addr));
103
+  msend_mfdel(m);
104
+}
105
+
106
+static void msend_mark(int s, mfile *m)
107
+{
108
+  int i;
109
+  int r;
110
+  if(!m->markcount){
111
+    /* close */
112
+    m->mdata.head.seqno = 0;
113
+    m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
114
+    lprintf(4, "msend_file_mark: file send complate! %s\n",m->fn);
115
+  }else{
116
+    lprintf(4, "msend_file_mark: block send retry %d\n",m->markcount);
117
+    for(i=0;i<m->markcount;i++){
118
+      m->mdata.head.seqno = m->mark[i];
119
+      lseek(m->fd, (m->mdata.head.seqno - 1) * MAKUO_BUFFER_SIZE, SEEK_SET);
120
+      r = read(m->fd, m->mdata.data, MAKUO_BUFFER_SIZE);
121
+      if(r>0){
122
+        m->mdata.head.szdata = r;
123
+        msend_packet(s, &(m->mdata), &(m->addr));
124
+      }else{
125
+        if(!r){
126
+          lprintf(0, "msend_mark: read eof? seqno=%d\n", m->mdata.head.seqno);
127
+        }else{
128
+          lprintf(0, "msend_mark: read err! seqno=%d errno=%d\n", m->mdata.head.seqno, errno);
129
+        }
130
+      }
131
+    }
132
+    /* eof */
133
+    m->markcount = 0;
134
+    m->mdata.head.seqno = 0;
135
+    m->mdata.head.nstate = MAKUO_SENDSTATE_MARKINIT;
136
+  }
137
+}
138
+
139
+static void msend_data(int s, mfile *m)
140
+{
141
+  int readsize;
142
+  lseek(m->fd, (m->mdata.head.seqno - 1) * MAKUO_BUFFER_SIZE, SEEK_SET);
143
+  readsize = read(m->fd, m->mdata.data, MAKUO_BUFFER_SIZE);
144
+  if(readsize > 0){
145
+    m->mdata.head.szdata = readsize;
146
+    if(msend_packet(s, &(m->mdata), &(m->addr)) == 1){
147
+      m->mdata.head.seqno++;
148
+    }
149
+  }else{
150
+    if(readsize == -1){
151
+      /* err */
152
+      lprintf(0, "msend_data: read error! seqno=%d errno=%d\n", m->mdata.head.seqno, errno);
153
+    }else{
154
+      /* eof */
155
+      lprintf(4, "msend_data: block send count=%d\n", m->mdata.head.seqno);
156
+      m->mdata.head.seqno = 0;
157
+      m->mdata.head.nstate = MAKUO_SENDSTATE_MARKINIT;
158
+      m->lickflag  = 1;
159
+    }
160
+  }
161
+}
162
+
163
+static void msend_file_stat_init(int s, mfile *m)
164
+{
165
+  if(!m->comm){
166
+    lprintf(9, "msend_file: STATINIT %s (CANCEL)\n", m->fn);
167
+    msend_mfdel(m);
168
+    m=NULL;
169
+  }else{
170
+    lprintf(9, "msend_file: STATINIT %s\n", m->fn);
171
+    m->sendwait = 1;
172
+    m->mdata.head.nstate = MAKUO_SENDSTATE_STAT;
173
+    ack_clear(m,-1);
174
+    msend_packet(s, &(m->mdata), &(m->addr));
175
+  }
176
+}
177
+
178
+static void msend_file_stat(int s, mfile *m)
179
+{
180
+  mhost *h;
181
+
182
+  if(m->sendwait){
183
+    msend_packet(s, &(m->mdata), &(m->addr));
184
+  }else{
185
+    lprintf(9,"msend_file: STAT %s\n", m->fn);
186
+    if(m->dryrun){
187
+      if(ack_check(m, MAKUO_RECVSTATE_UPDATE) != 1){
188
+        cprintf(5, m->comm, "(%s)\r\n", m->fn);
189
+      }else{
190
+        cprintf(0, m->comm, "[%s]\r\n", m->fn);
191
+        if(!m->sendto){
192
+          for(h=members;h;h=h->next){
193
+            if(h->state == MAKUO_RECVSTATE_UPDATE)
194
+              cprintf(1, m->comm, "%s: update\r\n", h->hostname);
195
+            if(h->state == MAKUO_RECVSTATE_SKIP)
196
+              cprintf(2, m->comm, "%s: skip\r\n", h->hostname);
197
+            if(h->state == MAKUO_RECVSTATE_READONLY)
198
+              cprintf(2, m->comm, "%s: skip(read only)\r\n", h->hostname);
199
+          }
200
+        }
201
+      }
202
+      m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
203
+    }else{
204
+      if(ack_check(m, MAKUO_RECVSTATE_UPDATE) != 1){
205
+        cprintf(5, m->comm, "(%s)\r\n", m->fn);
206
+        m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
207
+      }else{
208
+        lprintf(1, "msend_file_stat: update %s\n", m->fn);
209
+        cprintf(1, m->comm, "[%s]\r\n", m->fn);
210
+        if(!m->sendto){
211
+          for(h=members;h;h=h->next){
212
+            if(h->state == MAKUO_RECVSTATE_UPDATE)
213
+              cprintf(2, m->comm, "%s: update\r\n", h->hostname);
214
+            if(h->state == MAKUO_RECVSTATE_SKIP)
215
+              cprintf(3, m->comm, "%s: skip\r\n", h->hostname);
216
+            if(h->state == MAKUO_RECVSTATE_READONLY)
217
+              cprintf(3, m->comm, "%s: skip(read only)\r\n", h->hostname);
218
+          }
219
+        }
220
+        m->mdata.head.nstate = MAKUO_SENDSTATE_OPENINIT;
221
+      }
222
+    }
223
+  }
224
+}
225
+
226
+static void msend_file_open_init(int s, mfile *m)
227
+{
228
+  lprintf(9,"msend_file: OPENINIT %s\n", m->fn);
229
+  m->sendwait = 1;
230
+  ack_clear(m, MAKUO_RECVSTATE_UPDATE);
231
+  m->mdata.head.nstate = MAKUO_SENDSTATE_OPEN;
232
+  /*----- symlink -----*/
233
+  if(S_ISLNK(m->fs.st_mode)){
234
+    msend_packet(s, &(m->mdata), &(m->addr));
235
+  }else{
236
+    /*----- dir -----*/
237
+    if(S_ISDIR(m->fs.st_mode)){
238
+      msend_packet(s, &(m->mdata), &(m->addr));
239
+    }
240
+    /*----- file -----*/
241
+    if(S_ISREG(m->fs.st_mode)){
242
+      m->fd = open(m->fn, O_RDONLY, 0);
243
+      if(m->fd != -1){
244
+        msend_packet(s, &(m->mdata), &(m->addr));
245
+        lprintf(4, "msend_file: open fd=%d %s\n", m->fd, m->fn);
246
+      }else{
247
+        m->sendwait = 0;
248
+        m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
249
+        cprintf(0, m->comm, "msend_file: open error errno=%d %s\n", errno, m->fn);
250
+        lprintf(0,          "msend_file: open error errno=%d %s\n", errno, m->fn);
251
+      }
252
+    }
253
+  }
254
+}
255
+
256
+static void msend_file_open(int s, mfile *m)
257
+{
258
+  if(m->sendwait){
259
+    msend_packet(s, &(m->mdata), &(m->addr));
260
+  }else{
261
+    lprintf(9,"msend_file: OPEN %s\n", m->fn);
262
+    if(ack_check(m, MAKUO_RECVSTATE_OPEN) != 1){
263
+      m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
264
+    }else{
265
+      if(S_ISLNK(m->fs.st_mode)){
266
+        m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
267
+      }else{
268
+        if(S_ISDIR(m->fs.st_mode)){
269
+          m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
270
+        }
271
+        if(S_ISREG(m->fs.st_mode)){
272
+          m->mdata.head.seqno = 1;
273
+        }
274
+      }
275
+    }
276
+  }
277
+}
278
+
279
+static void msend_file_close_init(int s, mfile *m)
280
+{
281
+  lprintf(9,"msend_file: CLOSEINIT %s\n", m->fn);
282
+  m->sendwait = 1;
283
+  ack_clear(m, MAKUO_RECVSTATE_OPEN);
284
+  ack_clear(m, MAKUO_RECVSTATE_UPDATE);
285
+  m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE;
286
+  msend_packet(s, &(m->mdata), &(m->addr));
287
+}
288
+
289
+static void msend_file_close(int s, mfile *m)
290
+{
291
+  if(m->sendwait){
292
+    msend_packet(s, &(m->mdata), &(m->addr));
293
+  }else{
294
+    lprintf(9,"msend_file: CLOSE %s\n",m->fn);
295
+    msend_mfdel(m);
296
+    m = NULL;
297
+  }
298
+}
299
+
300
+static void msend_file_mark_init(int s, mfile *m)
301
+{
302
+  m->sendwait = 1;
303
+  ack_clear(m, MAKUO_RECVSTATE_OPEN);
304
+  m->mdata.head.nstate = MAKUO_SENDSTATE_MARK;
305
+  msend_packet(s, &(m->mdata), &(m->addr));
306
+}
307
+
308
+static void msend_file_mark(int s, mfile *m)
309
+{
310
+  if(m->sendwait){
311
+    msend_packet(s, &(m->mdata), &(m->addr));
312
+  }else{
313
+    m->mdata.head.seqno = 1;
314
+  }
315
+}
316
+
317
+/*----------------------------------------------------------------------------
318
+ *
319
+ *  send
320
+ *
321
+ */
322
+static void msend_file(int s, mfile *m)
323
+{
324
+  mstat fs;
325
+  if(m->mdata.head.seqno){
326
+    if(!m->comm){
327
+      m->mdata.head.seqno = 0;
328
+      m->mdata.head.nstate = MAKUO_SENDSTATE_BREAK;
329
+    }else{
330
+      if(m->lickflag){
331
+        msend_mark(s, m); /* send rery */
332
+      }else{
333
+        msend_data(s, m); /* send data */
334
+      }
335
+    }
336
+  }else{
337
+    if(!m->comm){
338
+      msend_mfdel(m);
339
+      return;
340
+    }
341
+    m->mdata.p = m->mdata.data;
342
+    m->mdata.head.szdata  = sizeof(fs);
343
+    m->mdata.head.szdata += strlen(m->fn) + 1;
344
+    m->mdata.head.szdata += strlen(m->ln) + 1;
345
+    if(m->mdata.head.szdata > MAKUO_BUFFER_SIZE){
346
+      lprintf(0, "msend_file: buffer size over size=%d file=%s\n", m->mdata.head.szdata, m->fn);
347
+      cprintf(0, m->comm, "error: buffer size over size=%d file=%s\n", m->mdata.head.szdata, m->fn);
348
+      return;
349
+    }
350
+    fs.mode  = htonl(m->fs.st_mode);
351
+    fs.uid   = htons(m->fs.st_uid);
352
+    fs.gid   = htons(m->fs.st_gid);
353
+    fs.sizel = htonl((uint32_t)(m->fs.st_size & 0xFFFFFFFF));
354
+    fs.sizeh = htonl((uint32_t)(m->fs.st_size >> 32));
355
+    fs.mtime = htonl(m->fs.st_mtime);
356
+    fs.ctime = htonl(m->fs.st_ctime);
357
+    fs.fnlen = htons(strlen(m->fn));
358
+    fs.lnlen = htons(strlen(m->ln));
359
+    memcpy(m->mdata.p, &fs, sizeof(fs));
360
+    m->mdata.p += sizeof(fs);
361
+    strcpy(m->mdata.p, m->fn);
362
+    m->mdata.p += strlen(m->fn);
363
+    strcpy(m->mdata.p, m->ln);
364
+    m->mdata.p += strlen(m->ln);
365
+
366
+    switch(m->mdata.head.nstate){
367
+      case MAKUO_SENDSTATE_BREAK:
368
+        msend_file_break(s, m);
369
+        break;
370
+      case MAKUO_SENDSTATE_STATINIT:
371
+        msend_file_stat_init(s, m);
372
+        break;
373
+      case MAKUO_SENDSTATE_STAT:
374
+        msend_file_stat(s, m);
375
+        break;
376
+      case MAKUO_SENDSTATE_OPENINIT:
377
+        msend_file_open_init(s, m);
378
+        break;
379
+      case MAKUO_SENDSTATE_OPEN:
380
+        msend_file_open(s, m);
381
+        break;
382
+      case MAKUO_SENDSTATE_CLOSEINIT:
383
+        msend_file_close_init(s, m);
384
+        break;
385
+      case MAKUO_SENDSTATE_CLOSE:
386
+        msend_file_close(s, m);
387
+        break;
388
+      case MAKUO_SENDSTATE_MARKINIT:
389
+        msend_file_mark_init(s, m);
390
+        break;
391
+      case MAKUO_SENDSTATE_MARK:
392
+        msend_file_mark(s, m);
393
+        break;
394
+    }
395
+  }
396
+}
397
+
398
+/*----------------------------------------------------------------------------
399
+ *
400
+ *  md5
401
+ *
402
+ */
403
+static void msend_md5_open_init(int s, mfile *m)
404
+{
405
+  lprintf(9,"msend_md5: OPENINIT %s\n", m->fn);
406
+  m->sendwait = 1;
407
+  ack_clear(m, -1);
408
+  m->mdata.head.nstate = MAKUO_SENDSTATE_OPEN;
409
+  msend_packet(s, &(m->mdata), &(m->addr));
410
+}
411
+
412
+static void msend_md5_open(int s, mfile *m)
413
+{
414
+  if(m->sendwait){
415
+    msend_packet(s, &(m->mdata), &(m->addr));
416
+  }else{
417
+    lprintf(9,"msend_md5: OPEN %s\n", m->fn);
418
+    m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSEINIT;
419
+  }
420
+}
421
+
422
+static void msend_md5_close_init(int s, mfile *m)
423
+{
424
+  lprintf(9,"msend_md5: CLOSEINIT %s\n", m->fn);
425
+  m->sendwait = 1;
426
+  ack_clear(m, MAKUO_RECVSTATE_MD5OK);
427
+  ack_clear(m, MAKUO_RECVSTATE_MD5NG);
428
+  m->mdata.head.nstate = MAKUO_SENDSTATE_CLOSE;
429
+  msend_packet(s, &(m->mdata), &(m->addr));
430
+}
431
+
432
+static void msend_md5_close(int s, mfile *m)
433
+{
434
+  if(m->sendwait){
435
+    msend_packet(s, &(m->mdata), &(m->addr));
436
+  }else{
437
+    lprintf(9,"msend_md5: CLOSE %s\n",m->fn);
438
+    msend_mfdel(m);
439
+    m = NULL;
440
+  }
441
+}
442
+
443
+static void msend_md5(int s, mfile *m)
444
+{
445
+  switch(m->mdata.head.nstate){
446
+    case MAKUO_SENDSTATE_OPENINIT:
447
+      msend_md5_open_init(s, m);
448
+      break;
449
+    case MAKUO_SENDSTATE_OPEN:
450
+      msend_md5_open(s, m);
451
+      break;
452
+    case MAKUO_SENDSTATE_CLOSEINIT:
453
+      msend_md5_close_init(s, m);
454
+      break;
455
+    case MAKUO_SENDSTATE_CLOSE:
456
+      msend_md5_close(s, m);
457
+      break;
458
+  }
459
+}
460
+
461
+static void msend_retry(mfile *m)
462
+{
463
+  if(!m->sendwait){
464
+    m->retrycnt = MAKUO_SEND_RETRYCNT;
465
+  }else{
466
+    mhost *t;
467
+    lprintf(2, "msend_retry: send retry count=%02d rid=%06d state=%d %s\n", m->retrycnt, m->mdata.head.reqid, m->mdata.head.nstate, m->fn);
468
+    for(t=members;t;t=t->next){
469
+      switch(moption.loglevel){
470
+        case 3:
471
+          if(t->state == MAKUO_RECVSTATE_NONE){
472
+            lprintf(0, "msend_retry:   state=%d %s(%s)\n", t->state, inet_ntoa(t->ad), t->hostname);
473
+          }
474
+          break;
475
+        default:
476
+          lprintf(4, "msend_retry:   state=%d %s(%s)\n", t->state, inet_ntoa(t->ad), t->hostname);
477
+          break;
478
+      }
479
+    }
480
+    m->retrycnt--;
481
+  }
482
+}
483
+
484
+/*
485

                
486

                
487

                
488
+ */
489
+void msend(int s, mfile *m)
490
+{
491
+  if(!m)
492
+    return;
493
+  msend_retry(m);
494
+  mtimeget(&m->lastsend);
495
+  switch(m->mdata.head.opcode){
496
+    case MAKUO_OP_PING:
497
+    case MAKUO_OP_PONG:
498
+    case MAKUO_OP_EXIT:
499
+      msend_shot(s, m);
500
+      break;
501
+    case MAKUO_OP_ACK:
502
+      msend_ack(s, m);
503
+      break;
504
+    case MAKUO_OP_FILE:
505
+      msend_file(s, m);
506
+      break;
507
+    case MAKUO_OP_MD5:
508
+      msend_md5(s, m);
509
+      break;
510
+  }
511
+}
512
+
0 513
new file mode 100644
... ...
@@ -0,0 +1,188 @@
0
+「プロトコルフォーマット」
1
+
2
+ 0                   1                   2                   3
3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
4
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
5
+| ProtocolVer   |   Operation   |   new status  |  old status   |
6
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
7
+|           data size           |             flags             |
8
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
9
+|                         Request ID                            | 
10
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ makuo header
11
+|                       Sequence Number                         | 
12
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13
+|                                                               | 
14
+|                          checksum                             | 
15
+|                          (16byte)                             | 
16
+|                                                               | 
17
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
18
+|                                                               | 
19
+|                                                               | 
20
+|                             data                              | makuo data
21
+|                                                               | 
22
+|                                                               | 
23
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
24
+
25
+先頭に32バイトのヘッダ(まくおヘッダ)があり、そのあとに可変長データが続きます。
26
+データ最大サイズは1024バイトです。
27
+データフォーマットは OperationCode毎に定義します。
28
+まくおヘッダの各フィールドの意味は以下の通りです。
29
+
30
+- Protocol Version
31
+ まくおプロトコルのバージョン番号。
32
+ バージョン番号の異なるプロトコルは処理しません。
33
+
34
+- Operation
35
+ オペレーションコード
36
+
37
+- rid
38
+ コマンドを発行する度にインクリメントする
39
+
40
+- status
41
+ 現在の状態
42
+
43
+- old status
44
+ さっきの状態
45
+
46
+- data size
47
+ データフィールドのバイト数
48
+
49
+- Sequence Number
50
+
51
+
52
+「データフォーマット」
53
+
54
+[ping]
55
+プログラム起動時に送出するパケット。
56
+このパケットを受け取ったノードは送信者をメンバリストに追加してユニキャストで
57
+PONGを返す。
58
+
59
+ 0                   1                   2                   3
60
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
61
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
62
+|       HostName Length         |     Version String Length     | 
63
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
+|                                                               | 
65
+|                          HostName                             | 
66
+|                                                               | 
67
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
+|                                                               | 
69
+|                       Version String                          | 
70
+|                                                               | 
71
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
72
+
73
+HostName:
74
+
75
+Version String:
76
+
77
+[pong]
78
+pingに対する応答パケット。
79
+これを受け取ったノードは送信者をメンバリストに追加する。
80
+また、一定時間(MAKUO_PONG_INTERVAL)毎にマルチキャストして生存確認をする。
81
+MAKUO_PONG_TIMEOUTの間pongを確認できないノードはメンバリストから削除される。
82
+
83
+ 0                   1                   2                   3
84
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
85
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
86
+|       HostName Length         |     Version String Length     | 
87
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88
+|                                                               | 
89
+|                          HostName                             | 
90
+|                                                               | 
91
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92
+|                                                               | 
93
+|                       Version String                          | 
94
+|                                                               | 
95
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
96
+
97
+
98
+[exit]
99
+プログラム終了時に発行するパケット。
100
+受け取ったノードは送信者をメンバリストから削除する。
101
+
102
+ 0                   1                   2                   3
103
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
104
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
105
+|       HostName Length         |     Version String Length     | 
106
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107
+|                                                               | 
108
+|                          HostName                             | 
109
+|                                                               | 
110
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
111
+|                                                               | 
112
+|                       Version String                          | 
113
+|                                                               | 
114
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
115
+
116
+[send]
117
+
118
+ 0                   1                   2                   3
119
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
120
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
121
+|                              mode                             | 
122
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
123
+|           uid                 |             gid               | 
124
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
125
+|                         file size(low)                        | 
126
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
127
+|                         file size(high)                       | 
128
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
129
+|                             mtime                             | 
130
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
131
+|                             ctime                             | 
132
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
133
+|        filename length        |        linkname length        | 
134
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135
+|                                                               | 
136
+|                          filename                             | 
137
+|                                                               | 
138
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139
+|                                                               | 
140
+|                          linkname                             | 
141
+|                                                               | 
142
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------
143
+
144
+[send  Format]
145
+Operation Code  = 4 (MAKUO_OP_FILE)
146
+Sequence Number > 0 
147
+
148
+ 0                   1                   2                   3
149
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
150
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
151
+|                                                               | 
152
+|                                                               | 
153
+|                                                               | 
154
+|                                                               | 
155
+|                                                               | 
156
+|                                                               | 
157
+|                                                               | 
158
+|                                                               | 
159
+|                                                               | 
160
+|                                                               | 
161
+|                                                               | 
162
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------
163
+
164
+[md5]
165
+Operation Code  = 5 (MAKUO_OP_MD5)
166
+
167
+ 0                   1                   2                   3
168
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
169
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
170
+|                                                               | 
171
+|                             md5                               | 
172
+|                          (16bytes)                            | 
173
+|                                                               | 
174
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
175
+|        filename length        |                               | 
176
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
177
+|                                                               | 
178
+|                          filename                             | 
179
+|                   (filename length bytes)                     | 
180
+|                                                               | 
181
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--------------
182
+
183
+result:
184
+  Operation Code  = 3 (MAKUO_OP_ACK)
185
+  Status = 10 or 11 (MAKUO_RECVSTATE_MD5OK or MAKUO_RECVSTATE_MD5NG)
186
+
187
+