ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/usr.bin/patch/inp.c
(Generate patch)

Comparing trunk/usr.bin/patch/inp.c (file contents):
Revision 11458 by laffer1, Sun Sep 4 01:22:34 2016 UTC vs.
Revision 11459 by laffer1, Sat Jul 7 16:51:18 2018 UTC

# Line 25 | Line 25
25   * behaviour
26   *
27   * $OpenBSD: inp.c,v 1.36 2012/04/10 14:46:34 ajacoutot Exp $
28 < * $FreeBSD: stable/11/usr.bin/patch/inp.c 286795 2015-08-15 00:42:33Z delphij $
28 > * $FreeBSD: stable/10/usr.bin/patch/inp.c 287223 2015-08-27 21:52:09Z delphij $
29   */
30  
31   #include <sys/types.h>
# Line 62 | Line 62 | static char    empty_line[] = { '\0' };
62   static int      tifd = -1;      /* plan b virtual string array */
63   static char     *tibuf[2];      /* plan b buffers */
64   static LINENUM  tiline[2] = {-1, -1};   /* 1st line in each buffer */
65 < static size_t   lines_per_buf;  /* how many lines per buffer */
66 < static size_t   tibuflen;       /* plan b buffer length */
67 < static size_t   tireclen;       /* length of records in tmp file */
65 > static LINENUM  lines_per_buf;  /* how many lines per buffer */
66 > static int      tireclen;       /* length of records in tmp file */
67  
68   static bool     rev_in_string(const char *);
69   static bool     reallocate_lines(size_t *);
# Line 138 | Line 137 | reallocate_lines(size_t *lines_allocated)
137   static bool
138   plan_a(const char *filename)
139   {
140 <        int             ifd, statfailed;
141 <        char            *p, *s;
140 >        int             ifd, statfailed, pstat;
141 >        char            *p, *s, lbuf[INITLINELEN];
142          struct stat     filestat;
143          ptrdiff_t       sz;
144          size_t          i;
145          size_t          iline, lines_allocated;
146 +        pid_t           pid;
147  
148   #ifdef DEBUGGING
149          if (debug & 8)
# Line 169 | Line 169 | plan_a(const char *filename)
169                  close(creat(filename, 0666));
170                  statfailed = stat(filename, &filestat);
171          }
172 <        if (statfailed)
173 <                fatal("can't find %s\n", filename);
172 >        if (statfailed && check_only)
173 >                fatal("%s not found, -C mode, can't probe further\n", filename);
174 >        /* For nonexistent or read-only files, look for RCS versions.  */
175 >
176 >        if (statfailed ||
177 >            /* No one can write to it.  */
178 >            (filestat.st_mode & 0222) == 0 ||
179 >            /* I can't write to it.  */
180 >            ((filestat.st_mode & 0022) == 0 && filestat.st_uid != getuid())) {
181 >                char    *filebase, *filedir;
182 >                struct stat     cstat;
183 >                char    *tmp_filename1, *tmp_filename2;
184 >                char    *argp[4] = { NULL };
185 >                posix_spawn_file_actions_t file_actions;
186 >
187 >                tmp_filename1 = strdup(filename);
188 >                tmp_filename2 = strdup(filename);
189 >                if (tmp_filename1 == NULL || tmp_filename2 == NULL)
190 >                        fatal("strdupping filename");
191 >
192 >                filebase = basename(tmp_filename1);
193 >                filedir = dirname(tmp_filename2);
194 >
195 >                memset(argp, 0, sizeof(argp));
196 >
197 > #define try(f, a1, a2, a3) \
198 >        (snprintf(lbuf, sizeof(lbuf), f, a1, a2, a3), stat(lbuf, &cstat) == 0)
199 >
200 >                /*
201 >                 * else we can't write to it but it's not under a version
202 >                 * control system, so just proceed.
203 >                 */
204 >                if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
205 >                    try("%s/RCS/%s%s", filedir, filebase, "") ||
206 >                    try("%s/%s%s", filedir, filebase, RCSSUFFIX)) {
207 >                        if (!statfailed) {
208 >                                if ((filestat.st_mode & 0222) != 0)
209 >                                        /* The owner can write to it.  */
210 >                                        fatal("file %s seems to be locked "
211 >                                            "by somebody else under RCS\n",
212 >                                            filename);
213 >                                /*
214 >                                 * It might be checked out unlocked.  See if
215 >                                 * it's safe to check out the default version
216 >                                 * locked.
217 >                                 */
218 >                                if (verbose)
219 >                                        say("Comparing file %s to default "
220 >                                            "RCS version...\n", filename);
221 >
222 >                                argp[0] = __DECONST(char *, RCSDIFF);
223 >                                argp[1] = __DECONST(char *, filename);
224 >                                posix_spawn_file_actions_init(&file_actions);
225 >                                posix_spawn_file_actions_addopen(&file_actions,
226 >                                    STDOUT_FILENO, _PATH_DEVNULL, O_WRONLY, 0);
227 >                                if (posix_spawn(&pid, RCSDIFF, &file_actions,
228 >                                    NULL, argp, NULL) == 0) {
229 >                                        pid = waitpid(pid, &pstat, 0);
230 >                                        if (pid == -1 || WEXITSTATUS(pstat) != 0)
231 >                                                fatal("can't check out file %s: "
232 >                                                    "differs from default RCS version\n",
233 >                                                    filename);
234 >                                } else
235 >                                        fatal("posix_spawn: %s\n", strerror(errno));
236 >                                posix_spawn_file_actions_destroy(&file_actions);
237 >                        }
238 >
239 >                        if (verbose)
240 >                                say("Checking out file %s from RCS...\n",
241 >                                    filename);
242 >
243 >                        argp[0] = __DECONST(char *, CHECKOUT);
244 >                        argp[1] = __DECONST(char *, "-l");
245 >                        argp[2] = __DECONST(char *, filename);
246 >                        if (posix_spawn(&pid, CHECKOUT, NULL, NULL, argp,
247 >                            NULL) == 0) {
248 >                                pid = waitpid(pid, &pstat, 0);
249 >                                if (pid == -1 || WEXITSTATUS(pstat) != 0 ||
250 >                                    stat(filename, &filestat))
251 >                                        fatal("can't check out file %s from RCS\n",
252 >                                            filename);
253 >                        } else
254 >                                fatal("posix_spawn: %s\n", strerror(errno));
255 >                } else if (statfailed) {
256 >                        fatal("can't find %s\n", filename);
257 >                }
258 >                free(tmp_filename1);
259 >                free(tmp_filename2);
260 >        }
261 >
262          filemode = filestat.st_mode;
263          if (!S_ISREG(filemode))
264                  fatal("%s is not a normal file--can't patch\n", filename);
# Line 252 | Line 340 | plan_a(const char *filename)
340          /* now check for revision, if any */
341  
342          if (revision != NULL) {
343 <                if (i_womp == NULL || !rev_in_string(i_womp)) {
343 >                if (!rev_in_string(i_womp)) {
344                          if (force) {
345                                  if (verbose)
346                                          say("Warning: this file doesn't appear "
# Line 282 | Line 370 | static void
370   plan_b(const char *filename)
371   {
372          FILE    *ifp;
373 <        size_t  i = 0, j, len, maxlen = 1;
374 <        char    *lbuf = NULL, *p;
373 >        size_t  i = 0, j, maxlen = 1;
374 >        char    *p;
375          bool    found_revision = (revision == NULL);
376  
377          using_plan_a = false;
# Line 292 | Line 380 | plan_b(const char *filename)
380          unlink(TMPINNAME);
381          if ((tifd = open(TMPINNAME, O_EXCL | O_CREAT | O_WRONLY, 0666)) < 0)
382                  pfatal("can't open file %s", TMPINNAME);
383 <        while ((p = fgetln(ifp, &len)) != NULL) {
384 <                if (p[len - 1] == '\n')
297 <                        p[len - 1] = '\0';
298 <                else {
299 <                        /* EOF without EOL, copy and add the NUL */
300 <                        if ((lbuf = malloc(len + 1)) == NULL)
301 <                                fatal("out of memory\n");
302 <                        memcpy(lbuf, p, len);
303 <                        lbuf[len] = '\0';
304 <                        p = lbuf;
305 <
306 <                        last_line_missing_eol = true;
307 <                        len++;
308 <                }
309 <                if (revision != NULL && !found_revision && rev_in_string(p))
383 >        while (fgets(buf, buf_size, ifp) != NULL) {
384 >                if (revision != NULL && !found_revision && rev_in_string(buf))
385                          found_revision = true;
386 <                if (len > maxlen)
387 <                        maxlen = len;   /* find longest line */
386 >                if ((i = strlen(buf)) > maxlen)
387 >                        maxlen = i;     /* find longest line */
388          }
389 <        free(lbuf);
390 <        if (ferror(ifp))
391 <                pfatal("can't read file %s", filename);
389 >        last_line_missing_eol = i > 0 && buf[i - 1] != '\n';
390 >        if (last_line_missing_eol && maxlen == i)
391 >                maxlen++;
392  
393          if (revision != NULL) {
394                  if (!found_revision) {
# Line 338 | Line 413 | plan_b(const char *filename)
413                              revision);
414          }
415          fseek(ifp, 0L, SEEK_SET);       /* rewind file */
416 +        lines_per_buf = BUFFERSIZE / maxlen;
417          tireclen = maxlen;
418 <        tibuflen = maxlen > BUFFERSIZE ? maxlen : BUFFERSIZE;
343 <        lines_per_buf = tibuflen / maxlen;
344 <        tibuf[0] = malloc(tibuflen + 1);
418 >        tibuf[0] = malloc(BUFFERSIZE + 1);
419          if (tibuf[0] == NULL)
420                  fatal("out of memory\n");
421 <        tibuf[1] = malloc(tibuflen + 1);
421 >        tibuf[1] = malloc(BUFFERSIZE + 1);
422          if (tibuf[1] == NULL)
423                  fatal("out of memory\n");
424          for (i = 1;; i++) {
425                  p = tibuf[0] + maxlen * (i % lines_per_buf);
426                  if (i % lines_per_buf == 0)     /* new block */
427 <                        if (write(tifd, tibuf[0], tibuflen) !=
354 <                            (ssize_t) tibuflen)
427 >                        if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
428                                  pfatal("can't write temp file");
429                  if (fgets(p, maxlen + 1, ifp) == NULL) {
430                          input_lines = i - 1;
431                          if (i % lines_per_buf != 0)
432 <                                if (write(tifd, tibuf[0], tibuflen) !=
360 <                                    (ssize_t) tibuflen)
432 >                                if (write(tifd, tibuf[0], BUFFERSIZE) < BUFFERSIZE)
433                                          pfatal("can't write temp file");
434                          break;
435                  }
# Line 399 | Line 471 | ifetch(LINENUM line, int whichbuf)
471                          tiline[whichbuf] = baseline;
472  
473                          if (lseek(tifd, (off_t) (baseline / lines_per_buf *
474 <                            tibuflen), SEEK_SET) < 0)
474 >                            BUFFERSIZE), SEEK_SET) < 0)
475                                  pfatal("cannot seek in the temporary input file");
476  
477 <                        if (read(tifd, tibuf[whichbuf], tibuflen) !=
406 <                            (ssize_t) tibuflen)
477 >                        if (read(tifd, tibuf[whichbuf], BUFFERSIZE) < 0)
478                                  pfatal("error reading tmp file %s", TMPINNAME);
479                  }
480                  return tibuf[whichbuf] + (tireclen * offline);

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines