db69c889e79da7afac3fc7791000fd31ec61adb5
   1#include "cache.h"
   2#include "rsh.h"
   3#include "refs.h"
   4
   5#include <string.h>
   6
   7unsigned char local_version = 1;
   8unsigned char remote_version = 0;
   9
  10int serve_object(int fd_in, int fd_out) {
  11        ssize_t size;
  12        int posn = 0;
  13        unsigned char sha1[20];
  14        unsigned long objsize;
  15        void *buf;
  16        signed char remote;
  17        do {
  18                size = read(fd_in, sha1 + posn, 20 - posn);
  19                if (size < 0) {
  20                        perror("git-ssh-push: read ");
  21                        return -1;
  22                }
  23                if (!size)
  24                        return -1;
  25                posn += size;
  26        } while (posn < 20);
  27        
  28        /* fprintf(stderr, "Serving %s\n", sha1_to_hex(sha1)); */
  29        remote = 0;
  30        
  31        buf = map_sha1_file(sha1, &objsize);
  32        
  33        if (!buf) {
  34                fprintf(stderr, "git-ssh-push: could not find %s\n", 
  35                        sha1_to_hex(sha1));
  36                remote = -1;
  37        }
  38        
  39        write(fd_out, &remote, 1);
  40        
  41        if (remote < 0)
  42                return 0;
  43        
  44        posn = 0;
  45        do {
  46                size = write(fd_out, buf + posn, objsize - posn);
  47                if (size <= 0) {
  48                        if (!size) {
  49                                fprintf(stderr, "git-ssh-push: write closed");
  50                        } else {
  51                                perror("git-ssh-push: write ");
  52                        }
  53                        return -1;
  54                }
  55                posn += size;
  56        } while (posn < objsize);
  57        return 0;
  58}
  59
  60int serve_version(int fd_in, int fd_out)
  61{
  62        if (read(fd_in, &remote_version, 1) < 1)
  63                return -1;
  64        write(fd_out, &local_version, 1);
  65        return 0;
  66}
  67
  68int serve_ref(int fd_in, int fd_out)
  69{
  70        char ref[PATH_MAX];
  71        unsigned char sha1[20];
  72        int posn = 0;
  73        signed char remote = 0;
  74        do {
  75                if (read(fd_in, ref + posn, 1) < 1)
  76                        return -1;
  77                posn++;
  78        } while (ref[posn - 1]);
  79        if (get_ref_sha1(ref, sha1))
  80                remote = -1;
  81        write(fd_out, &remote, 1);
  82        if (remote)
  83                return 0;
  84        write(fd_out, sha1, 20);
  85        return 0;
  86}
  87
  88
  89void service(int fd_in, int fd_out) {
  90        char type;
  91        int retval;
  92        do {
  93                retval = read(fd_in, &type, 1);
  94                if (retval < 1) {
  95                        if (retval < 0)
  96                                perror("git-ssh-push: read ");
  97                        return;
  98                }
  99                if (type == 'v' && serve_version(fd_in, fd_out))
 100                        return;
 101                if (type == 'o' && serve_object(fd_in, fd_out))
 102                        return;
 103                if (type == 'r' && serve_ref(fd_in, fd_out))
 104                        return;
 105        } while (1);
 106}
 107
 108static const char *ssh_push_usage =
 109        "git-ssh-push [-c] [-t] [-a] [-w ref] commit-id url";
 110
 111int main(int argc, char **argv)
 112{
 113        int arg = 1;
 114        char *commit_id;
 115        char *url;
 116        int fd_in, fd_out;
 117        const char *prog = getenv("GIT_SSH_PULL") ? : "git-ssh-pull";
 118        unsigned char sha1[20];
 119        char hex[41];
 120
 121        while (arg < argc && argv[arg][0] == '-') {
 122                if (argv[arg][1] == 'w')
 123                        arg++;
 124                arg++;
 125        }
 126        if (argc < arg + 2)
 127                usage(ssh_push_usage);
 128        commit_id = argv[arg];
 129        url = argv[arg + 1];
 130        if (get_sha1(commit_id, sha1))
 131                usage(ssh_push_usage);
 132        memcpy(hex, sha1_to_hex(sha1), sizeof(hex));
 133        argv[arg] = hex;
 134
 135        if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
 136                return 1;
 137
 138        service(fd_in, fd_out);
 139        return 0;
 140}