[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.33

1.33    ! deraadt     1: /*     $OpenBSD: remote.c,v 1.32 2017/08/28 19:33:20 otto 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.30      deraadt    18: #include <sys/param.h> /* MAXBSIZE */
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))
                     32:
1.1       joris      33: struct cvs_resp *
                     34: cvs_remote_get_response_info(const char *response)
                     35: {
                     36:        int i;
                     37:
                     38:        for (i = 0; cvs_responses[i].supported != -1; i++) {
                     39:                if (!strcmp(cvs_responses[i].name, response))
                     40:                        return (&(cvs_responses[i]));
                     41:        }
                     42:
                     43:        return (NULL);
                     44: }
                     45:
                     46: struct cvs_req *
                     47: cvs_remote_get_request_info(const char *request)
                     48: {
                     49:        int i;
                     50:
                     51:        for (i = 0; cvs_requests[i].supported != -1; i++) {
                     52:                if (!strcmp(cvs_requests[i].name, request))
                     53:                        return (&(cvs_requests[i]));
                     54:        }
                     55:
                     56:        return (NULL);
                     57: }
                     58:
                     59: void
1.32      otto       60: cvs_remote_output(char *data)
1.1       joris      61: {
                     62:        FILE *out;
1.17      tobias     63:        size_t len;
1.16      tobias     64:        char nl = '\n';
1.1       joris      65:
                     66:        if (cvs_server_active)
                     67:                out = stdout;
                     68:        else
                     69:                out = current_cvsroot->cr_srvin;
                     70:
                     71:        fputs(data, out);
                     72:        fputs("\n", out);
1.16      tobias     73:
                     74:        if (cvs_server_active == 0 && cvs_client_inlog_fd != -1) {
1.17      tobias     75:                len = strlen(data);
                     76:                if (atomicio(vwrite, cvs_client_inlog_fd, data, len) != len ||
                     77:                    atomicio(vwrite, cvs_client_inlog_fd, &nl, 1) != 1)
                     78:                        fatal("failed to write to log file");
1.16      tobias     79:        }
1.1       joris      80: }
                     81:
                     82: char *
                     83: cvs_remote_input(void)
                     84: {
                     85:        FILE *in;
                     86:        size_t len;
1.16      tobias     87:        char nl = '\n';
1.1       joris      88:        char *data, *ldata;
                     89:
                     90:        if (cvs_server_active)
                     91:                in = stdin;
                     92:        else
                     93:                in = current_cvsroot->cr_srvout;
                     94:
                     95:        data = fgetln(in, &len);
                     96:        if (data == NULL) {
                     97:                if (sig_received != 0)
                     98:                        fatal("received signal %d", sig_received);
                     99:
                    100:                if (cvs_server_active) {
                    101:                        cvs_cleanup();
                    102:                        exit(0);
                    103:                }
                    104:
                    105:                fatal("the connection has been closed by the server");
                    106:        }
                    107:
                    108:        if (data[len - 1] == '\n') {
                    109:                data[len - 1] = '\0';
1.9       otto      110:                ldata = xstrdup(data);
1.1       joris     111:        } else {
                    112:                ldata = xmalloc(len + 1);
1.9       otto      113:                memcpy(ldata, data, len);
                    114:                ldata[len] = '\0';
1.1       joris     115:        }
1.5       joris     116:
                    117:        if (cvs_server_active == 0 && cvs_client_outlog_fd != -1) {
1.17      tobias    118:                len = strlen(data);
                    119:                if (atomicio(vwrite, cvs_client_outlog_fd, data, len) != len ||
                    120:                    atomicio(vwrite, cvs_client_outlog_fd, &nl, 1) != 1)
                    121:                        fatal("failed to write to log file");
1.5       joris     122:        }
                    123:
1.1       joris     124:        return (ldata);
                    125: }
                    126:
1.6       joris     127: void
                    128: cvs_remote_receive_file(int fd, size_t len)
1.1       joris     129: {
                    130:        FILE *in;
1.10      otto      131:        char data[MAXBSIZE];
1.17      tobias    132:        size_t nread, nleft, toread;
1.1       joris     133:
                    134:        if (cvs_server_active)
                    135:                in = stdin;
                    136:        else
                    137:                in = current_cvsroot->cr_srvout;
                    138:
1.6       joris     139:        nleft = len;
                    140:
                    141:        while (nleft > 0) {
1.30      deraadt   142:                toread = MINIMUM(nleft, MAXBSIZE);
1.6       joris     143:
                    144:                nread = fread(data, sizeof(char), toread, in);
                    145:                if (nread == 0)
                    146:                        fatal("error receiving file");
1.4       joris     147:
1.17      tobias    148:                if (atomicio(vwrite, fd, data, nread) != nread)
1.8       otto      149:                        fatal("failed to write %zu bytes", nread);
1.6       joris     150:
1.17      tobias    151:                if (cvs_server_active == 0 && cvs_client_outlog_fd != -1 &&
                    152:                    atomicio(vwrite, cvs_client_outlog_fd, data, nread)
                    153:                    != nread)
                    154:                        fatal("failed to write to log file");
1.1       joris     155:
1.6       joris     156:                nleft -= nread;
1.5       joris     157:        }
1.1       joris     158: }
                    159:
                    160: void
1.21      joris     161: cvs_remote_send_file(const char *path, int _fd)
1.1       joris     162: {
1.13      xsa       163:        int fd;
1.6       joris     164:        FILE *out, *in;
1.8       otto      165:        size_t ret, rw;
                    166:        off_t total;
1.1       joris     167:        struct stat st;
1.11      otto      168:        char buf[18], data[MAXBSIZE];
1.1       joris     169:
                    170:        if (cvs_server_active)
                    171:                out = stdout;
                    172:        else
                    173:                out = current_cvsroot->cr_srvin;
                    174:
1.21      joris     175:        fd = dup(_fd);
                    176:        if (fd == -1)
                    177:                fatal("cvs_remote_send_file: dup: %s", strerror(errno));
                    178:
1.33    ! deraadt   179:        if (lseek(fd, 0, SEEK_SET) == -1)
1.21      joris     180:                fatal("cvs_remote_send_file: %s: lseek: %s", path,
                    181:                    strerror(errno));
1.1       joris     182:
                    183:        if (fstat(fd, &st) == -1)
1.21      joris     184:                fatal("cvs_remote_send_file: %s: fstat: %s", path,
                    185:                    strerror(errno));
1.1       joris     186:
                    187:        cvs_modetostr(st.st_mode, buf, sizeof(buf));
                    188:        cvs_remote_output(buf);
                    189:
1.13      xsa       190:        (void)xsnprintf(buf, sizeof(buf), "%lld", st.st_size);
1.1       joris     191:        cvs_remote_output(buf);
                    192:
1.6       joris     193:        if ((in = fdopen(fd, "r")) == NULL)
                    194:                fatal("cvs_remote_send_file: fdopen %s", strerror(errno));
                    195:
                    196:        total = 0;
                    197:        while ((ret = fread(data, sizeof(char), MAXBSIZE, in)) != 0) {
                    198:                rw = fwrite(data, sizeof(char), ret, out);
                    199:                if (rw != ret)
1.8       otto      200:                        fatal("failed to write %zu bytes", ret);
1.5       joris     201:
1.17      tobias    202:                if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
                    203:                    atomicio(vwrite, cvs_client_inlog_fd, data, ret) != ret)
                    204:                        fatal("failed to write to log file");
1.6       joris     205:
                    206:                total += ret;
1.5       joris     207:        }
1.1       joris     208:
1.6       joris     209:        if (total != st.st_size)
1.8       otto      210:                fatal("length mismatch, %lld vs %lld", total, st.st_size);
1.4       joris     211:
1.6       joris     212:        (void)fclose(in);
1.23      joris     213: }
                    214:
                    215: void
                    216: cvs_remote_send_file_buf(char *file, BUF *bp, mode_t mode)
                    217: {
                    218:        char buf[18];
                    219:        u_char *data;
                    220:        size_t len, ret;
                    221:
                    222:        if (cvs_server_active != 1)
                    223:                fatal("cvs_remote_send_file_buf is server only");
                    224:
1.29      ray       225:        len = buf_len(bp);
                    226:        data = buf_release(bp);
1.23      joris     227:
                    228:        cvs_modetostr(mode, buf, sizeof(buf));
                    229:        cvs_remote_output(buf);
                    230:
                    231:        (void)xsnprintf(buf, sizeof(buf), "%ld", len);
                    232:        cvs_remote_output(buf);
                    233:
                    234:        ret = fwrite(data, sizeof(char), len, stdout);
                    235:        if (ret != len)
                    236:                cvs_log(LP_ERR, "warning: sent %s truncated", file);
                    237:
                    238:        if (cvs_server_active == 0 && cvs_client_inlog_fd != -1 &&
                    239:            atomicio(vwrite, cvs_client_inlog_fd, data, len) != len)
                    240:                fatal("failed to write to log file");
                    241:
1.31      nicm      242:        free(data);
1.1       joris     243: }
                    244:
                    245: void
                    246: cvs_remote_classify_file(struct cvs_file *cf)
                    247: {
                    248:        struct stat st;
                    249:        CVSENTRIES *entlist;
                    250:
                    251:        entlist = cvs_ent_open(cf->file_wd);
                    252:        cf->file_ent = cvs_ent_get(entlist, cf->file_name);
                    253:
                    254:        if (cf->file_ent != NULL && cf->file_ent->ce_status != CVS_ENT_REG) {
1.28      joris     255:                if (cf->file_ent->ce_status == CVS_ENT_ADDED) {
                    256:                        if (cf->fd != -1)
                    257:                                cf->file_status = FILE_ADDED;
                    258:                        else
                    259:                                cf->file_status = FILE_UNKNOWN;
                    260:                } else {
1.1       joris     261:                        cf->file_status = FILE_REMOVED;
1.28      joris     262:                }
                    263:
1.1       joris     264:                return;
1.2       joris     265:        }
                    266:
                    267:        if (cf->file_ent != NULL) {
                    268:                if (cf->file_ent->ce_type == CVS_ENT_DIR)
                    269:                        cf->file_type = CVS_DIR;
                    270:                else
                    271:                        cf->file_type = CVS_FILE;
1.1       joris     272:        }
                    273:
1.25      joris     274:        if (cf->fd != -1)
                    275:                cf->file_flags |= FILE_ON_DISK;
                    276:
                    277:        if ((cf->file_flags & FILE_ON_DISK) && cf->file_ent != NULL) {
1.1       joris     278:                if (fstat(cf->fd, &st) == -1)
                    279:                        fatal("cvs_remote_classify_file(%s): %s", cf->file_path,
                    280:                            strerror(errno));
                    281:
1.27      joris     282:                if (st.st_mtime != cf->file_ent->ce_mtime ||
                    283:                    cf->file_ent->ce_conflict != NULL)
1.1       joris     284:                        cf->file_status = FILE_MODIFIED;
                    285:                else
                    286:                        cf->file_status = FILE_UPTODATE;
1.25      joris     287:        } else if (!(cf->file_flags & FILE_ON_DISK)) {
1.1       joris     288:                cf->file_status = FILE_UNKNOWN;
                    289:        }
1.7       joris     290:
                    291:        if (cvs_cmdop == CVS_OP_IMPORT && cf->file_type == CVS_FILE)
                    292:                cf->file_status = FILE_MODIFIED;
1.1       joris     293: }
                    294:
1.18      joris     295:
                    296: void
                    297: cvs_validate_directory(const char *path)
                    298: {
                    299:        char *dir, *sp, *dp;
                    300:
1.20      joris     301:        dir = xstrdup(path);
1.18      joris     302:
                    303:        for (sp = dir; sp != NULL; sp = dp) {
                    304:                dp = strchr(sp, '/');
                    305:                if (dp != NULL)
                    306:                        *(dp++) = '\0';
                    307:
                    308:                if (!strcmp(sp, ".."))
                    309:                        fatal("path validation failed!");
                    310:        }
                    311:
1.31      nicm      312:        free(dir);
1.18      joris     313: }