[BACK]Return to remote.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/remote.c, Revision 1.34

1.34    ! deraadt     1: /*     $OpenBSD: remote.c,v 1.33 2019/06/28 13:35:00 deraadt Exp $     */
1.1       joris       2: /*
                      3:  * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
1.34    ! deraadt    18: #include <sys/types.h>
1.14      otto       19: #include <sys/stat.h>
                     20:
                     21: #include <errno.h>
                     22: #include <fcntl.h>
                     23: #include <stdlib.h>
                     24: #include <string.h>
                     25: #include <unistd.h>
1.1       joris      26:
1.17      tobias     27: #include "atomicio.h"
1.1       joris      28: #include "cvs.h"
                     29: #include "remote.h"
                     30:
1.30      deraadt    31: #define MINIMUM(a, b)  (((a) < (b)) ? (a) : (b))
1.34    ! deraadt    32: #define _MAXBSIZE      (64 * 1024)
1.30      deraadt    33:
1.1       joris      34: struct cvs_resp *
                     35: cvs_remote_get_response_info(const char *response)
                     36: {
                     37:        int i;
                     38:
                     39:        for (i = 0; cvs_responses[i].supported != -1; i++) {
                     40:                if (!strcmp(cvs_responses[i].name, response))
                     41:                        return (&(cvs_responses[i]));
                     42:        }
                     43:
                     44:        return (NULL);
                     45: }
                     46:
                     47: struct cvs_req *
                     48: cvs_remote_get_request_info(const char *request)
                     49: {
                     50:        int i;
                     51:
                     52:        for (i = 0; cvs_requests[i].supported != -1; i++) {
                     53:                if (!strcmp(cvs_requests[i].name, request))
                     54:                        return (&(cvs_requests[i]));
                     55:        }
                     56:
                     57:        return (NULL);
                     58: }
                     59:
                     60: void
1.32      otto       61: cvs_remote_output(char *data)
1.1       joris      62: {
                     63:        FILE *out;
1.17      tobias     64:        size_t len;
1.16      tobias     65:        char nl = '\n';
1.1       joris      66:
                     67:        if (cvs_server_active)
                     68:                out = stdout;
                     69:        else
                     70:                out = current_cvsroot->cr_srvin;
                     71:
                     72:        fputs(data, out);
                     73:        fputs("\n", out);
1.16      tobias     74:
                     75:        if (cvs_server_active == 0 && cvs_client_inlog_fd != -1) {
1.17      tobias     76:                len = strlen(data);
                     77:                if (atomicio(vwrite, cvs_client_inlog_fd, data, len) != len ||
                     78:                    atomicio(vwrite, cvs_client_inlog_fd, &nl, 1) != 1)
                     79:                        fatal("failed to write to log file");
1.16      tobias     80:        }
1.1       joris      81: }
                     82:
                     83: char *
                     84: cvs_remote_input(void)
                     85: {
                     86:        FILE *in;
                     87:        size_t len;
1.16      tobias     88:        char nl = '\n';
1.1       joris      89:        char *data, *ldata;
                     90:
                     91:        if (cvs_server_active)
                     92:                in = stdin;
                     93:        else
                     94:                in = current_cvsroot->cr_srvout;
                     95:
                     96:        data = fgetln(in, &len);
                     97:        if (data == NULL) {
                     98:                if (sig_received != 0)
                     99:                        fatal("received signal %d", sig_received);
                    100:
                    101:                if (cvs_server_active) {
                    102:                        cvs_cleanup();
                    103:                        exit(0);
                    104:                }
                    105:
                    106:                fatal("the connection has been closed by the server");
                    107:        }
                    108:
                    109:        if (data[len - 1] == '\n') {
                    110:                data[len - 1] = '\0';
1.9       otto      111:                ldata = xstrdup(data);
1.1       joris     112:        } else {
                    113:                ldata = xmalloc(len + 1);
1.9       otto      114:                memcpy(ldata, data, len);
                    115:                ldata[len] = '\0';
1.1       joris     116:        }
1.5       joris     117:
                    118:        if (cvs_server_active == 0 && cvs_client_outlog_fd != -1) {
1.17      tobias    119:                len = strlen(data);
                    120:                if (atomicio(vwrite, cvs_client_outlog_fd, data, len) != len ||
                    121:                    atomicio(vwrite, cvs_client_outlog_fd, &nl, 1) != 1)
                    122:                        fatal("failed to write to log file");
1.5       joris     123:        }
                    124:
1.1       joris     125:        return (ldata);
                    126: }
                    127:
1.6       joris     128: void
                    129: cvs_remote_receive_file(int fd, size_t len)
1.1       joris     130: {
                    131:        FILE *in;
1.34    ! deraadt   132:        char data[_MAXBSIZE];
1.17      tobias    133:        size_t nread, nleft, toread;
1.1       joris     134:
                    135:        if (cvs_server_active)
                    136:                in = stdin;
                    137:        else
                    138:                in = current_cvsroot->cr_srvout;
                    139:
1.6       joris     140:        nleft = len;
                    141:
                    142:        while (nleft > 0) {
1.34    ! deraadt   143:                toread = MINIMUM(nleft, sizeof data);
1.6       joris     144:
                    145:                nread = fread(data, sizeof(char), toread, in);
                    146:                if (nread == 0)
                    147:                        fatal("error receiving file");
1.4       joris     148:
1.17      tobias    149:                if (atomicio(vwrite, fd, data, nread) != nread)
1.8       otto      150:                        fatal("failed to write %zu bytes", nread);
1.6       joris     151:
1.17      tobias    152:                if (cvs_server_active == 0 && cvs_client_outlog_fd != -1 &&
                    153:                    atomicio(vwrite, cvs_client_outlog_fd, data, nread)
                    154:                    != nread)
                    155:                        fatal("failed to write to log file");
1.1       joris     156:
1.6       joris     157:                nleft -= nread;
1.5       joris     158:        }
1.1       joris     159: }
                    160:
                    161: void
1.21      joris     162: cvs_remote_send_file(const char *path, int _fd)
1.1       joris     163: {
1.13      xsa       164:        int fd;
1.6       joris     165:        FILE *out, *in;
1.8       otto      166:        size_t ret, rw;
                    167:        off_t total;
1.1       joris     168:        struct stat st;
1.34    ! deraadt   169:        char buf[18], data[_MAXBSIZE];
1.1       joris     170:
                    171:        if (cvs_server_active)
                    172:                out = stdout;
                    173:        else
                    174:                out = current_cvsroot->cr_srvin;
                    175:
1.21      joris     176:        fd = dup(_fd);
                    177:        if (fd == -1)
                    178:                fatal("cvs_remote_send_file: dup: %s", strerror(errno));
                    179:
1.33      deraadt   180:        if (lseek(fd, 0, SEEK_SET) == -1)
1.21      joris     181:                fatal("cvs_remote_send_file: %s: lseek: %s", path,
                    182:                    strerror(errno));
1.1       joris     183:
                    184:        if (fstat(fd, &st) == -1)
1.21      joris     185:                fatal("cvs_remote_send_file: %s: fstat: %s", path,
                    186:                    strerror(errno));
1.1       joris     187:
                    188:        cvs_modetostr(st.st_mode, buf, sizeof(buf));
                    189:        cvs_remote_output(buf);
                    190:
1.13      xsa       191:        (void)xsnprintf(buf, sizeof(buf), "%lld", st.st_size);
1.1       joris     192:        cvs_remote_output(buf);
                    193:
1.6       joris     194:        if ((in = fdopen(fd, "r")) == NULL)
                    195:                fatal("cvs_remote_send_file: fdopen %s", strerror(errno));
                    196:
                    197:        total = 0;
1.34    ! deraadt   198:        while ((ret = fread(data, sizeof(char), sizeof data, in)) != 0) {
1.6       joris     199:                rw = fwrite(data, sizeof(char), ret, out);
                    200:                if (rw != ret)
1.8       otto      201:                        fatal("failed to write %zu bytes", ret);
1.5       joris     202:
1.17      tobias    203:                if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
                    204:                    atomicio(vwrite, cvs_client_inlog_fd, data, ret) != ret)
                    205:                        fatal("failed to write to log file");
1.6       joris     206:
                    207:                total += ret;
1.5       joris     208:        }
1.1       joris     209:
1.6       joris     210:        if (total != st.st_size)
1.8       otto      211:                fatal("length mismatch, %lld vs %lld", total, st.st_size);
1.4       joris     212:
1.6       joris     213:        (void)fclose(in);
1.23      joris     214: }
                    215:
                    216: void
                    217: cvs_remote_send_file_buf(char *file, BUF *bp, mode_t mode)
                    218: {
                    219:        char buf[18];
                    220:        u_char *data;
                    221:        size_t len, ret;
                    222:
                    223:        if (cvs_server_active != 1)
                    224:                fatal("cvs_remote_send_file_buf is server only");
                    225:
1.29      ray       226:        len = buf_len(bp);
                    227:        data = buf_release(bp);
1.23      joris     228:
                    229:        cvs_modetostr(mode, buf, sizeof(buf));
                    230:        cvs_remote_output(buf);
                    231:
                    232:        (void)xsnprintf(buf, sizeof(buf), "%ld", len);
                    233:        cvs_remote_output(buf);
                    234:
                    235:        ret = fwrite(data, sizeof(char), len, stdout);
                    236:        if (ret != len)
                    237:                cvs_log(LP_ERR, "warning: sent %s truncated", file);
                    238:
                    239:        if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
                    240:            atomicio(vwrite, cvs_client_inlog_fd, data, len) != len)
                    241:                fatal("failed to write to log file");
                    242:
1.31      nicm      243:        free(data);
1.1       joris     244: }
                    245:
                    246: void
                    247: cvs_remote_classify_file(struct cvs_file *cf)
                    248: {
                    249:        struct stat st;
                    250:        CVSENTRIES *entlist;
                    251:
                    252:        entlist = cvs_ent_open(cf->file_wd);
                    253:        cf->file_ent = cvs_ent_get(entlist, cf->file_name);
                    254:
                    255:        if (cf->file_ent != NULL && cf->file_ent->ce_status != CVS_ENT_REG) {
1.28      joris     256:                if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
                    257:                        if (cf->fd != -1)
                    258:                                cf->file_status = FILE_ADDED;
                    259:                        else
                    260:                                cf->file_status = FILE_UNKNOWN;
                    261:                } else {
1.1       joris     262:                        cf->file_status = FILE_REMOVED;
1.28      joris     263:                }
                    264:
1.1       joris     265:                return;
1.2       joris     266:        }
                    267:
                    268:        if (cf->file_ent != NULL) {
                    269:                if (cf->file_ent->ce_type == CVS_ENT_DIR)
                    270:                        cf->file_type = CVS_DIR;
                    271:                else
                    272:                        cf->file_type = CVS_FILE;
1.1       joris     273:        }
                    274:
1.25      joris     275:        if (cf->fd != -1)
                    276:                cf->file_flags |= FILE_ON_DISK;
                    277:
                    278:        if ((cf->file_flags & FILE_ON_DISK) && cf->file_ent != NULL) {
1.1       joris     279:                if (fstat(cf->fd, &st) == -1)
                    280:                        fatal("cvs_remote_classify_file(%s): %s", cf->file_path,
                    281:                            strerror(errno));
                    282:
1.27      joris     283:                if (st.st_mtime != cf->file_ent->ce_mtime ||
                    284:                    cf->file_ent->ce_conflict != NULL)
1.1       joris     285:                        cf->file_status = FILE_MODIFIED;
                    286:                else
                    287:                        cf->file_status = FILE_UPTODATE;
1.25      joris     288:        } else if (!(cf->file_flags & FILE_ON_DISK)) {
1.1       joris     289:                cf->file_status = FILE_UNKNOWN;
                    290:        }
1.7       joris     291:
                    292:        if (cvs_cmdop == CVS_OP_IMPORT && cf->file_type == CVS_FILE)
                    293:                cf->file_status = FILE_MODIFIED;
1.1       joris     294: }
                    295:
1.18      joris     296:
                    297: void
                    298: cvs_validate_directory(const char *path)
                    299: {
                    300:        char *dir, *sp, *dp;
                    301:
1.20      joris     302:        dir = xstrdup(path);
1.18      joris     303:
                    304:        for (sp = dir; sp != NULL; sp = dp) {
                    305:                dp = strchr(sp, '/');
                    306:                if (dp != NULL)
                    307:                        *(dp++) = '\0';
                    308:
                    309:                if (!strcmp(sp, ".."))
                    310:                        fatal("path validation failed!");
                    311:        }
                    312:
1.31      nicm      313:        free(dir);
1.18      joris     314: }