version.c 2.5 KB

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