version.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <venti.h>
  4. static char *okvers[] = {
  5. "02",
  6. nil,
  7. };
  8. /*
  9. static char EBigString[] = "string too long";
  10. static char EBigPacket[] = "packet too long";
  11. static char ENullString[] = "missing string";
  12. */
  13. static char EBadVersion[] = "bad format in version string";
  14. static int
  15. vtreadversion(VtConn *z, char *q, char *v, int nv)
  16. {
  17. int n;
  18. for(;;){
  19. if(nv <= 1){
  20. werrstr("version too long");
  21. return -1;
  22. }
  23. n = read(z->infd, v, 1);
  24. if(n <= 0){
  25. if(n == 0)
  26. werrstr("unexpected eof");
  27. return -1;
  28. }
  29. if(*v == '\n'){
  30. *v = 0;
  31. break;
  32. }
  33. if((uchar)*v < ' ' || (uchar)*v > 0x7f || (*q && *v != *q)){
  34. werrstr(EBadVersion);
  35. return -1;
  36. }
  37. v++;
  38. nv--;
  39. if(*q)
  40. q++;
  41. }
  42. return 0;
  43. }
  44. int
  45. vtversion(VtConn *z)
  46. {
  47. char buf[VtMaxStringSize], *p, *ep, *prefix, *pp;
  48. int i;
  49. qlock(&z->lk);
  50. if(z->state != VtStateAlloc){
  51. werrstr("bad session state");
  52. qunlock(&z->lk);
  53. return -1;
  54. }
  55. qlock(&z->inlk);
  56. qlock(&z->outlk);
  57. p = buf;
  58. ep = buf + sizeof buf;
  59. prefix = "venti-";
  60. p = seprint(p, ep, "%s", prefix);
  61. p += strlen(p);
  62. for(i=0; okvers[i]; i++)
  63. p = seprint(p, ep, "%s%s", i ? ":" : "", okvers[i]);
  64. p = seprint(p, ep, "-libventi\n");
  65. assert(p-buf < sizeof buf);
  66. if(write(z->outfd, buf, p-buf) != p-buf)
  67. goto Err;
  68. vtdebug(z, "version string out: %s", buf);
  69. if(vtreadversion(z, prefix, buf, sizeof buf) < 0)
  70. goto Err;
  71. vtdebug(z, "version string in: %s", buf);
  72. p = buf+strlen(prefix);
  73. for(; *p; p=pp){
  74. if(*p == ':' || *p == '-')
  75. p++;
  76. pp = strpbrk(p, ":-");
  77. if(pp == nil)
  78. pp = p+strlen(p);
  79. for(i=0; okvers[i]; i++)
  80. if(strlen(okvers[i]) == pp-p && memcmp(okvers[i], p, pp-p) == 0){
  81. *pp = 0;
  82. z->version = vtstrdup(p);
  83. goto Okay;
  84. }
  85. }
  86. werrstr("unable to negotiate version");
  87. goto Err;
  88. Okay:
  89. z->state = VtStateConnected;
  90. qunlock(&z->inlk);
  91. qunlock(&z->outlk);
  92. qunlock(&z->lk);
  93. return 0;
  94. Err:
  95. werrstr("vtversion: %r");
  96. if(z->infd >= 0)
  97. close(z->infd);
  98. if(z->outfd >= 0 && z->outfd != z->infd)
  99. close(z->outfd);
  100. z->infd = -1;
  101. z->outfd = -1;
  102. z->state = VtStateClosed;
  103. qunlock(&z->inlk);
  104. qunlock(&z->outlk);
  105. qunlock(&z->lk);
  106. return -1;
  107. }