rem: int err; struct buffer buf2; uint32_t id = sftp_get_id(); struct request *req = (struct request *) malloc(sizeof(struct request));  buf_init(&buf2, buf->len + 4); buf_add_uint32(&buf2, id); buf_add_mem(&buf2, buf->p, buf->len);  req->want_reply = expect_type != 0 ? 1 : 0; sem_init(&req->ready, 0, 0); buf_init(&req->reply, 0); pthread_mutex_lock(&lock); err = start_processing_thread(); g_hash_table_insert(reqtab, (gpointer) id, req); gettimeofday(&req->start, NULL); DEBUG("[%05i] %s\n", id, type_name(type)); pthread_mutex_unlock(&lock); if (err) goto out;  err = -EIO; if (sftp_send(type, &buf2) == -1) { pthread_mutex_lock(&lock); g_hash_table_remove(reqtab, (gpointer) id); pthread_mutex_unlock(&lock); goto out; } if (expect_type == 0) { buf_free(&buf2); return 0; }  sem_wait(&req->ready); err = -EPROTO; if (req->reply_type != expect_type && req->reply_type != SSH_FXP_STATUS) { fprintf(stderr, "protocol error\n"); goto out; } if (req->reply_type == SSH_FXP_STATUS) { uint32_t serr; if (buf_get_uint32(&req->reply, &serr) == -1) goto out;  switch (serr) { case SSH_FX_OK: if (expect_type == SSH_FXP_STATUS) err = 0; else err = -EPROTO; break;  case SSH_FX_EOF: if (type == SSH_FXP_READ || type == SSH_FXP_READDIR) err = MY_EOF; else err = -EPROTO; break;  case SSH_FX_NO_SUCH_FILE:      err = -ENOENT; break; case SSH_FX_PERMISSION_DENIED: err = -EACCES; break; case SSH_FX_FAILURE:           err = -EPERM;  break; case SSH_FX_BAD_MESSAGE: default:                       err = -EPROTO; break; } } else { buf_init(outbuf, req->reply.size - req->reply.len); buf_get_mem(&req->reply, outbuf->p, outbuf->size); err = 0; }  out: buf_free(&buf2); buf_free(&req->reply); sem_destroy(&req->ready); free(req); return err;
add: return sftp_request_common(type, buf, expect_type, outbuf, NULL, NULL, NULL);
context: static int sftp_request(uint8_t type, const struct buffer *buf,                        uint8_t expect_type, struct buffer *outbuf){    int err;    struct buffer buf2;    uint32_t id = sftp_get_id();    struct request *req = (struct request *) malloc(sizeof(struct request));    buf_init(&buf2, buf->len + 4);    buf_add_uint32(&buf2, id);    buf_add_mem(&buf2, buf->p, buf->len);    req->want_reply = expect_type != 0 ? 1 : 0;    sem_init(&req->ready, 0, 0);    buf_init(&req->reply, 0);    pthread_mutex_lock(&lock);    err = start_processing_thread();    g_hash_table_insert(reqtab, (gpointer) id, req);    gettimeofday(&req->start, NULL);    DEBUG("[%05i] %s\n", id, type_name(type));    pthread_mutex_unlock(&lock);    if (err)        goto out;        err = -EIO;    if (sftp_send(type, &buf2) == -1) {        pthread_mutex_lock(&lock);        g_hash_table_remove(reqtab, (gpointer) id);        pthread_mutex_unlock(&lock);        goto out;    }    if (expect_type == 0) {        buf_free(&buf2);        return 0;    }    sem_wait(&req->ready);    err = -EPROTO;    if (req->reply_type != expect_type && req->reply_type != SSH_FXP_STATUS) {        fprintf(stderr, "protocol error\n");        goto out;    }    if (req->reply_type == SSH_FXP_STATUS) {        uint32_t serr;        if (buf_get_uint32(&req->reply, &serr) == -1)            goto out;                switch (serr) {        case SSH_FX_OK:            if (expect_type == SSH_FXP_STATUS)                err = 0;            else                err = -EPROTO;            break;        case SSH_FX_EOF:            if (type == SSH_FXP_READ || type == SSH_FXP_READDIR)                err = MY_EOF;            else                err = -EPROTO;            break;        case SSH_FX_NO_SUCH_FILE:      err = -ENOENT; break;        case SSH_FX_PERMISSION_DENIED: err = -EACCES; break;                    case SSH_FX_FAILURE:           err = -EPERM;  break;        case SSH_FX_BAD_MESSAGE:        default:                       err = -EPROTO; break;        }    } else {        buf_init(outbuf, req->reply.size - req->reply.len);        buf_get_mem(&req->reply, outbuf->p, outbuf->size);        err = 0;    } out:    buf_free(&buf2);    buf_free(&req->reply);    sem_destroy(&req->ready);    free(req);    return err;        }