VirtualBox

source: kBuild/trunk/src/kmk/output.c@ 3260

Last change on this file since 3260 was 3260, checked in by bird, 6 years ago

kmk/output.c: Don't log working directory for each and every recipe that's executed when in KMK mode - it drives me nuts.

  • Property svn:eol-style set to native
File size: 34.5 KB
Line 
1/* Output to stdout / stderr for GNU make
2Copyright (C) 2013-2016 Free Software Foundation, Inc.
3This file is part of GNU Make.
4
5GNU Make is free software; you can redistribute it and/or modify it under the
6terms of the GNU General Public License as published by the Free Software
7Foundation; either version 3 of the License, or (at your option) any later
8version.
9
10GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program. If not, see <http://www.gnu.org/licenses/>. */
16
17#include "makeint.h"
18#include "job.h"
19
20/* GNU make no longer supports pre-ANSI89 environments. */
21
22#include <assert.h>
23#include <stdio.h>
24#include <stdarg.h>
25
26#ifdef HAVE_UNISTD_H
27# include <unistd.h>
28#endif
29
30#ifdef HAVE_FCNTL_H
31# include <fcntl.h>
32#else
33# include <sys/file.h>
34#endif
35
36#ifdef WINDOWS32
37# include <windows.h>
38# include <io.h>
39# ifndef CONFIG_NEW_WIN_CHILDREN
40# include "sub_proc.h"
41# else
42# include "w32/winchildren.h"
43# endif
44#endif /* WINDOWS32 */
45#ifdef KBUILD_OS_WINDOWS
46# include "console.h"
47#endif
48
49struct output *output_context = NULL;
50unsigned int stdio_traced = 0;
51
52#define OUTPUT_NONE (-1)
53
54#define OUTPUT_ISSET(_out) ((_out)->out >= 0 || (_out)->err >= 0)
55
56#ifdef HAVE_FCNTL_H
57# define STREAM_OK(_s) ((fcntl (fileno (_s), F_GETFD) != -1) || (errno != EBADF))
58#else
59# define STREAM_OK(_s) 1
60#endif
61
62
63#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
64# define MEMBUF_MIN_SEG_SIZE 4096
65# define MEMBUF_MAX_SEG_SIZE (512*1024)
66# define MEMBUF_MAX_MOVE_LEN ( MEMBUF_MIN_SEG_SIZE \
67 - offsetof (struct output_segment, runs) \
68 - sizeof (struct output_run))
69# define MEMBUF_MAX_TOTAL ( sizeof (void *) <= 4 \
70 ? (size_t)512*1024 : (size_t)16*1024*1024 )
71
72static void *acquire_semaphore (void);
73static void release_semaphore (void *);
74static int log_working_directory (int);
75
76/* Is make's stdout going to the same place as stderr?
77 Also, did we already sync_init (== -1)? */
78static int combined_output = -1;
79
80/* Internal worker for output_dump and membuf_dump_most. */
81static void membuf_dump (struct output *out)
82{
83 if (out->out.total || out->err.total)
84 {
85 int traced = 0;
86 struct output_run *err_run;
87 struct output_run *out_run;
88 struct output_segment *seg;
89 FILE *prevdst;
90
91 /* Try to acquire the semaphore. If it fails, dump the output
92 unsynchronized; still better than silently discarding it.
93 We want to keep this lock for as little time as possible. */
94 void *sem = acquire_semaphore ();
95# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
96 int prev_mode_out = _setmode (fileno (stdout), _O_BINARY);
97 int prev_mode_err = _setmode (fileno (stderr), _O_BINARY);
98# endif
99
100# ifndef KMK /* this drives me bananas. */
101 /* Log the working directory for this dump. */
102 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
103 traced = log_working_directory (1);
104# endif
105
106 /* Work the out and err sequences in parallel. */
107 out_run = out->out.head_run;
108 err_run = out->err.head_run;
109 prevdst = NULL;
110 while (err_run || out_run)
111 {
112 FILE *dst;
113 const void *src;
114 size_t len;
115 if (out_run && (!err_run || out_run->seqno <= err_run->seqno))
116 {
117 src = out_run + 1;
118 len = out_run->len;
119 dst = stdout;
120 out_run = out_run->next;
121 }
122 else
123 {
124 src = err_run + 1;
125 len = err_run->len;
126 dst = stderr;
127 err_run = err_run->next;
128 }
129 if (dst != prevdst)
130 fflush(prevdst);
131 prevdst = dst;
132# if 0 /* for debugging */
133 while (len > 0)
134 {
135 const char *nl = (const char *)memchr (src, '\n', len);
136 size_t line_len = nl ? nl - (const char *)src + 1 : len;
137 char *tmp = (char *)xmalloc (1 + line_len + 1 + 1);
138 tmp[0] = '{';
139 memcpy (&tmp[1], src, line_len);
140 tmp[1 + line_len] = '}';
141# ifdef KBUILD_OS_WINDOWS
142 maybe_con_fwrite (tmp, 1 + line_len + 1, 1, dst);
143# else
144 fwrite (tmp, 1 + line_len + 1, 1, dst);
145# endif
146 free (tmp);
147 src = (const char *)src + line_len;
148 len -= line_len;
149 }
150#else
151# ifdef KBUILD_OS_WINDOWS
152 maybe_con_fwrite (src, len, 1, dst);
153# else
154 fwrite (src, len, 1, dst);
155# endif
156# endif
157 }
158 if (prevdst)
159 fflush (prevdst);
160
161# ifndef KMK /* this drives me bananas. */
162 if (traced)
163 log_working_directory (0);
164# endif
165
166 /* Exit the critical section. */
167# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
168 _setmode (fileno (stdout), prev_mode_out);
169 _setmode (fileno (stderr), prev_mode_err);
170# endif
171 if (sem)
172 release_semaphore (sem);
173
174 /* Free the segments and reset the state. */
175 while ((seg = out->out.head_seg))
176 {
177 out->out.head_seg = seg->next;
178 free (seg);
179 }
180 out->out.tail_seg = NULL;
181 out->out.tail_run = NULL;
182 out->out.head_run = NULL;
183 out->out.left = 0;
184 out->out.total = 0;
185
186 while ((seg = out->err.head_seg))
187 {
188 out->err.head_seg = seg->next;
189 free (seg);
190 }
191 out->err.tail_seg = NULL;
192 out->err.tail_run = NULL;
193 out->err.head_run = NULL;
194 out->err.left = 0;
195 out->err.total = 0;
196
197 out->seqno = 0;
198 }
199 else
200 assert (out->out.head_seg == NULL && out->err.head_seg == NULL);
201}
202
203/* Writes up to LEN bytes to the given segment.
204 Returns how much was actually written. */
205static size_t
206membuf_write_segment (struct output_membuf *membuf, struct output_segment *seg,
207 const char *src, size_t len, unsigned int *pseqno)
208{
209 size_t written = 0;
210 if (seg && membuf->left > 0)
211 {
212 struct output_run *run = membuf->tail_run;
213 char *dst = (char *)(run + 1) + run->len;
214 assert ((uintptr_t)run - (uintptr_t)seg < seg->size);
215
216 /* If the sequence number didn't change, then we can append
217 to the current run without further considerations. */
218 if (run->seqno == *pseqno)
219 written = len;
220 /* If the current run does not end with a newline, don't start a new
221 run till we encounter one. */
222 else if (dst[-1] != '\n')
223 {
224 char const *srcnl = (const char *)memchr (src, '\n', len);
225 written = srcnl ? srcnl - src + 1 : len;
226 }
227 /* Try create a new empty run and append to it. */
228 else
229 {
230 size_t const offnextrun = ( (uintptr_t)dst - (uintptr_t)(seg)
231 + sizeof(void *) - 1)
232 & ~(sizeof(void *) - 1);
233 if (offnextrun > seg->size - sizeof (struct output_run) * 2)
234 return 0; /* need new segment */
235
236 run = run->next = (struct output_run *)((char *)seg + offnextrun);
237 run->next = NULL;
238 run->seqno = ++(*pseqno);
239 run->len = 0;
240 membuf->tail_run = run;
241 membuf->left = seg->size - (offnextrun + sizeof (*run));
242 dst = (char *)(run + 1);
243 written = len;
244 }
245
246 /* Append to the current run. */
247 if (written > membuf->left)
248 written = membuf->left;
249 memcpy (dst, src, written);
250 run->len += written;
251 membuf->left -= written;
252 }
253 return written;
254}
255
256/* Helper for membuf_write_new_segment and membuf_dump_most that figures out
257 now much data needs to be moved from the previous run in order to make it
258 end with a newline. */
259static size_t membuf_calc_move_len (struct output_run *tail_run)
260{
261 size_t to_move = 0;
262 if (tail_run)
263 {
264 const char *data = (const char *)(tail_run + 1);
265 size_t off = tail_run->len;
266 while (off > 0 && data[off - 1] != '\n')
267 off--;
268 to_move = tail_run->len - off;
269 if (to_move >= MEMBUF_MAX_MOVE_LEN)
270 to_move = 0;
271 }
272 return to_move;
273}
274
275/* Allocates a new segment and writes to it.
276 This will take care to make sure the previous run terminates with
277 a newline so that we pass whole lines to fwrite when dumping. */
278static size_t
279membuf_write_new_segment (struct output_membuf *membuf, const char *src,
280 size_t len, unsigned int *pseqno)
281{
282 struct output_run *prev_run = membuf->tail_run;
283 struct output_segment *prev_seg = membuf->tail_seg;
284 size_t const to_move = membuf_calc_move_len (prev_run);
285 struct output_segment *new_seg;
286 size_t written;
287 char *dst;
288
289 /* Figure the the segment size. We start with MEMBUF_MIN_SEG_SIZE and double
290 it each time till we reach MEMBUF_MAX_SEG_SIZE. */
291 size_t const offset_runs = offsetof (struct output_segment, runs);
292 size_t segsize = !prev_seg ? MEMBUF_MIN_SEG_SIZE
293 : prev_seg->size >= MEMBUF_MAX_SEG_SIZE ? MEMBUF_MAX_SEG_SIZE
294 : prev_seg->size * 2;
295 while ( segsize < to_move + len + offset_runs + sizeof (struct output_run) * 2
296 && segsize < MEMBUF_MAX_SEG_SIZE)
297 segsize *= 2;
298
299 /* Allocate the segment and link it and the first run. */
300 new_seg = (struct output_segment *)xmalloc (segsize);
301 new_seg->size = segsize;
302 new_seg->next = NULL;
303 new_seg->runs[0].next = NULL;
304 if (!prev_seg)
305 {
306 membuf->head_seg = new_seg;
307 membuf->head_run = &new_seg->runs[0];
308 }
309 else
310 {
311 prev_seg->next = new_seg;
312 prev_run->next = &new_seg->runs[0];
313 }
314 membuf->tail_seg = new_seg;
315 membuf->tail_run = &new_seg->runs[0];
316 membuf->total += segsize;
317 membuf->left = segsize - sizeof (struct output_run) - offset_runs;
318
319 /* Initialize and write data to the first run. */
320 dst = (char *)&new_seg->runs[0]; /* Try bypass gcc array size cleverness. */
321 dst += sizeof (struct output_run);
322 assert (MEMBUF_MAX_MOVE_LEN < MEMBUF_MIN_SEG_SIZE);
323 if (to_move > 0)
324 {
325 /* Move to_move bytes from the previous run in hope that we'll get a
326 newline to soon. Afterwards call membuf_segment_write to work SRC. */
327 assert (prev_run != NULL);
328 assert (membuf->left >= to_move);
329 prev_run->len -= to_move;
330 new_seg->runs[0].len = to_move;
331 new_seg->runs[0].seqno = prev_run->seqno;
332 memcpy (dst, (const char *)(prev_run + 1) + prev_run->len, to_move);
333 membuf->left -= to_move;
334
335 written = membuf_write_segment (membuf, new_seg, src, len, pseqno);
336 }
337 else
338 {
339 /* Create a run with up to LEN from SRC. */
340 written = len;
341 if (written > membuf->left)
342 written = membuf->left;
343 new_seg->runs[0].len = written;
344 new_seg->runs[0].seqno = ++(*pseqno);
345 memcpy (dst, src, written);
346 membuf->left -= written;
347 }
348 return written;
349}
350
351/* Worker for output_write that will dump most of the output when we hit
352 MEMBUF_MAX_TOTAL on either of the two membuf structures, then free all the
353 output segments. Incomplete lines will be held over to the next buffers
354 and copied into new segments. */
355static void
356membuf_dump_most (struct output *out)
357{
358 size_t out_to_move = membuf_calc_move_len (out->out.tail_run);
359 size_t err_to_move = membuf_calc_move_len (out->err.tail_run);
360 if (!out_to_move && !err_to_move)
361 membuf_dump (out);
362 else
363 {
364 /* Allocate a stack buffer for holding incomplete lines. This should be
365 fine since we're only talking about max 2 * MEMBUF_MAX_MOVE_LEN.
366 The -1 on the sequence numbers, ise because membuf_write_new_segment
367 will increment them before use. */
368 unsigned int out_seqno = out_to_move ? out->out.tail_run->seqno - 1 : 0;
369 unsigned int err_seqno = err_to_move ? out->err.tail_run->seqno - 1 : 0;
370 char *tmp = alloca (out_to_move + err_to_move);
371 if (out_to_move)
372 {
373 out->out.tail_run->len -= out_to_move;
374 memcpy (tmp,
375 (char *)(out->out.tail_run + 1) + out->out.tail_run->len,
376 out_to_move);
377 }
378 if (err_to_move)
379 {
380 out->err.tail_run->len -= err_to_move;
381 memcpy (tmp + out_to_move,
382 (char *)(out->err.tail_run + 1) + out->err.tail_run->len,
383 err_to_move);
384 }
385
386 membuf_dump (out);
387
388 if (out_to_move)
389 {
390 size_t written = membuf_write_new_segment (&out->out, tmp,
391 out_to_move, &out_seqno);
392 assert (written == out_to_move); (void)written;
393 }
394 if (err_to_move)
395 {
396 size_t written = membuf_write_new_segment (&out->err,
397 tmp + out_to_move,
398 err_to_move, &err_seqno);
399 assert (written == err_to_move); (void)written;
400 }
401 }
402}
403
404
405
406/* write/fwrite like function, binary mode. */
407ssize_t
408output_write_bin (struct output *out, int is_err, const char *src, size_t len)
409{
410 size_t ret = len;
411 if (!out || !out->syncout)
412 {
413 FILE *f = is_err ? stderr : stdout;
414# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
415 /* On DOS platforms we need to disable \n -> \r\n converts that is common on
416 standard output/error. Also optimize for console output. */
417 int saved_errno;
418 int fd = fileno (f);
419 int prev_mode = _setmode (fd, _O_BINARY);
420 maybe_con_fwrite (src, len, 1, f);
421 if (fflush (f) == EOF)
422 ret = -1;
423 saved_errno = errno;
424 _setmode (fd, prev_mode);
425 errno = saved_errno;
426# else
427 fwrite (src, len, 1, f);
428 if (fflush (f) == EOF)
429 ret = -1;
430# endif
431 }
432 else
433 {
434 struct output_membuf *membuf = is_err ? &out->err : &out->out;
435 while (len > 0)
436 {
437 size_t runlen = membuf_write_segment (membuf, membuf->tail_seg, src, len, &out->seqno);
438 if (!runlen)
439 {
440 if (membuf->total < MEMBUF_MAX_TOTAL)
441 runlen = membuf_write_new_segment (membuf, src, len, &out->seqno);
442 else
443 membuf_dump_most (out);
444 }
445 /* advance */
446 len -= runlen;
447 src += runlen;
448 }
449 }
450 return ret;
451}
452
453#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
454
455/* write/fwrite like function, text mode. */
456ssize_t
457output_write_text (struct output *out, int is_err, const char *src, size_t len)
458{
459#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
460# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
461 ssize_t ret = len;
462 if (!out || !out->syncout)
463 {
464 /* ASSUME fwrite does the desired conversion. */
465 FILE *f = is_err ? stderr : stdout;
466# ifdef KBUILD_OS_WINDOWS
467 if (maybe_con_fwrite (src, len, 1, f) < 0)
468 ret = -1;
469# else
470 fwrite (src, len, 1, f);
471# endif
472 if (fflush (f) == EOF)
473 ret = -1;
474 }
475 else
476 {
477 /* Work the buffer line by line, replacing each \n with \r\n. */
478 while (len > 0)
479 {
480 const char *nl = memchr ( src, '\n', len);
481 size_t line_len = nl ? nl - src : len;
482 output_write_bin (out, is_err, src, line_len);
483 if (!nl)
484 break;
485 output_write_bin (out, is_err, "\r\n", 2);
486 len -= line_len + 1;
487 src += line_len + 1;
488 }
489 }
490 return ret;
491# else
492 return output_write_bin (out, is_err, src, len);
493# endif
494#else
495 ssize_t ret = len;
496 if (! out || ! out->syncout)
497 {
498 FILE *f = is_err ? stderr : stdout;
499# ifdef KBUILD_OS_WINDOWS
500 maybe_con_fwrite(src, len, 1, f);
501# else
502 fwrite (src, len, 1, f);
503# endif
504 fflush (f);
505 }
506 else
507 {
508 int fd = is_err ? out->err : out->out;
509 int r;
510
511 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
512 while (1)
513 {
514 EINTRLOOP (r, write (fd, src, len));
515 if ((size_t)r == len || r <= 0)
516 break;
517 len -= r;
518 src += r;
519 }
520 }
521 return ret;
522#endif
523}
524
525
526
527/* Write a string to the current STDOUT or STDERR. */
528static void
529_outputs (struct output *out, int is_err, const char *msg)
530{
531#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
532 output_write_text (out, is_err, msg, strlen (msg));
533#else /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
534 if (! out || ! out->syncout)
535 {
536 FILE *f = is_err ? stderr : stdout;
537# ifdef KBUILD_OS_WINDOWS
538 maybe_con_fwrite(msg, strlen(msg), 1, f);
539# else
540 fputs (msg, f);
541# endif
542 fflush (f);
543 }
544 else
545 {
546 int fd = is_err ? out->err : out->out;
547 int len = strlen (msg);
548 int r;
549
550 EINTRLOOP (r, lseek (fd, 0, SEEK_END));
551 while (1)
552 {
553 EINTRLOOP (r, write (fd, msg, len));
554 if (r == len || r <= 0)
555 break;
556 len -= r;
557 msg += r;
558 }
559 }
560#endif /* !CONFIG_WITH_OUTPUT_IN_MEMORY */
561}
562
563
564/* Write a message indicating that we've just entered or
565 left (according to ENTERING) the current directory. */
566
567static int
568log_working_directory (int entering)
569{
570 static char *buf = NULL;
571 static unsigned int len = 0;
572 unsigned int need;
573 const char *fmt;
574 char *p;
575
576 /* Get enough space for the longest possible output. */
577 need = strlen (program) + INTSTR_LENGTH + 2 + 1;
578 if (starting_directory)
579 need += strlen (starting_directory);
580
581 /* Use entire sentences to give the translators a fighting chance. */
582 if (makelevel == 0)
583 if (starting_directory == 0)
584 if (entering)
585 fmt = _("%s: Entering an unknown directory\n");
586 else
587 fmt = _("%s: Leaving an unknown directory\n");
588 else
589 if (entering)
590 fmt = _("%s: Entering directory '%s'\n");
591 else
592 fmt = _("%s: Leaving directory '%s'\n");
593 else
594 if (starting_directory == 0)
595 if (entering)
596 fmt = _("%s[%u]: Entering an unknown directory\n");
597 else
598 fmt = _("%s[%u]: Leaving an unknown directory\n");
599 else
600 if (entering)
601 fmt = _("%s[%u]: Entering directory '%s'\n");
602 else
603 fmt = _("%s[%u]: Leaving directory '%s'\n");
604
605 need += strlen (fmt);
606
607 if (need > len)
608 {
609 buf = xrealloc (buf, need);
610 len = need;
611 }
612
613 p = buf;
614 if (print_data_base_flag)
615 {
616 *(p++) = '#';
617 *(p++) = ' ';
618 }
619
620 if (makelevel == 0)
621 if (starting_directory == 0)
622 sprintf (p, fmt , program);
623 else
624 sprintf (p, fmt, program, starting_directory);
625 else if (starting_directory == 0)
626 sprintf (p, fmt, program, makelevel);
627 else
628 sprintf (p, fmt, program, makelevel, starting_directory);
629
630 _outputs (NULL, 0, buf);
631
632 return 1;
633}
634
635/* Set a file descriptor to be in O_APPEND mode.
636 If it fails, just ignore it. */
637
638static void
639set_append_mode (int fd)
640{
641#if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND)
642 int flags = fcntl (fd, F_GETFL, 0);
643 if (flags >= 0)
644 fcntl (fd, F_SETFL, flags | O_APPEND);
645#endif
646}
647
648
649
650#ifndef NO_OUTPUT_SYNC
651
652/* Semaphore for use in -j mode with output_sync. */
653static sync_handle_t sync_handle = -1;
654
655#define FD_NOT_EMPTY(_f) ((_f) != OUTPUT_NONE && lseek ((_f), 0, SEEK_END) > 0)
656
657/* Set up the sync handle. Disables output_sync on error. */
658static int
659sync_init (void)
660{
661 int combined_output = 0;
662
663#ifdef WINDOWS32
664# ifdef CONFIG_NEW_WIN_CHILDREN
665 if (STREAM_OK (stdout))
666 {
667 if (STREAM_OK (stderr))
668 {
669 char mtxname[256];
670 sync_handle = create_mutex (mtxname, sizeof (mtxname));
671 if (sync_handle != -1)
672 {
673 prepare_mutex_handle_string (mtxname);
674 return same_stream (stdout, stderr);
675 }
676 perror_with_name ("output-sync suppressed: ", "create_mutex");
677 }
678 else
679 perror_with_name ("output-sync suppressed: ", "stderr");
680 }
681 else
682 perror_with_name ("output-sync suppressed: ", "stdout");
683 output_sync = OUTPUT_SYNC_NONE;
684
685# else /* !CONFIG_NEW_WIN_CHILDREN */
686 if ((!STREAM_OK (stdout) && !STREAM_OK (stderr))
687 || (sync_handle = create_mutex ()) == -1)
688 {
689 perror_with_name ("output-sync suppressed: ", "stderr");
690 output_sync = 0;
691 }
692 else
693 {
694 combined_output = same_stream (stdout, stderr);
695 prepare_mutex_handle_string (sync_handle);
696 }
697# endif /* !CONFIG_NEW_WIN_CHILDREN */
698
699#else
700 if (STREAM_OK (stdout))
701 {
702 struct stat stbuf_o, stbuf_e;
703
704 sync_handle = fileno (stdout);
705 combined_output = (fstat (fileno (stdout), &stbuf_o) == 0
706 && fstat (fileno (stderr), &stbuf_e) == 0
707 && stbuf_o.st_dev == stbuf_e.st_dev
708 && stbuf_o.st_ino == stbuf_e.st_ino);
709 }
710 else if (STREAM_OK (stderr))
711 sync_handle = fileno (stderr);
712 else
713 {
714 perror_with_name ("output-sync suppressed: ", "stderr");
715 output_sync = 0;
716 }
717#endif
718
719 return combined_output;
720}
721
722#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
723/* Support routine for output_sync() */
724static void
725pump_from_tmp (int from, FILE *to)
726{
727# ifdef KMK
728 char buffer[8192];
729# else
730 static char buffer[8192];
731#endif
732
733# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
734 int prev_mode;
735
736 /* "from" is opened by open_tmpfd, which does it in binary mode, so
737 we need the mode of "to" to match that. */
738 prev_mode = _setmode (fileno (to), _O_BINARY);
739#endif
740
741 if (lseek (from, 0, SEEK_SET) == -1)
742 perror ("lseek()");
743
744 while (1)
745 {
746 int len;
747 EINTRLOOP (len, read (from, buffer, sizeof (buffer)));
748 if (len < 0)
749 perror ("read()");
750 if (len <= 0)
751 break;
752 if (fwrite (buffer, len, 1, to) < 1)
753 {
754 perror ("fwrite()");
755 break;
756 }
757 fflush (to);
758 }
759
760# if defined (KBUILD_OS_WINDOWS) || defined (KBUILD_OS_OS2) || defined (KBUILD_OS_DOS)
761 /* Switch "to" back to its original mode, so that log messages by
762 Make have the same EOL format as without --output-sync. */
763 _setmode (fileno (to), prev_mode);
764#endif
765}
766#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
767
768/* Obtain the lock for writing output. */
769static void *
770acquire_semaphore (void)
771{
772 static struct flock fl;
773
774 fl.l_type = F_WRLCK;
775 fl.l_whence = SEEK_SET;
776 fl.l_start = 0;
777 fl.l_len = 1;
778 if (fcntl (sync_handle, F_SETLKW, &fl) != -1)
779 return &fl;
780 perror ("fcntl()");
781 return NULL;
782}
783
784/* Release the lock for writing output. */
785static void
786release_semaphore (void *sem)
787{
788 struct flock *flp = (struct flock *)sem;
789 flp->l_type = F_UNLCK;
790 if (fcntl (sync_handle, F_SETLKW, flp) == -1)
791 perror ("fcntl()");
792}
793
794#ifndef CONFIG_WITH_OUTPUT_IN_MEMORY
795
796/* Returns a file descriptor to a temporary file. The file is automatically
797 closed/deleted on exit. Don't use a FILE* stream. */
798int
799output_tmpfd (void)
800{
801 int fd = -1;
802 FILE *tfile = tmpfile ();
803
804 if (! tfile)
805 pfatal_with_name ("tmpfile");
806
807 /* Create a duplicate so we can close the stream. */
808 fd = dup (fileno (tfile));
809 if (fd < 0)
810 pfatal_with_name ("dup");
811
812 fclose (tfile);
813
814 set_append_mode (fd);
815
816 return fd;
817}
818
819/* Adds file descriptors to the child structure to support output_sync; one
820 for stdout and one for stderr as long as they are open. If stdout and
821 stderr share a device they can share a temp file too.
822 Will reset output_sync on error. */
823static void
824setup_tmpfile (struct output *out)
825{
826 /* Is make's stdout going to the same place as stderr? */
827 static int combined_output = -1;
828
829 if (combined_output < 0)
830 combined_output = sync_init ();
831
832 if (STREAM_OK (stdout))
833 {
834 int fd = output_tmpfd ();
835 if (fd < 0)
836 goto error;
837 CLOSE_ON_EXEC (fd);
838 out->out = fd;
839 }
840
841 if (STREAM_OK (stderr))
842 {
843 if (out->out != OUTPUT_NONE && combined_output)
844 out->err = out->out;
845 else
846 {
847 int fd = output_tmpfd ();
848 if (fd < 0)
849 goto error;
850 CLOSE_ON_EXEC (fd);
851 out->err = fd;
852 }
853 }
854
855 return;
856
857 /* If we failed to create a temp file, disable output sync going forward. */
858 error:
859 output_close (out);
860 output_sync = OUTPUT_SYNC_NONE;
861}
862
863#endif /* CONFIG_WITH_OUTPUT_IN_MEMORY */
864
865/* Synchronize the output of jobs in -j mode to keep the results of
866 each job together. This is done by holding the results in temp files,
867 one for stdout and potentially another for stderr, and only releasing
868 them to "real" stdout/stderr when a semaphore can be obtained. */
869
870void
871output_dump (struct output *out)
872{
873#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
874 membuf_dump (out);
875#else
876 int outfd_not_empty = FD_NOT_EMPTY (out->out);
877 int errfd_not_empty = FD_NOT_EMPTY (out->err);
878
879 if (outfd_not_empty || errfd_not_empty)
880 {
881 int traced = 0;
882
883 /* Try to acquire the semaphore. If it fails, dump the output
884 unsynchronized; still better than silently discarding it.
885 We want to keep this lock for as little time as possible. */
886 void *sem = acquire_semaphore ();
887
888# ifndef KMK /* this drives me bananas. */
889 /* Log the working directory for this dump. */
890 if (print_directory_flag && output_sync != OUTPUT_SYNC_RECURSE)
891 traced = log_working_directory (1);
892# endif
893
894 if (outfd_not_empty)
895 pump_from_tmp (out->out, stdout);
896 if (errfd_not_empty && out->err != out->out)
897 pump_from_tmp (out->err, stderr);
898
899# ifndef KMK /* this drives me bananas. */
900 if (traced)
901 log_working_directory (0);
902# endif
903
904 /* Exit the critical section. */
905 if (sem)
906 release_semaphore (sem);
907
908 /* Truncate and reset the output, in case we use it again. */
909 if (out->out != OUTPUT_NONE)
910 {
911 int e;
912 lseek (out->out, 0, SEEK_SET);
913 EINTRLOOP (e, ftruncate (out->out, 0));
914 }
915 if (out->err != OUTPUT_NONE && out->err != out->out)
916 {
917 int e;
918 lseek (out->err, 0, SEEK_SET);
919 EINTRLOOP (e, ftruncate (out->err, 0));
920 }
921 }
922#endif
923}
924#endif /* NO_OUTPUT_SYNC */
925
926
927
928/* Provide support for temporary files. */
929
930#ifndef HAVE_STDLIB_H
931# ifdef HAVE_MKSTEMP
932int mkstemp (char *template);
933# else
934char *mktemp (char *template);
935# endif
936#endif
937
938FILE *
939output_tmpfile (char **name, const char *template)
940{
941#ifdef HAVE_FDOPEN
942 int fd;
943#endif
944
945#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
946# define TEMPLATE_LEN strlen (template)
947#else
948# define TEMPLATE_LEN L_tmpnam
949#endif
950 *name = xmalloc (TEMPLATE_LEN + 1);
951 strcpy (*name, template);
952
953#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
954 /* It's safest to use mkstemp(), if we can. */
955 fd = mkstemp (*name);
956 if (fd == -1)
957 return 0;
958 return fdopen (fd, "w");
959#else
960# ifdef HAVE_MKTEMP
961 (void) mktemp (*name);
962# else
963 (void) tmpnam (*name);
964# endif
965
966# ifdef HAVE_FDOPEN
967 /* Can't use mkstemp(), but guard against a race condition. */
968 EINTRLOOP (fd, open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600));
969 if (fd == -1)
970 return 0;
971 return fdopen (fd, "w");
972# else
973 /* Not secure, but what can we do? */
974 return fopen (*name, "w");
975# endif
976#endif
977}
978
979
980
981/* This code is stolen from gnulib.
982 If/when we abandon the requirement to work with K&R compilers, we can
983 remove this (and perhaps other parts of GNU make!) and migrate to using
984 gnulib directly.
985
986 This is called only through atexit(), which means die() has already been
987 invoked. So, call exit() here directly. Apparently that works...?
988*/
989
990/* Close standard output, exiting with status 'exit_failure' on failure.
991 If a program writes *anything* to stdout, that program should close
992 stdout and make sure that it succeeds before exiting. Otherwise,
993 suppose that you go to the extreme of checking the return status
994 of every function that does an explicit write to stdout. The last
995 printf can succeed in writing to the internal stream buffer, and yet
996 the fclose(stdout) could still fail (due e.g., to a disk full error)
997 when it tries to write out that buffered data. Thus, you would be
998 left with an incomplete output file and the offending program would
999 exit successfully. Even calling fflush is not always sufficient,
1000 since some file systems (NFS and CODA) buffer written/flushed data
1001 until an actual close call.
1002
1003 Besides, it's wasteful to check the return value from every call
1004 that writes to stdout -- just let the internal stream state record
1005 the failure. That's what the ferror test is checking below.
1006
1007 It's important to detect such failures and exit nonzero because many
1008 tools (most notably 'make' and other build-management systems) depend
1009 on being able to detect failure in other tools via their exit status. */
1010
1011static void
1012close_stdout (void)
1013{
1014 int prev_fail = ferror (stdout);
1015 int fclose_fail = fclose (stdout);
1016
1017 if (prev_fail || fclose_fail)
1018 {
1019 if (fclose_fail)
1020 perror_with_name (_("write error: stdout"), "");
1021 else
1022 O (error, NILF, _("write error: stdout"));
1023 exit (MAKE_TROUBLE);
1024 }
1025}
1026
1027
1028
1029void
1030output_init (struct output *out)
1031{
1032 if (out)
1033 {
1034#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1035 out->out.head_seg = NULL;
1036 out->out.tail_seg = NULL;
1037 out->out.head_run = NULL;
1038 out->out.tail_run = NULL;
1039 out->err.head_seg = NULL;
1040 out->err.tail_seg = NULL;
1041 out->err.head_run = NULL;
1042 out->err.tail_run = NULL;
1043 out->err.total = 0;
1044 out->out.total = 0;
1045 out->seqno = 0;
1046#else
1047 out->out = out->err = OUTPUT_NONE;
1048#endif
1049 out->syncout = !!output_sync;
1050 return;
1051 }
1052
1053 /* Configure this instance of make. Be sure stdout is line-buffered. */
1054
1055#ifdef HAVE_SETVBUF
1056# ifdef SETVBUF_REVERSED
1057 setvbuf (stdout, _IOLBF, xmalloc (BUFSIZ), BUFSIZ);
1058# else /* setvbuf not reversed. */
1059 /* Some buggy systems lose if we pass 0 instead of allocating ourselves. */
1060 setvbuf (stdout, 0, _IOLBF, BUFSIZ);
1061# endif /* setvbuf reversed. */
1062#elif HAVE_SETLINEBUF
1063 setlinebuf (stdout);
1064#endif /* setlinebuf missing. */
1065
1066 /* Force stdout/stderr into append mode. This ensures parallel jobs won't
1067 lose output due to overlapping writes. */
1068 set_append_mode (fileno (stdout));
1069 set_append_mode (fileno (stderr));
1070
1071#ifdef HAVE_ATEXIT
1072 if (STREAM_OK (stdout))
1073 atexit (close_stdout);
1074#endif
1075}
1076
1077void
1078output_close (struct output *out)
1079{
1080 if (! out)
1081 {
1082 if (stdio_traced)
1083 log_working_directory (0);
1084 return;
1085 }
1086
1087#ifndef NO_OUTPUT_SYNC
1088 output_dump (out);
1089#endif
1090
1091#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1092 assert (out->out.total == 0);
1093 assert (out->out.head_seg == NULL);
1094 assert (out->err.total == 0);
1095 assert (out->err.head_seg == NULL);
1096#else
1097 if (out->out >= 0)
1098 close (out->out);
1099 if (out->err >= 0 && out->err != out->out)
1100 close (out->err);
1101#endif
1102
1103 output_init (out);
1104}
1105
1106/* We're about to generate output: be sure it's set up. */
1107void
1108output_start (void)
1109{
1110#ifdef CONFIG_WITH_OUTPUT_IN_MEMORY
1111 /* If we're syncing output make sure the sempahore (win) is set up. */
1112 if (output_context && output_context->syncout)
1113 if (combined_output < 0)
1114 combined_output = sync_init ();
1115#else
1116#ifndef NO_OUTPUT_SYNC
1117 /* If we're syncing output make sure the temporary file is set up. */
1118 if (output_context && output_context->syncout)
1119 if (! OUTPUT_ISSET(output_context))
1120 setup_tmpfile (output_context);
1121#endif
1122#endif
1123
1124#ifndef KMK
1125 /* If we're not syncing this output per-line or per-target, make sure we emit
1126 the "Entering..." message where appropriate. */
1127 if (output_sync == OUTPUT_SYNC_NONE || output_sync == OUTPUT_SYNC_RECURSE)
1128#else
1129 /* Indiscriminately output "Entering..." and "Leaving..." message for each
1130 command line or target is plain annoying! And when there is no recursion
1131 it's actually inappropriate. Haven't got a simple way of detecting that,
1132 so back to the old behavior for now. [bird] */
1133#endif
1134 if (! stdio_traced && print_directory_flag)
1135 stdio_traced = log_working_directory (1);
1136}
1137
1138void
1139outputs (int is_err, const char *msg)
1140{
1141 if (! msg || *msg == '\0')
1142 return;
1143
1144 output_start ();
1145
1146 _outputs (output_context, is_err, msg);
1147}
1148
1149
1150
1151static struct fmtstring
1152 {
1153 char *buffer;
1154 size_t size;
1155 } fmtbuf = { NULL, 0 };
1156
1157static char *
1158get_buffer (size_t need)
1159{
1160 /* Make sure we have room. NEED includes space for \0. */
1161 if (need > fmtbuf.size)
1162 {
1163 fmtbuf.size += need * 2;
1164 fmtbuf.buffer = xrealloc (fmtbuf.buffer, fmtbuf.size);
1165 }
1166
1167 fmtbuf.buffer[need-1] = '\0';
1168
1169 return fmtbuf.buffer;
1170}
1171
1172/* Print a message on stdout. */
1173
1174void
1175message (int prefix, size_t len, const char *fmt, ...)
1176{
1177 va_list args;
1178 char *p;
1179
1180 len += strlen (fmt) + strlen (program) + INTSTR_LENGTH + 4 + 1 + 1;
1181 p = get_buffer (len);
1182
1183 if (prefix)
1184 {
1185 if (makelevel == 0)
1186 sprintf (p, "%s: ", program);
1187 else
1188 sprintf (p, "%s[%u]: ", program, makelevel);
1189 p += strlen (p);
1190 }
1191
1192 va_start (args, fmt);
1193 vsprintf (p, fmt, args);
1194 va_end (args);
1195
1196 strcat (p, "\n");
1197
1198 assert (fmtbuf.buffer[len-1] == '\0');
1199 outputs (0, fmtbuf.buffer);
1200}
1201
1202/* Print an error message. */
1203
1204void
1205error (const floc *flocp, size_t len, const char *fmt, ...)
1206{
1207 va_list args;
1208 char *p;
1209
1210 len += (strlen (fmt) + strlen (program)
1211 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1212 + INTSTR_LENGTH + 4 + 1 + 1);
1213 p = get_buffer (len);
1214
1215 if (flocp && flocp->filenm)
1216 sprintf (p, "%s:%lu: ", flocp->filenm, flocp->lineno + flocp->offset);
1217 else if (makelevel == 0)
1218 sprintf (p, "%s: ", program);
1219 else
1220 sprintf (p, "%s[%u]: ", program, makelevel);
1221 p += strlen (p);
1222
1223 va_start (args, fmt);
1224 vsprintf (p, fmt, args);
1225 va_end (args);
1226
1227 strcat (p, "\n");
1228
1229 assert (fmtbuf.buffer[len-1] == '\0');
1230 outputs (1, fmtbuf.buffer);
1231}
1232
1233/* Print an error message and exit. */
1234
1235void
1236fatal (const floc *flocp, size_t len, const char *fmt, ...)
1237{
1238 va_list args;
1239 const char *stop = _(". Stop.\n");
1240 char *p;
1241
1242 len += (strlen (fmt) + strlen (program)
1243 + (flocp && flocp->filenm ? strlen (flocp->filenm) : 0)
1244 + INTSTR_LENGTH + 8 + strlen (stop) + 1);
1245 p = get_buffer (len);
1246
1247 if (flocp && flocp->filenm)
1248 sprintf (p, "%s:%lu: *** ", flocp->filenm, flocp->lineno + flocp->offset);
1249 else if (makelevel == 0)
1250 sprintf (p, "%s: *** ", program);
1251 else
1252 sprintf (p, "%s[%u]: *** ", program, makelevel);
1253 p += strlen (p);
1254
1255 va_start (args, fmt);
1256 vsprintf (p, fmt, args);
1257 va_end (args);
1258
1259 strcat (p, stop);
1260
1261 assert (fmtbuf.buffer[len-1] == '\0');
1262 outputs (1, fmtbuf.buffer);
1263
1264 die (MAKE_FAILURE);
1265}
1266
1267/* Print an error message from errno. */
1268
1269void
1270perror_with_name (const char *str, const char *name)
1271{
1272 const char *err = strerror (errno);
1273 OSSS (error, NILF, _("%s%s: %s"), str, name, err);
1274}
1275
1276/* Print an error message from errno and exit. */
1277
1278void
1279pfatal_with_name (const char *name)
1280{
1281 const char *err = strerror (errno);
1282 OSS (fatal, NILF, _("%s: %s"), name, err);
1283
1284 /* NOTREACHED */
1285}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette