Exemple #1
0
static void
ngx_conf_flush_files(ngx_cycle_t *cycle)
{
    ssize_t           n, len;
    ngx_uint_t        i;
    ngx_list_part_t  *part;
    ngx_open_file_t  *file;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, cycle->log, 0, "flush files");

    part = &cycle->open_files.part;
    file = part->elts;

    for (i = 0; /* void */ ; i++) {

        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }
            part = part->next;
            file = part->elts;
            i = 0;
        }

        len = file[i].pos - file[i].buffer;

        if (file[i].buffer == NULL || len == 0) {
            continue;
        }

        n = ngx_write_fd(file[i].fd, file[i].buffer, len);

        if (n == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_write_fd_n " to \"%s\" failed",
                          file[i].name.data);

        } else if (n != len) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
                          file[i].name.data, n, len);
        }
    }
}
static void
ngx_rtmp_log_write(ngx_rtmp_session_t *s, ngx_rtmp_log_t *log, u_char *buf,
                   size_t len)
{
    u_char *name;
    time_t  now;
    ssize_t n;
    int     err;

    err = 0;
    name = log->file->name.data;
    n = ngx_write_fd(log->file->fd, buf, len);

    if (n == (ssize_t) len) {
        return;
    }

    now = ngx_time();

    if (n == -1) {
        err = ngx_errno;

        if (err == NGX_ENOSPC) {
            log->disk_full_time = now;
        }

        if (now - log->error_log_time > 59) {
            ngx_log_error(NGX_LOG_ALERT, s->connection->log, err,
                          ngx_write_fd_n " to \"%s\" failed", name);
            log->error_log_time = now;
        }
    }

    if (now - log->error_log_time > 59) {
        ngx_log_error(NGX_LOG_ALERT, s->connection->log, err,
                      ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
                      name, n, len);
        log->error_log_time = now;
    }
}
static void
ngx_http_groonga_write_fd(ngx_fd_t fd,
                          u_char *buffer, size_t buffer_size,
                          const char *message, size_t message_size)
{
  size_t rest_message_size = message_size;
  const char *current_message = message;

  while (rest_message_size > 0) {
    size_t current_message_size;

    if (rest_message_size > NGX_MAX_ERROR_STR) {
      current_message_size = NGX_MAX_ERROR_STR;
    } else {
      current_message_size = rest_message_size;
    }

    grn_memcpy(buffer, current_message, current_message_size);
    ngx_write_fd(fd, buffer, current_message_size);
    rest_message_size -= current_message_size;
    current_message += current_message_size;
  }
}
static void
ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level,
                            const char *timestamp, const char *title,
                            const char *message, const char *location,
                            void *user_data)
{
  ngx_http_groonga_logger_data_t *logger_data = user_data;
  const char level_marks[] = " EACewnid-";
  u_char buffer[NGX_MAX_ERROR_STR];
  u_char *last;

  if (location && *location) {
    last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
                        "%s|%c|%s %s %s\n",
                        timestamp, *(level_marks + level), title, message,
                        location);
  } else {
    last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
                        "%s|%c|%s %s\n",
                        timestamp, *(level_marks + level), title, message);
  }
  ngx_write_fd(logger_data->file->fd, buffer, last - buffer);
}
static ngx_int_t
ngx_rtmp_dash_write_init_segments(ngx_rtmp_session_t *s)
{
    ngx_fd_t               fd;
    ngx_int_t              rc;
    ngx_buf_t              b;
    ngx_rtmp_dash_ctx_t   *ctx;
    ngx_rtmp_codec_ctx_t  *codec_ctx;

    static u_char          buffer[NGX_RTMP_DASH_BUFSIZE];

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
    codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);

    if (ctx == NULL || codec_ctx == NULL) {
        return NGX_ERROR;
    }

    /* init video */

    *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4v") = 0;

    fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
                       NGX_FILE_DEFAULT_ACCESS);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: error creating video init file");
        return NGX_ERROR;
    }

    b.start = buffer;
    b.end = b.start + sizeof(buffer);
    b.pos = b.last = b.start;

    ngx_rtmp_mp4_write_ftyp(&b);
    ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_VIDEO_TRACK);

    rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start));
    if (rc == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: writing video init failed");
    }

    ngx_close_file(fd);

    /* init audio */

    *ngx_sprintf(ctx->stream.data + ctx->stream.len, "init.m4a") = 0;

    fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR, NGX_FILE_TRUNCATE,
                       NGX_FILE_DEFAULT_ACCESS);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: error creating dash audio init file");
        return NGX_ERROR;
    }

    b.pos = b.last = b.start;

    ngx_rtmp_mp4_write_ftyp(&b);
    ngx_rtmp_mp4_write_moov(s, &b, NGX_RTMP_MP4_AUDIO_TRACK);

    rc = ngx_write_fd(fd, b.start, (size_t) (b.last - b.start));
    if (rc == NGX_ERROR) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: writing audio init failed");
    }

    ngx_close_file(fd);

    return NGX_OK;
}
static ngx_int_t
ngx_rtmp_dash_write_playlist(ngx_rtmp_session_t *s)
{
    char                      *sep;
    u_char                    *p, *last;
    ssize_t                    n;
    ngx_fd_t                   fd;
    struct tm                  tm;
    ngx_str_t                  noname, *name;
    ngx_uint_t                 i, frame_rate_num, frame_rate_denom;
    ngx_rtmp_dash_ctx_t       *ctx;
    ngx_rtmp_codec_ctx_t      *codec_ctx;
    ngx_rtmp_dash_frag_t      *f;
    ngx_rtmp_dash_app_conf_t  *dacf;

    static u_char              buffer[NGX_RTMP_DASH_BUFSIZE];
    static u_char              start_time[sizeof("1970-09-28T12:00:00+06:00")];
    static u_char              end_time[sizeof("1970-09-28T12:00:00+06:00")];
    static u_char              frame_rate[(NGX_INT_T_LEN * 2) + 2];

    dacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_dash_module);
    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);
    codec_ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_codec_module);

    if (dacf == NULL || ctx == NULL || codec_ctx == NULL) {
        return NGX_ERROR;
    }

    if (ctx->id == 0) {
        ngx_rtmp_dash_write_init_segments(s);
    }

    fd = ngx_open_file(ctx->playlist_bak.data, NGX_FILE_WRONLY,
                       NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: open failed: '%V'", &ctx->playlist_bak);
        return NGX_ERROR;
    }


#define NGX_RTMP_DASH_MANIFEST_HEADER                                          \
    "<?xml version=\"1.0\"?>\n"                                                \
    "<MPD\n"                                                                   \
    "    type=\"dynamic\"\n"                                                   \
    "    xmlns=\"urn:mpeg:dash:schema:mpd:2011\"\n"                            \
    "    availabilityStartTime=\"%s\"\n"                                       \
    "    availabilityEndTime=\"%s\"\n"                                         \
    "    minimumUpdatePeriod=\"PT%uiS\"\n"                                     \
    "    minBufferTime=\"PT%uiS\"\n"                                           \
    "    timeShiftBufferDepth=\"PT0H0M0.00S\"\n"                               \
    "    suggestedPresentationDelay=\"PT%uiS\"\n"                              \
    "    profiles=\"urn:hbbtv:dash:profile:isoff-live:2012,"                   \
                   "urn:mpeg:dash:profile:isoff-live:2011\"\n"                 \
    "    xmlns:xsi=\"http://www.w3.org/2011/XMLSchema-instance\"\n"            \
    "    xsi:schemaLocation=\"urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd\">\n" \
    "  <Period start=\"PT0S\" id=\"dash\">\n"


#define NGX_RTMP_DASH_MANIFEST_VIDEO                                           \
    "    <AdaptationSet\n"                                                     \
    "        id=\"1\"\n"                                                       \
    "        segmentAlignment=\"true\"\n"                                      \
    "        maxWidth=\"%ui\"\n"                                               \
    "        maxHeight=\"%ui\"\n"                                              \
    "        maxFrameRate=\"%s\">\n"                                           \
    "      <Representation\n"                                                  \
    "          id=\"%V_H264\"\n"                                               \
    "          mimeType=\"video/mp4\"\n"                                       \
    "          codecs=\"avc1.%02uxi%02uxi%02uxi\"\n"                           \
    "          width=\"%ui\"\n"                                                \
    "          height=\"%ui\"\n"                                               \
    "          frameRate=\"%s\"\n"                                             \
    "          sar=\"1:1\"\n"                                                  \
    "          startWithSAP=\"1\"\n"                                           \
    "          bandwidth=\"%ui\">\n"                                           \
    "        <SegmentTemplate\n"                                               \
    "            presentationTimeOffset=\"0\"\n"                               \
    "            timescale=\"1000\"\n"                                         \
    "            media=\"%V%s$Time$.m4v\"\n"                                   \
    "            initialization=\"%V%sinit.m4v\">\n"                           \
    "          <SegmentTimeline>\n"


#define NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER                                    \
    "          </SegmentTimeline>\n"                                           \
    "        </SegmentTemplate>\n"                                             \
    "      </Representation>\n"                                                \
    "    </AdaptationSet>\n"


#define NGX_RTMP_DASH_MANIFEST_TIME                                            \
    "             <S t=\"%uD\" d=\"%uD\"/>\n"


#define NGX_RTMP_DASH_MANIFEST_AUDIO                                           \
    "    <AdaptationSet\n"                                                     \
    "        id=\"2\"\n"                                                       \
    "        segmentAlignment=\"true\">\n"                                     \
    "      <AudioChannelConfiguration\n"                                       \
    "          schemeIdUri=\"urn:mpeg:dash:"                                   \
                                "23003:3:audio_channel_configuration:2011\"\n" \
    "          value=\"1\"/>\n"                                                \
    "      <Representation\n"                                                  \
    "          id=\"%V_AAC\"\n"                                                \
    "          mimeType=\"audio/mp4\"\n"                                       \
    "          codecs=\"mp4a.%s\"\n"                                           \
    "          audioSamplingRate=\"%ui\"\n"                                    \
    "          startWithSAP=\"1\"\n"                                           \
    "          bandwidth=\"%ui\">\n"                                           \
    "        <SegmentTemplate\n"                                               \
    "            presentationTimeOffset=\"0\"\n"                               \
    "            timescale=\"1000\"\n"                                         \
    "            media=\"%V%s$Time$.m4a\"\n"                                   \
    "            initialization=\"%V%sinit.m4a\">\n"                           \
    "          <SegmentTimeline>\n"


#define NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER                                    \
    "          </SegmentTimeline>\n"                                           \
    "        </SegmentTemplate>\n"                                             \
    "      </Representation>\n"                                                \
    "    </AdaptationSet>\n"


#define NGX_RTMP_DASH_MANIFEST_FOOTER                                          \
    "  </Period>\n"                                                            \
    "</MPD>\n"

    ngx_libc_localtime(ctx->start_time.sec +
                       ngx_rtmp_dash_get_frag(s, 0)->timestamp / 1000, &tm);

    *ngx_sprintf(start_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
                 tm.tm_year + 1900, tm.tm_mon + 1,
                 tm.tm_mday, tm.tm_hour,
                 tm.tm_min, tm.tm_sec,
                 ctx->start_time.gmtoff < 0 ? '-' : '+',
                 ngx_abs(ctx->start_time.gmtoff / 60),
                 ngx_abs(ctx->start_time.gmtoff % 60)) = 0;

    ngx_libc_localtime(ctx->start_time.sec +
                       (ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->timestamp +
                        ngx_rtmp_dash_get_frag(s, ctx->nfrags - 1)->duration) /
                       1000, &tm);

    *ngx_sprintf(end_time, "%4d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d",
                 tm.tm_year + 1900, tm.tm_mon + 1,
                 tm.tm_mday, tm.tm_hour,
                 tm.tm_min, tm.tm_sec,
                 ctx->start_time.gmtoff < 0 ? '-' : '+',
                 ngx_abs(ctx->start_time.gmtoff / 60),
                 ngx_abs(ctx->start_time.gmtoff % 60)) = 0;

    last = buffer + sizeof(buffer);

    p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_HEADER,
                     start_time,
                     end_time,
                     (ngx_uint_t) (dacf->fraglen / 1000),
                     (ngx_uint_t) (dacf->fraglen / 1000),
                     (ngx_uint_t) (dacf->fraglen / 500));

    n = ngx_write_fd(fd, buffer, p - buffer);

    ngx_str_null(&noname);

    name = (dacf->nested ? &noname : &ctx->name);
    sep = (dacf->nested ? "" : "-");

    if (ctx->has_video) {
        frame_rate_num = (ngx_uint_t) (codec_ctx->frame_rate * 1000.);

        if (frame_rate_num % 1000 == 0) {
            *ngx_sprintf(frame_rate, "%ui", frame_rate_num / 1000) = 0;
        } else {
            frame_rate_denom = 1000;
            switch (frame_rate_num) {
                case 23976:
                    frame_rate_num = 24000;
                    frame_rate_denom = 1001;
                    break;
                case 29970:
                    frame_rate_num = 30000;
                    frame_rate_denom = 1001;
                    break;
                case 59940:
                    frame_rate_num = 60000;
                    frame_rate_denom = 1001;
                    break;
            }

            *ngx_sprintf(frame_rate, "%ui/%ui", frame_rate_num, frame_rate_denom) = 0;
        }

        p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_VIDEO,
                         codec_ctx->width,
                         codec_ctx->height,
                         frame_rate,
                         &ctx->name,
                         codec_ctx->avc_profile,
                         codec_ctx->avc_compat,
                         codec_ctx->avc_level,
                         codec_ctx->width,
                         codec_ctx->height,
                         frame_rate,
                         (ngx_uint_t) (codec_ctx->video_data_rate * 1000),
                         name, sep,
                         name, sep);

        for (i = 0; i < ctx->nfrags; i++) {
            f = ngx_rtmp_dash_get_frag(s, i);
            p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME,
                             f->timestamp, f->duration);
        }

        p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_VIDEO_FOOTER);

        n = ngx_write_fd(fd, buffer, p - buffer);
    }

    if (ctx->has_audio) {
        p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_AUDIO,
                         &ctx->name,
                         codec_ctx->audio_codec_id == NGX_RTMP_AUDIO_AAC ?
                         (codec_ctx->aac_sbr ? "40.5" : "40.2") : "6b",
                         codec_ctx->sample_rate,
                         (ngx_uint_t) (codec_ctx->audio_data_rate * 1000),
                         name, sep,
                         name, sep);

        for (i = 0; i < ctx->nfrags; i++) {
            f = ngx_rtmp_dash_get_frag(s, i);
            p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_TIME,
                             f->timestamp, f->duration);
        }

        p = ngx_slprintf(p, last, NGX_RTMP_DASH_MANIFEST_AUDIO_FOOTER);

        n = ngx_write_fd(fd, buffer, p - buffer);
    }

    p = ngx_slprintf(buffer, last, NGX_RTMP_DASH_MANIFEST_FOOTER);
    n = ngx_write_fd(fd, buffer, p - buffer);

    if (n < 0) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: write failed: '%V'", &ctx->playlist_bak);
        ngx_close_file(fd);
        return NGX_ERROR;
    }

    ngx_close_file(fd);

    if (ngx_rtmp_dash_rename_file(ctx->playlist_bak.data, ctx->playlist.data)
        == NGX_FILE_ERROR)
    {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: rename failed: '%V'->'%V'",
                      &ctx->playlist_bak, &ctx->playlist);
        return NGX_ERROR;
    }

    return NGX_OK;
}
Exemple #7
0
static void
ngx_pipe_log(ngx_cycle_t *cycle, ngx_open_pipe_t *op)
{
    ngx_int_t                   n_bytes_read;
    u_char                     *read_buf;
    size_t                      read_buf_len = 65536;
    ngx_fd_t                    log_fd = NGX_INVALID_FILE;
#ifdef T_PIPE_NO_DISPLAY
    size_t                      title_len;
#endif
    ngx_pipe_rollback_conf_t    rbcf;
    ngx_file_info_t             sb;
    size_t                      one_day = 24 * 60 * 60;

    ngx_pid = ngx_getpid();

    rbcf.last_open_time = 0;
    rbcf.last_suit_time = 0;
    rbcf.log_size = 0;

    if (ngx_pipe_rollback_parse_args(cycle, op, &rbcf) != NGX_OK) {
        ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "log rollback parse error");
        return;
    }

    read_buf = ngx_pcalloc(cycle->pool, read_buf_len);
    if (read_buf == NULL) {
        return;
    }

    //set title
    ngx_setproctitle((char *) op->cmd);
#ifdef T_PIPE_NO_DISPLAY
    title_len = ngx_strlen(ngx_os_argv[0]);
#if (NGX_SOLARIS)
#else
    ngx_memset((u_char *) ngx_os_argv[0], NGX_SETPROCTITLE_PAD, title_len);
    ngx_cpystrn((u_char *) ngx_os_argv[0], op->cmd, title_len);
#endif
#endif

    for (;;)
    {
        if (ngx_terminate == 1) {
            return;
        }

        n_bytes_read = ngx_read_fd(0, read_buf, read_buf_len);
        if (n_bytes_read == 0) {
            return;
        }
        if (errno == EINTR) {
            continue;

        } else if (n_bytes_read < 0) {
            return;
        }

        rbcf.time_now = ngx_pipe_get_now_sec();

        if (NULL != rbcf.suitpath) {
            if (rbcf.time_now / one_day >
                    rbcf.last_suit_time / one_day) {
                ngx_pipe_create_suitpath(cycle, &rbcf);
            }
        }

        if (log_fd >= 0) {
            if (rbcf.interval > 0) {
                if (((rbcf.time_now - rbcf.adjust_time) / rbcf.interval) >
                        (rbcf.last_open_time / rbcf.interval)) {
                    //need check rollback
                    ngx_close_file(log_fd);
                    log_fd = NGX_INVALID_FILE;
                    ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
                                  "need check rollback time [%s]", rbcf.logname);
                    ngx_pipe_do_rollback(cycle, &rbcf);
                }
            }
        }

        if (log_fd >= 0 && rbcf.log_max_size > 0 &&
                           rbcf.log_size >= rbcf.log_max_size) {
            ngx_close_file(log_fd);
            log_fd = NGX_INVALID_FILE;
            ngx_log_error(NGX_LOG_INFO, cycle->log, 0,
                          "need check rollback size [%s] [%d]",
                          rbcf.logname, rbcf.log_size);
            ngx_pipe_do_rollback(cycle, &rbcf);
        }

        /* If there is no log file open then open a new one.
         *   */
        if (log_fd < 0) {
            ngx_pipe_create_subdirs(rbcf.logname, cycle);
            if (rbcf.interval > 0 && rbcf.last_open_time == 0 
                    && ((rbcf.time_now - rbcf.adjust_time_raw) / rbcf.interval < rbcf.time_now / rbcf.interval)) { /*just check
                when time is after interval and befor adjust_time_raw, fix when no backup file, do rollback
                */
                //need check last rollback time, because other process may do rollback after when it adjust time more than this process
                ngx_pipe_get_last_rollback_time(&rbcf);
            } else {
                rbcf.last_open_time = ngx_pipe_get_now_sec();
            }

            log_fd = ngx_open_file(rbcf.logname, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN,
                          NGX_PIPE_FILE_ACCESS);
            if (log_fd < 0) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              "open [%s] failed", rbcf.logname);
                return;
            }

            if (0 == ngx_fd_info(log_fd, &sb)) {
                rbcf.log_size = sb.st_size;
            }
        }

        if (ngx_write_fd(log_fd, read_buf, n_bytes_read) != n_bytes_read) {
            if (errno != EINTR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              "write to [%s] failed", rbcf.logname);
                return;
            }
        }
        rbcf.log_size += n_bytes_read;
    }

}
Exemple #8
0
static ssize_t
ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
    u_char **name, u_char *buf, size_t len)
{
    size_t                     root;
    ssize_t                    n;
    ngx_str_t                  log, path;
    ngx_open_file_info_t       of;
    ngx_http_log_loc_conf_t   *llcf;
    ngx_http_core_loc_conf_t  *clcf;

    if (!r->root_tested) {

        /* test root directory existance */

        if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) {
            /* simulate successfull logging */
            return len;
        }

        path.data[root] = '\0';

        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

        ngx_memzero(&of, sizeof(ngx_open_file_info_t));

        of.valid = clcf->open_file_cache_valid;
        of.min_uses = clcf->open_file_cache_min_uses;
        of.test_dir = 1;
        of.test_only = 1;
        of.errors = clcf->open_file_cache_errors;
        of.events = clcf->open_file_cache_events;

        if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
            != NGX_OK)
        {
            if (of.err == 0) {
                /* simulate successfull logging */
                return len;
            }

            ngx_log_error(NGX_LOG_ERR, r->connection->log, of.err,
                          "testing \"%s\" existence failed", path.data);

            /* simulate successfull logging */
            return len;
        }

        if (!of.is_dir) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_ENOTDIR,
                          "testing \"%s\" existence failed", path.data);

            /* simulate successfull logging */
            return len;
        }
    }

    if (ngx_http_script_run(r, &log, script->lengths->elts, 1,
                            script->values->elts)
        == NULL)
    {
        /* simulate successfull logging */
        return len;
    }

    log.data[log.len - 1] = '\0';
    *name = log.data;

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log \"%s\"", log.data);

    llcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);

    ngx_memzero(&of, sizeof(ngx_open_file_info_t));

    of.log = 1;
    of.valid = llcf->open_file_cache_valid;
    of.min_uses = llcf->open_file_cache_min_uses;
    of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;

    if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
        != NGX_OK)
    {
        ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
                      "%s \"%s\" failed", of.failed, log.data);
        /* simulate successfull logging */
        return len;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http log #%d", of.fd);

    n = ngx_write_fd(of.fd, buf, len);

    return n;
}
static ngx_int_t
ngx_http_dav_copy_file(ngx_tree_ctx_t *ctx, u_char *from, u_char *to)
{
    off_t       size;
    ssize_t     n;
    ngx_fd_t    fd, cfd;
    ngx_int_t   rc;
    u_char      buf[NGX_HTTP_DAV_COPY_BLOCK];

    fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (fd == NGX_INVALID_FILE) {
        (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n,
                                  from);
        return NGX_ERROR;
    }

    cfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
                        ctx->access);

    rc = NGX_ERROR;

    if (cfd == NGX_INVALID_FILE) {
        (void) ngx_http_dav_error(ctx->log, ngx_errno, 0, ngx_open_file_n, to);
        goto failed;
    }

    for (size = ctx->size; size > 0; size -= n) {

        n = ngx_read_fd(fd, buf, NGX_HTTP_DAV_COPY_BLOCK);

        if (n == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                          ngx_read_fd_n " \"%s\" failed", from);
            goto failed;
        }

        if (ngx_write_fd(cfd, buf, n) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                          ngx_write_fd_n " \"%s\" failed", to);
            goto failed;
        }
    }

    if (ngx_set_file_time(to, cfd, ctx->mtime) != NGX_OK) {
        ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                      ngx_set_file_time_n " \"%s\" failed", to);
        goto failed;
    }

    if (ngx_close_file(cfd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", to);
        goto failed;
    }

    rc = NGX_OK;

failed:

    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, ctx->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", from);
    }

    return rc;
}
static void * xml_log_write(ngx_http_request_t *r) {

    char *ptr,*wptr;
    wptr=buf;

    r->server_name.data[r->server_name.len]=0;
    r->uri.data[r->uri.len]=0;

    wptr=ngx_sprintf(wptr,"<log time=\"%d\" ip=\"%d\" host=\"%s\" path=\"%s\">\n",ngx_time(),((struct sockaddr_in *) r->connection->sockaddr)->sin_addr.s_addr,r->server_name.data,r->uri.data);


    unsigned off=0;

    if(r->method == NGX_HTTP_POST) {

	if(r->request_body && r->request_body->buf && (len=r->request_body->buf->last - r->request_body->buf->start) && len > 0) {

	    pos.key=0;
	    pos.value=0;
	    ptr=r->request_body->buf->start;
            for(;len > 0;ptr++,len--) {
			if(pos.key == 0 && pos.value == 0) {
			    pos.key=1;
			    wptr=cpy(wptr,"\t<query method=\"POST\" name=\"");
			}
			
			if(pos.key ==1 && pos.value == 0) {
			    if(*ptr == '=') {
				wptr=cpy(wptr,"\" empty=\"0\"><![CDATA[");
				pos.key=0;
				pos.value=1;
			    } else if(*ptr == '&') {
				wptr=cpy(wptr,"\" empty=\"1\"/>\n");
				pos.key=pos.value=0;
			    } else {
				wptr[0]=*ptr;
				wptr++;
			    }
			} else if(pos.key ==0 && pos.value == 1) {
			    if(*ptr == '&') {
				wptr=cpy(wptr,"]]></query>\n");
				pos.key=pos.value=0;
			    } else {
				wptr[0]=*ptr;
				wptr++;
			    }
			}
            }
    
        if(pos.key == 1)  wptr=cpy(wptr,"\" empty=\"1\" />\n");
        else wptr=cpy(wptr,"]]></query>\n");

	}
    }

    if(r->args.len > 0) {
        pos.key=0;
	pos.value=0;
	ptr=r->args.data;
	len=r->args.len;
        for(;len > 0;ptr++,len--) {
		if(pos.key == 0 && pos.value == 0) {
		    pos.key=1;
		    wptr=cpy(wptr,"\t<query method=\"GET\" name=\"");
		}
		
		if(pos.key ==1 && pos.value == 0) {
		    if(*ptr == '=') {
			wptr=cpy(wptr,"\" empty=\"0\"><![CDATA[");
			pos.key=0;
			pos.value=1;
		    } else if(*ptr == '&') {
			wptr=cpy(wptr,"\" empty=\"1\"/>\n");
			pos.key=pos.value=0;
		    } else {
			wptr[0]=*ptr;
			wptr++;
		    }
		} else if(pos.key ==0 && pos.value == 1) {
		    if(*ptr == '&') {
			wptr=cpy(wptr,"]]></query>\n");
			pos.key=pos.value=0;
		    } else {
			wptr[0]=*ptr;
			wptr++;
		    }
		}
        }
        if(pos.key == 1)  wptr=cpy(wptr,"\" empty=\"1\" />\n");
        else wptr=cpy(wptr,"]]></query>\n");

    }

    wptr=cpy(wptr,"</log>\n");
    wptr[0]=0;
    len=(unsigned)(wptr-buf);
    ngx_write_fd(fd,buf,wptr-buf);

}
Exemple #11
0
int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }

    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        ngx_process = NGX_PROCESS_MASTER;
    }

#if !(NGX_WIN32)

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    if (log->file->fd != ngx_stderr) {
        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);

    } else {
        ngx_master_process_cycle(cycle);
    }

    return 0;
}
Exemple #12
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list  args;
#endif
    u_char   errstr[NGX_MAX_ERROR_STR], *p, *last;

    if (log->file->fd == NGX_INVALID_FILE) {
        return;
    }

    last = errstr + NGX_MAX_ERROR_STR;

    ngx_memcpy(errstr, ngx_cached_err_log_time.data,
               ngx_cached_err_log_time.len);

    p = errstr + ngx_cached_err_log_time.len;

    p = ngx_snprintf(p, last - p, " [%s] ", err_levels[level]);

    /* pid#tid */
    p = ngx_snprintf(p, last - p, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    if (log->connection) {
        p = ngx_snprintf(p, last - p, "*%uA ", log->connection);
    }

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vsnprintf(p, last - p, fmt, args);
    va_end(args);

#else

    p = ngx_vsnprintf(p, last - p, fmt, args);

#endif

    if (err) {

        if (p > last - 50) {

            /* leave a space for an error code */

            p = last - 50;
            *p++ = '.';
            *p++ = '.';
            *p++ = '.';
        }

#if (NGX_WIN32)

        if ((unsigned) err >= 0x80000000) {
            p = ngx_snprintf(p, last - p, " (%Xd: ", err);

        } else {
            p = ngx_snprintf(p, last - p, " (%d: ", err);
        }

#else

        p = ngx_snprintf(p, last - p, " (%d: ", err);

#endif

        p = ngx_strerror_r(err, p, last - p);

        if (p < last) {
            *p++ = ')';
        }
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    (void) ngx_write_fd(log->file->fd, errstr, p - errstr);
}
static ngx_buf_t *
ngx_http_pngquant_quantize(ngx_http_request_t *r, ngx_http_pngquant_ctx_t *ctx)
{
    u_char                    *out;
    ngx_buf_t                 *b;
    ngx_pool_cleanup_t        *cln;
    ngx_http_pngquant_conf_t  *conf;
    gdImagePtr                 img;
    int                        size;

    ngx_int_t                  rc;
    ngx_temp_file_t           *tf;
    ssize_t                    n;
    ngx_ext_rename_file_t      ext;
    ngx_str_t                  dest;
    ngx_str_t                  value;


    img = gdImageCreateFromPngPtr(ctx->length, ctx->image);

    if (img == NULL) {

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
            "gdImageCreateFromPngPtr() failed");

        return NULL;
    }

    conf = ngx_http_get_module_loc_conf(r, ngx_http_pngquant_module);

    /*
     * gdImageTrueColorToPaletteSetMethod(img, GD_QUANT_LIQ, conf->speed);
     * gdImageTrueColorToPalette(img, conf->dither, conf->colors);
     */

    ngx_pngquant_gd_image(img, conf->dither, conf->colors, conf->speed);

    out = gdImagePngPtr(img, &size);

    gdImageDestroy(img);

    ngx_pfree(r->pool, ctx->image);

    if (out == NULL) {

        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "gdImagePngPtr() failed");

        return NULL;
    }

    if (conf->store) {

        if(ngx_http_complex_value(r, conf->store, &value) != NGX_OK) {

            goto failed;
        }

        dest.len = value.len + 1;
        dest.data = ngx_pnalloc(r->pool, dest.len);

        if (dest.data == NULL) {

            goto failed;
        }

        ngx_memzero(dest.data, dest.len);
        ngx_memcpy(dest.data, value.data, value.len);

        ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                       "pngquant_store (%s)", dest.data);

        tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));

        if (tf == NULL) {

            goto failed;
        }

        tf->file.fd = NGX_INVALID_FILE;
        tf->file.log = r->connection->log;
        tf->path = conf->temp_path;
        tf->pool = r->pool;
        tf->persistent = 1;
        rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent,
                                  tf->clean, tf->access);

        if (rc != NGX_OK) {

            goto failed;
        }

        n = ngx_write_fd(tf->file.fd, out, size);

        if (n == NGX_FILE_ERROR) {

            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                          ngx_write_fd_n " \"%s\" failed", tf->file.name.data);

            goto failed;
        }

        if ((int) n != size) {

            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
                          ngx_write_fd_n " has written only %z of %uz bytes",
                          n, size);

            goto failed;
        }

        ext.access = conf->store_access;
        ext.path_access = conf->store_access;
        ext.time = -1;
        ext.create_path = 1;
        ext.delete_file = 1;
        ext.log = r->connection->log;

        rc = ngx_ext_rename_file(&tf->file.name, &dest, &ext);

        if (rc != NGX_OK) {

            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "ngx_ext_rename_file() failed");

            goto failed;
        }
    }

    cln = ngx_pool_cleanup_add(r->pool, 0);

    if (cln == NULL) {

        goto failed;
    }

    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));

    if (b == NULL) {

        goto failed;
    }

    cln->handler = ngx_http_pngquant_cleanup;
    cln->data = out;

    b->pos = out;
    b->last = out + size;
    b->memory = 1;
    b->last_buf = 1;

    ngx_http_pngquant_length(r, b);

#if defined(nginx_version) && (nginx_version >= 1007003)
    ngx_http_weak_etag(r);
#endif

    return b;

failed:

    gdFree(out);

    return NULL;
}
Exemple #14
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    ssize_t      n;
    ngx_uint_t   wrote_stderr, debug_connection;
    u_char       errstr[NGX_MAX_ERROR_STR];

    // 错误消息的最大长度,2k字节
    last = errstr + NGX_MAX_ERROR_STR;

    // 先拷贝当前的时间
    // 格式是"1970/09/28 12:00:00"
    p = ngx_cpymem(errstr, ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);

    // 打印错误等级的字符串描述信息,使用关联数组err_levels
    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    // 打印pid和tid
    // #define ngx_log_pid  ngx_pid
    // #define ngx_log_tid           ngx_thread_tid()
    // in os/unix

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    // 如果有连接计数则打印
    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    // 前面输出的是基本的信息:当前时间+[错误级别]+pid#tid:
    msg = p;

    // 打印可变参数
#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    // 如果有系统错误码,那么记录(err)
    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    // 记录错误日志时可以执行的回调函数
    // 参数是消息缓冲区里剩余的空间
    // 只有高于debug才会执行
    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    // #define NGX_LINEFEED_SIZE        1
    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    // #define ngx_linefeed(p)          *p++ = LF;
    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    // 对整个日志链表执行写入操作
    while (log) {

        if (log->log_level < level && !debug_connection) {
            break;
        }

        if (log->writer) {
            log->writer(log, level, errstr, p - errstr);
            goto next;
        }

        if (ngx_time() == log->disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            goto next;
        }

        // 写错误日志消息到关联的文件
        // 实际上就是系统调用write,见ngx_files.h
        n = ngx_write_fd(log->file->fd, errstr, p - errstr);

        // 写入失败,且错误是磁盘满
        if (n == -1 && ngx_errno == NGX_ENOSPC) {
            log->disk_full_time = ngx_time();
        }

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

    next:

        // 使用下一个日志对象记录日志
        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr)
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
Exemple #15
0
 /*
  * __cdecl表示C语言默认的函数调用方法,即所有参数从右到左依次入栈,这些参数有调用者负责清除,被调用函数不会要求
  * 调用者传递多少参数,调用者传递过多或过少的参数都不会引起编译错误。
  */
int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;

    ngx_debug_init();  //设置全局变量ngx_debug_malloc

    /*初始化系统错误码对应的描述性字符串*/
    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    /*ngx_get_options()函数用于解析命令行参数,并设置命令行参数相应的标志位*/
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    /*根据ngx_get_options()函数中设置的标志位打印相关信息到标准输出上*/
    if (ngx_show_version) {
        ngx_show_version_info();

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    /*初始化并更新nginx内核使用的时间*/
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    /*获取master进程ID*/
    ngx_pid = ngx_getpid();

    /*初始化全局错误日志对象ngx_log及前缀ngx_prefix*/
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    /*为进程唯一核心结构体ngx_cycle_t的创建内存池*/
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

    /*保存命令行参数*/
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    /*ngx_process_options()用于初始化ngx_cycle的prefix, conf_prefix, conf_file, conf_param等*/
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    /*对Nginx内核中用到的一些和操作系统相关性大的全局变量进行初始化*/
    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    /*初始化循环冗余校验表,后续校验可以直接通过查表法*/
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    /*平滑升级时新版本master进程对旧版本master进程的监听句柄做继承处理*/
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    /*ngx_preinit_modules()初始化模块的一些信息和部分相关全局变量*/
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

    /*初始化全局唯一的ngx_cycle_t*/
    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    /*"nginx -s xxx"*/
    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        ngx_process = NGX_PROCESS_MASTER;
    }

#if !(NGX_WIN32)

    /*初始化信号*/
    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    /*创建pidfile,并写入当前进程id*/
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    /*关闭日志文件流*/
    if (log->file->fd != ngx_stderr) {
        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    /*单进程模式运行*/
    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);

    } else {
        /*以一个master进程多个woker进程运行*/
        ngx_master_process_cycle(cycle);
    }

    return 0;
}
Exemple #16
0
// nginx启动的入口函数
// 相关文件ngx_process_cycle.c/ngx_posix_init.c/ngx_process.c
// 设置重要的指针volatile ngx_cycle_t  *ngx_cycle;
//
// 1)解析命令行参数,显示帮助信息
// 2)初始化操作系统调用接口函数ngx_os_io = ngx_linux_io;
// 3)根据命令行参数等建立一个基本的cycle
// 4)初始化模块数组ngx_modules
// 5)核心操作,调用ngx_init_cycle创建进程使用的cycle,解析配置文件,启动监听端口
// 6)启动单进程或多进程
int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;    //cycle结构体
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;      //获得ngx_core_module的配置结构体

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    // 解析命令行参数, 本文件内查找ngx_get_options
    // 设置ngx_show_version/ngx_show_help等变量
    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    // 1.9.x改到ngx_show_version_info()
    if (ngx_show_version) {

        ngx_show_version_info();

        // 1.9.x ngx_show_version_info()结束

        if (!ngx_test_config) {     //如果是-t参数,那么接下来要走流程检查配置但不启动
            return 0;
        }
    }

    // 在ngx_os_init函数里设置(os/unix/ngx_posix_init.c)
    // 使用系统调用getrlimit(RLIMIT_NOFILE, &rlmt)
    // 是nginx能够打开的最多描述数量,但似乎并没有使用
    /* TODO */ ngx_max_sockets = -1;

    // ngx_times.c,初始化各个cache时间变量
    // 调用ngx_time_update(),得到当前的时间
    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();       // 正则表达式库初始化
#endif

    // 定义在os/unix/ngx_process_cycle.c : ngx_pid_t     ngx_pid;
    // ngx_process.h : #define ngx_getpid   getpid
    // 获取当前进程也就是master进程的pid
    // 如果是master/worker,会fork出新的子进程,见os/unix/ngx_daemon.c
    ngx_pid = ngx_getpid();

    // 初始化log
    // ngx_prefix是-p后的参数,即nginx的工作目录
    // 默认是NGX_CONF_PREFIX,即/usr/local/nginx
    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    // 设置最开始的cycle
    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;

    // 定义在ngx_cycle.c,
    // volatile ngx_cycle_t  *ngx_cycle;
    // nginx生命周期使用的超重要对象
    // ngx_cycle指针指向第一个cycle结构体
    ngx_cycle = &init_cycle;

    //创建cycle使用的内存池,用于之后所有的内存分配,必须成功
    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

    // 分配内存,拷贝参数,没有使用内存池
    // 拷贝到全局变量ngx_argc/ngx.argv
    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    // 设置cycle->prefix/cycle->conf_prefix等成员
    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    // os/unix/ngx_posix_init.c
    // 初始化ngx_os_io结构体,设置基本的收发函数
    // 基本的页大小,ngx_pagesize = getpagesize()
    // 最多描述符数量,ngx_max_sockets
    // 初始化随机数
    // ngx_os_io = ngx_linux_io;重要的操作,设置为linux的接口函数
    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    // 初始化用于crc32计算的表,在ngx_crc32.c
    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    // 检查NGINX环境变量,获取之前监听的socket
    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    // 开始计算所有的静态模块数量
    // ngx_modules是nginx模块数组,存储所有的模块指针,由make生成在objs/ngx_modules.c
    // 这里赋值每个模块的index成员
    // ngx_modules_n保存了最后一个可用的序号
    // ngx_max_module是模块数量的上限
    if (ngx_preinit_modules() != NGX_OK) {
        return 1;
    }

    // ngx_cycle.c
    // 初始化cycle,800多行
    // 由之前最基本的init_cycle产生出真正使用的cycle
    // 解析配置文件,配置所有的模块
    // 创建共享内存,打开文件,监听配置的端口
    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

    // 如果用了-t参数要测试配置,在这里就结束了
    // 定义在ngx_cycle.c
    if (ngx_test_config) {
        //非安静模式,输出测试信息
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        // 1.10, dump整个配置文件
        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    // 如果用了-s参数,那么就要发送reload/stop等信号,然后结束
    if (ngx_signal) {
        // ngx_cycle.c
        // 最后调用os/unix/ngx_process.c里的函数ngx_os_signal_process()
        return ngx_signal_process(cycle, ngx_signal);
    }

    // ngx_posix_init.c
    // 使用NGX_LOG_NOTICE记录操作系统的一些信息,通常不会显示
    ngx_os_status(cycle->log);

    // 定义在ngx_cycle.c,
    // volatile ngx_cycle_t  *ngx_cycle;
    // nginx生命周期使用的超重要对象
    ngx_cycle = cycle;

    // 检查core模块的配置
    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    // master on且单进程
    // 如果master_process off那么就不是master进程
    // ngx_process定义在os/unix/ngx_process_cycle.c
    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        // 设置为master进程状态
        ngx_process = NGX_PROCESS_MASTER;
    }

// unix/linux将进程守护进程化
#if !(NGX_WIN32)

    // os/unix/ngx_process.c
    // 使用signals数组,初始化信号处理handler
    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    // 守护进程
    if (!ngx_inherited && ccf->daemon) {
        // os/unix/ngx_daemon.c
        // 经典的daemon操作,使用fork
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    // ngx_cycle.c
    // 把ngx_pid字符串化,写入pid文件
    // 在daemon后,此时的pid是真正的master进程pid
    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    if (log->file->fd != ngx_stderr) {
        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    // 启动单进程或者master/worker多进程,内部会调用fork
    // 子进程完全复制父进程的cycle,包括打开的文件、共享内存、监听的端口
    if (ngx_process == NGX_PROCESS_SINGLE) {
        // 如果master_process off那么就不是master进程
        // ngx_process_cycle.c
        ngx_single_process_cycle(cycle);

    } else {
        // ngx_process_cycle.c
        // 启动worker进程,数量由配置决定,即worker_processes指令
        // 核心操作是sigsuspend,暂时挂起进程,不占用CPU,只有收到信号时才被唤醒
        ngx_master_process_cycle(cycle);
    }

    // 只有退出无限循环才会走到这里,进程结束
    return 0;
}
static void
ngx_rtmp_dash_close_fragment(ngx_rtmp_session_t *s, ngx_rtmp_dash_track_t *t)
{
    u_char                    *pos, *pos1;
    size_t                     left;
    ssize_t                    n;
    ngx_fd_t                   fd;
    ngx_buf_t                  b;
    ngx_rtmp_dash_ctx_t       *ctx;
    ngx_rtmp_dash_frag_t      *f;

    static u_char              buffer[NGX_RTMP_DASH_BUFSIZE];

    if (!t->opened) {
        return;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "dash: close fragment id=%ui, type=%c, pts=%uD",
                   t->id, t->type, t->earliest_pres_time);

    ctx = ngx_rtmp_get_module_ctx(s, ngx_rtmp_dash_module);

    b.start = buffer;
    b.end = buffer + sizeof(buffer);
    b.pos = b.last = b.start;

    ngx_rtmp_mp4_write_styp(&b);

    pos = b.last;
    b.last += 44; /* leave room for sidx */

    ngx_rtmp_mp4_write_moof(&b, t->earliest_pres_time, t->sample_count,
                            t->samples, t->sample_mask, t->id);
    pos1 = b.last;
    b.last = pos;

    ngx_rtmp_mp4_write_sidx(&b, t->mdat_size + 8 + (pos1 - (pos + 44)),
                            t->earliest_pres_time, t->latest_pres_time);
    b.last = pos1;
    ngx_rtmp_mp4_write_mdat(&b, t->mdat_size + 8);

    /* move the data down to make room for the headers */

    f = ngx_rtmp_dash_get_frag(s, ctx->nfrags);

    *ngx_sprintf(ctx->stream.data + ctx->stream.len, "%uD.m4%c",
                 f->timestamp, t->type) = 0;

    fd = ngx_open_file(ctx->stream.data, NGX_FILE_RDWR,
                       NGX_FILE_TRUNCATE, NGX_FILE_DEFAULT_ACCESS);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: error creating dash temp video file");
        goto done;
    }

    if (ngx_write_fd(fd, b.pos, (size_t) (b.last - b.pos)) == NGX_ERROR) {
        goto done;
    }

    left = (size_t) t->mdat_size;

#if (NGX_WIN32)
    if (SetFilePointer(t->fd, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
                      "dash: SetFilePointer error");
        goto done;
    }
#else
    if (lseek(t->fd, 0, SEEK_SET) == -1) {
        ngx_log_error(NGX_LOG_ERR, s->connection->log, ngx_errno,
                      "dash: lseek error");
        goto done;
    }
#endif

    while (left > 0) {

        n = ngx_read_fd(t->fd, buffer, ngx_min(sizeof(buffer), left));
        if (n == NGX_ERROR) {
            break;
        }

        n = ngx_write_fd(fd, buffer, (size_t) n);
        if (n == NGX_ERROR) {
            break;
        }

        left -= n;
    }

done:

    if (fd != NGX_INVALID_FILE) {
        ngx_close_file(fd);
    }

    ngx_close_file(t->fd);

    t->fd = NGX_INVALID_FILE;
    t->opened = 0;
}
Exemple #18
0
int ngx_cdecl
main(int argc, char *const *argv)
{
    ngx_buf_t        *b;
    ngx_log_t        *log;
    ngx_uint_t        i;
    ngx_cycle_t      *cycle, init_cycle;
    ngx_conf_dump_t  *cd;
    ngx_core_conf_t  *ccf;

    ngx_debug_init();

    if (ngx_strerror_init() != NGX_OK) {
        return 1;
    }

    if (ngx_get_options(argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_show_version) {
        ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

        if (ngx_show_help) {
            ngx_write_stderr(
                "Usage: nginx [-?hvVtTq] [-s signal] [-c filename] "
                             "[-p prefix] [-g directives]" NGX_LINEFEED
                             NGX_LINEFEED
                "Options:" NGX_LINEFEED
                "  -?,-h         : this help" NGX_LINEFEED
                "  -v            : show version and exit" NGX_LINEFEED
                "  -V            : show version and configure options then exit"
                                   NGX_LINEFEED
                "  -t            : test configuration and exit" NGX_LINEFEED
                "  -T            : test configuration, dump it and exit"
                                   NGX_LINEFEED
                "  -q            : suppress non-error messages "
                                   "during configuration testing" NGX_LINEFEED
                "  -s signal     : send signal to a master process: "
                                   "stop, quit, reopen, reload" NGX_LINEFEED
#ifdef NGX_PREFIX
                "  -p prefix     : set prefix path (default: "
                                   NGX_PREFIX ")" NGX_LINEFEED
#else
                "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
#endif
                "  -c filename   : set configuration file (default: "
                                   NGX_CONF_PATH ")" NGX_LINEFEED
                "  -g directives : set global directives out of configuration "
                                   "file" NGX_LINEFEED NGX_LINEFEED
                );
        }

        if (ngx_show_configure) {

#ifdef NGX_COMPILER
            ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
#endif

#if (NGX_SSL)
            if (SSLeay() == SSLEAY_VERSION_NUMBER) {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 NGX_LINEFEED);
            } else {
                ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
                                 " (running with ");
                ngx_write_stderr((char *) (uintptr_t)
                                 SSLeay_version(SSLEAY_VERSION));
                ngx_write_stderr(")" NGX_LINEFEED);
            }
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
            ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
#else
            ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
#endif
#endif

            ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
        }

        if (!ngx_test_config) {
            return 0;
        }
    }

    /* TODO */ ngx_max_sockets = -1;

    ngx_time_init();

#if (NGX_PCRE)
    ngx_regex_init();
#endif

    ngx_pid = ngx_getpid();

    log = ngx_log_init(ngx_prefix);
    if (log == NULL) {
        return 1;
    }

    /* STUB */
#if (NGX_OPENSSL)
    ngx_ssl_init(log);
#endif

    /*
     * init_cycle->log is required for signal handlers and
     * ngx_process_options()
     */

    ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
    init_cycle.log = log;
    ngx_cycle = &init_cycle;

    init_cycle.pool = ngx_create_pool(1024, log);
    if (init_cycle.pool == NULL) {
        return 1;
    }

    if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
        return 1;
    }

    if (ngx_process_options(&init_cycle) != NGX_OK) {
        return 1;
    }

    if (ngx_os_init(log) != NGX_OK) {
        return 1;
    }

    /*
     * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
     */

    if (ngx_crc32_table_init() != NGX_OK) {
        return 1;
    }

    if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
        return 1;
    }

    ngx_max_module = 0;
    for (i = 0; ngx_modules[i]; i++) {
        ngx_modules[i]->index = ngx_max_module++;
    }

    cycle = ngx_init_cycle(&init_cycle);
    if (cycle == NULL) {
        if (ngx_test_config) {
            ngx_log_stderr(0, "configuration file %s test failed",
                           init_cycle.conf_file.data);
        }

        return 1;
    }

    if (ngx_test_config) {
        if (!ngx_quiet_mode) {
            ngx_log_stderr(0, "configuration file %s test is successful",
                           cycle->conf_file.data);
        }

        if (ngx_dump_config) {
            cd = cycle->config_dump.elts;

            for (i = 0; i < cycle->config_dump.nelts; i++) {

                ngx_write_stdout("# configuration file ");
                (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
                                    cd[i].name.len);
                ngx_write_stdout(":" NGX_LINEFEED);

                b = cd[i].buffer;

                (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
                ngx_write_stdout(NGX_LINEFEED);
            }
        }

        return 0;
    }

    if (ngx_signal) {
        return ngx_signal_process(cycle, ngx_signal);
    }

    ngx_os_status(cycle->log);

    ngx_cycle = cycle;

    ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

    if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
        ngx_process = NGX_PROCESS_MASTER;
    }

#if !(NGX_WIN32)

    if (ngx_init_signals(cycle->log) != NGX_OK) {
        return 1;
    }

    if (!ngx_inherited && ccf->daemon) {
        if (ngx_daemon(cycle->log) != NGX_OK) {
            return 1;
        }

        ngx_daemonized = 1;
    }

    if (ngx_inherited) {
        ngx_daemonized = 1;
    }

#endif

    if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
        return 1;
    }

    if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
        return 1;
    }

    if (log->file->fd != ngx_stderr) {
        if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_close_file_n " built-in log failed");
        }
    }

    ngx_use_stderr = 0;

    if (ngx_process == NGX_PROCESS_SINGLE) {
        ngx_single_process_cycle(cycle);

    } else {
        ngx_master_process_cycle(cycle);
    }

    return 0;
}
char *
ngx_xconf_include_uri(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_str_t          *arg, uri, filename, scheme_name;
    ngx_xconf_ctx_t     ctx;
    ngx_flag_t          is_last_elt;
    ngx_uint_t          i;
    ngx_str_t          *cmd_name;
    u_char              need_next;
    ngx_str_t           ofilename_prefix = ngx_string("$file"),
                        ofilename_suffix = ngx_string("l$line.conf"),
                        ofilename_suffix2 = ngx_string("conf");
    char               *rv;
    u_char             *s; /* 用于临时分配内存用 */;
    lua_State          *L;
    ngx_xconf_scheme_t *scheme;


    arg = cf->args->elts;
    cmd_name = &arg[0];

    scheme = ngx_xconf_schemes;
    if ((scheme == NULL) || (scheme->name.len == 0)) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "%V: no scheme define.",
                cmd_name);

        return NGX_CONF_ERROR;
    }

    /* 参数说明见 README */

    uri.len = 0;        /* 如果没设定报错 */
    filename.len = 0;   /* 如果没设定就默认给一个 */
    ctx.evaluri = 1;    /* 默认 eval uri */
    ctx.keep_error_cachefile = 0;   /* 默认删除解析出错的 cachefile */
    ctx.pre_usecache = -1;   /* 默认不使用 cachefile */
    ctx.fail_usecache = -1;   /* 默认不使用 cachefile */

    ctx.fetch_content = NULL;
    ctx.do_cachefile = 0;

    need_next = 0;
    is_last_elt = 0;

    /* 解析参数 {{{ */
    for (i = 1; i < cf->args->nelts; i++) {
        if (! (arg[i].len)) {
            continue;
        }

        is_last_elt = i == cf->args->nelts - 1;

        if (need_next) {
            switch(need_next) {
                case 'o':
                    filename.data = arg[i].data;
                    filename.len = arg[i].len;
                    break;
                case 'O':
                    filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix.len + sizeof("..") - 1;
                    filename.data = ngx_palloc(cf->pool, filename.len + 1);
                    ngx_snprintf(filename.data, filename.len,
                            "%V.%V.%V",
                            &ofilename_prefix, &arg[i], &ofilename_suffix);
                    break;
                case 'I':
                    filename.len = ofilename_prefix.len + arg[i].len + ofilename_suffix2.len + sizeof("..") - 1;
                    filename.data = ngx_palloc(cf->pool, filename.len + 1);
                    ngx_snprintf(filename.data, filename.len,
                            "%V.%V.%V",
                            &ofilename_prefix, &arg[i], &ofilename_suffix2);
                    break;
                case 't':
                    ctx.timeout = ngx_parse_time(&arg[i], 1);
                    if (ctx.timeout == NGX_ERROR) {
                        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                                "%V: option [-t %V] value error.",
                                cmd_name, &arg[i]);

                        return NGX_CONF_ERROR;
                    }
                    break;
                case 'c':
                    if (arg[i].len == 2 && arg[i].data[0] == '-' && arg[i].data[1] == '1') {
                        ctx.pre_usecache = -1 * (arg[i].data[1] - '0');
                    } else {
                        ctx.pre_usecache = ngx_parse_time(&arg[i], 1);
                        if (ctx.pre_usecache == NGX_ERROR) {
                            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                                    "%V: option [-c %V] value error.",
                                    cmd_name, &arg[i]);

                            return NGX_CONF_ERROR;
                        }
                    }
                    break;
                case 'C':
                    if (arg[i].len == 2 && arg[i].data[0] == '-' &&
                            (arg[i].data[1] >= '1' && arg[i].data[1] <= '2')) {
                        ctx.fail_usecache = -1 * (arg[i].data[1] - '0');
                    } else {
                        ctx.fail_usecache = ngx_parse_time(&arg[i], 1);
                        if (ctx.fail_usecache == NGX_ERROR) {
                            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                                    "%V: option [-C %V] value error.",
                                    cmd_name, &arg[i]);

                            return NGX_CONF_ERROR;
                        }
                    }
                    break;
                default:
                    /* 通常不会到这里 */
                    ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                            "%V: unknown option [%c] .",
                            cmd_name, need_next);

                    return NGX_CONF_ERROR;
            }

            need_next = 0;
            continue;
        } else {
            if (arg[i].data[0] == '-') {
                /* 现在只支持 -x */
                if (arg[i].len != 2) {
                    goto unknow_opt;
                }
                switch(arg[i].data[1]) {
                    case 'K':
                        ctx.keep_error_cachefile = 1;
                        break;
                    case 'n':
                        ctx.evaluri = 0;
                        break;
                    case 'c':
                    case 'C':
                    case 'o':
                    case 'I':
                    case 'O':
                    case 't':
                        need_next = arg[i].data[1];

                        if (is_last_elt) {
                            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                                    "%V: option [-%c] need a value.",
                                    cmd_name, need_next);

                            return NGX_CONF_ERROR;
                        }

                        break;
                    default:
                        goto unknow_opt;
                }

                continue;
            } else { /* this will be the uri */
                uri.data = arg[i].data;
                uri.len = arg[i].len;

                continue;
            }
        }

        goto unknow_opt;
    }
    /* }}} */

    /* 因为上面不需要用到 lua 的功能,所有此刻才初始化 lua vm {{{ */
    L = luaL_newstate();

    if (L == NULL) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "%V: create lua vm fail.",
                cmd_name);

        return NGX_CONF_ERROR;
    }

    /* XXX 从这以下如果出错,需要 goto error; 因为要 close lua vm */

    ctx.lua = L;

    luaL_openlibs(L);
    {
        int         rc;
        ngx_str_t   msg;

        rc = luaL_loadbuffer(L, (const char*) xconf_util_lua, sizeof(xconf_util_lua), "ngx_xconf_util.lua(embed)");
        if (rc != 0) {
            msg.data = (u_char *) lua_tolstring(L, -1, &msg.len);

            if (msg.data == NULL) {
                msg.data = (u_char *) "unknown reason";
                msg.len = sizeof("unknown reason") - 1;
            }

            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "xconf load lua code error: %V.",
                    &msg);

            lua_pop(L, 1);

            rv = NULL;
            goto error;
        }
    }
    /* 这个 lua 文件会创建 若干个 全局函数,如: format */

    if (ngx_xconf_util_lua_pcall(cf, L, 0, 0, 0, 0) != NGX_OK) {
        rv = NULL;
        goto error;
    }
    /* }}} */

    /* 创建变量 table 到 lua vm (var_ctx) 里,用于变量插值 {{{ */
    lua_createtable(L, /* i */0, /* key */10); /* var_ctx */
    lua_pushlstring(L, (char *)cf->conf_file->file.name.data, cf->conf_file->file.name.len);
    lua_setfield(L, -2, "file");
    lua_pushnumber(L, cf->conf_file->line);
    lua_setfield(L, -2, "line");
    lua_pushlstring(L, (char *)cf->cycle->prefix.data, cf->cycle->prefix.len);
    lua_setfield(L, -2, "prefix");
    lua_pushlstring(L, (char *)cf->cycle->conf_prefix.data, cf->cycle->conf_prefix.len);
    lua_setfield(L, -2, "conf_prefix");
    lua_pushnumber(L, (int) ngx_pid);
    lua_setfield(L, -2, "pid");
    lua_pushlstring(L, (char *)cf->cycle->hostname.data, cf->cycle->hostname.len);
    lua_setfield(L, -2, "hostname");
    {
        ngx_time_t *tp = ngx_timeofday();

        lua_pushnumber(L, (int) (tp->sec));
        lua_setfield(L, -2, "time"); /* var_ctx */
    }

    lua_setfield(L, LUA_GLOBALSINDEX, "var_ctx");
    /* }}} */

    /* 对 uri 进行变量插值 {{{ */
    if (ctx.evaluri) {
        lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */
        lua_pushlstring(L, (char *) uri.data, uri.len);
        if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) {
            rv = NULL;
            goto error;
        }
        uri.data = (u_char *) lua_tolstring(L, -1, &uri.len);
        s = ngx_palloc(cf->pool, uri.len);
        ngx_memcpy(s, uri.data, uri.len);
        uri.data = s;
        s = NULL;
        lua_pop(L, 1);
    }

    if (! (uri.len)) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "%V: must give us uri.",
                cmd_name);

        rv = NULL;
        goto error;
    }

    ctx.uri.len = uri.len;
    ctx.uri.data = uri.data;
    /* }}} */

    /* 计算 uri 的 scheme_name {{{ */
    /* 如果以 '//' 开头 认为是 http: */
    if (uri.len > 2 && uri.data[0] == '/' && uri.data[1] == '/') {
        ctx.noscheme_uri.data = uri.data;
        ctx.noscheme_uri.len = uri.len;

        scheme_name.len = sizeof("http") - 1;
        scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1);
        ngx_cpystrn(scheme_name.data, (u_char *)"http", scheme_name.len + 1);
    /* 如果以 '/' 或 './' 开头 认为是 file: */
    } else if (uri.data[0] == '/'
            || (uri.len > 2 && uri.data[0] == '.' && uri.data[1] == '/')) {

        size_t is_abs = uri.data[0] == '/';
        u_char *data = uri.data + (is_abs ? 0 : 2);
        size_t len = uri.len - (is_abs ? 0 : 2);

        ctx.noscheme_uri.len = len + 2;
        ctx.noscheme_uri.data = ngx_palloc(cf->pool, len + 2 + 1);
        ctx.noscheme_uri.data[0] = '/';
        ctx.noscheme_uri.data[1] = '/';
        ngx_cpystrn(ctx.noscheme_uri.data + 2, data, len + 1);

        scheme_name.len = sizeof("file") - 1;
        scheme_name.data = ngx_palloc(cf->pool, scheme_name.len + 1);
        ngx_cpystrn(scheme_name.data, (u_char *)"file", scheme_name.len + 1);
    } else {
        u_char      c;
        ngx_str_t   tmp_scheme;
        size_t      i, maxi, found;

        /* find scheme: [a-z_][a-z_0-9+.-]: , max_scheme_len */
        tmp_scheme.data = ngx_palloc(cf->pool, max_scheme_len);
        tmp_scheme.len = 0;
        i = 0;
        maxi = uri.len - 1;
        found = 0;

        while (i < max_scheme_len && i <= maxi) {
            c = uri.data[i];

            if (c == ':') {
                found = 1;
                break;
            }

            tmp_scheme.data[i] = c;
            tmp_scheme.len++;
            if ((c >= 'a' && c <= 'z')
                    || (c >= 'A' && c <= 'Z')
                    || (c >= '0' && c <= '9')
                    || c == '+' || c == '-' || c == '.') {
            } else {
                ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                        "%V: uri (%V...) have no valid scheme name.",
                        cmd_name, &tmp_scheme);

                rv = NULL;
                goto error;
            }

            /* XXX important */
            i++;
        }

        if (! (found && tmp_scheme.len)) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%V: uri (%V) have no valid scheme name.",
                    cmd_name, &uri);

            rv = NULL;
            goto error;
        }

        scheme_name.len = tmp_scheme.len;
        scheme_name.data = tmp_scheme.data;
        scheme_name.data[tmp_scheme.len] = '\0';

        /* 1 -> the ':' after scheme name */
        ctx.noscheme_uri.len = uri.len - tmp_scheme.len - 1;
        ctx.noscheme_uri.data = uri.data + tmp_scheme.len + 1;
    }
    /* }}} */

    /* 查找当前 scheme {{{ */
    for ( /* void */ ; scheme->name.len; scheme++) {
        if (scheme_name.len == scheme->name.len &&
                ngx_strcmp(scheme_name.data, scheme->name.data) == 0) {
            break;
        }
    }

    if (! scheme->name.len) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "%V: no scheme found for \"%V\".",
                cmd_name, &ctx.scheme);

        rv = NULL;
        goto error;
    }
    /* }}} */

    ctx.scheme = scheme;

    /* 如果 scheme usecache 则计算 filename 并 判断 pre_usecache {{{ */
    if (scheme->usecache) {
        /* filename 计算, 插值, 展开 {{{ */
        if (! (filename.len)) {
            filename.len = ofilename_prefix.len + ofilename_suffix.len + sizeof(".") - 1;
            filename.data = ngx_palloc(cf->pool, filename.len + 1);
            ngx_snprintf(filename.data, filename.len,
                    "%V.%V",
                    &ofilename_prefix, &ofilename_suffix);
        }

        /* FIXME filename.data 是否需要 free ?? */
        lua_getfield(L, LUA_GLOBALSINDEX, "format"); /* got the format function */
        lua_pushlstring(L, (char *) filename.data, filename.len);
        if (ngx_xconf_util_lua_pcall(cf, L, 1, 1, 0, 0) != NGX_OK) {
            rv = NULL;
            goto error;
        }
        filename.data = (u_char *) lua_tolstring(L, -1, &filename.len);
        s = ngx_palloc(cf->pool, filename.len + 1);
        ngx_cpystrn(s, filename.data, filename.len + 1); /* 让 ngx_cpystrn 帮忙添加个 \0 */
        filename.data = s;
        s = NULL;
        lua_pop(L, 1);

        if (ngx_conf_full_name(cf->cycle, &filename, 1) != NGX_OK) {
            rv = NULL;
            goto error;
        }
        /* }}} */

        ctx.cachefile = ngx_palloc(cf->pool, sizeof(ngx_file_t));
        if (ctx.cachefile == NULL) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%V: alloc cachefile error.",
                    cmd_name);

            rv = NULL;
            goto error;
        }
        ngx_memzero(ctx.cachefile, sizeof(ngx_file_t));

        ctx.cachefile->name = filename;
        ctx.cachefile->log = cf->log;

        dd("pre-usecache: %d, %d", (int)ctx.scheme->pre_usecache, (int)ctx.pre_usecache);
        if (ctx.scheme->pre_usecache && ctx.pre_usecache > -1) {
            ngx_file_t  *file;

            file = ctx.cachefile;

            /* 获取文件信息 FAIL */
            if (ngx_file_info(file->name.data, &file->info) == -1) {
                /* 如果文件不存在则忽略,否则报错 */
                if (errno != ENOENT) {
                    ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                            "%V: get file \"%V\" info error: %s.",
                            cmd_name, file->name, strerror(errno));

                    rv = NULL;
                    goto error;
                }
            /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */
            } else {
                int     now;

                /* 只要文件存在就用 */
                if (ctx.pre_usecache == 0) {
                    goto do_cachefile;
                }

                ngx_time_update();
                now = (int)ngx_time();

                dd("pre-usecache now: %d, mtime: %d, diff: %d, pref: %d.",
                        now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.pre_usecache);

                if (now - file->info.st_mtime <= ctx.pre_usecache) {
                    goto do_cachefile;
                }
            }
        }
    }
    /* }}} */

    ngx_log_error(NGX_LOG_INFO, cf->log, 0,
            "\n- - - - - - - -\ncmd_name: %V\nfileneme: %V\nuri: %V\npre_usecache: %d\nfail_usecache: %d\nevaluri: %d\nscheme: %V\nnoscheme_uri: %V\n- - - - - - - -",
            cmd_name, &filename, &uri, ctx.pre_usecache, ctx.fail_usecache, ctx.evaluri, &ctx.scheme->name, &ctx.noscheme_uri);

    /* 执行具体 scheme {{{ */
    rv = scheme->handler(cf, cmd, conf, &ctx);

    if (rv == NGX_CONF_OK) {
        goto done;
    } else if (rv == NGX_XCONF_FETCH_ERROR) {
        /* do fail_usecache */
        if (scheme->usecache) {
            goto fetch_fail;
        } else {
            /* 不可能 */
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "if you see this error, please report it to author with \"%V\".",
                    &scheme->name);

            rv = NULL;
            goto error;
        }
    } else if (rv == NGX_XCONF_FETCH_OK) {
        if (scheme->usecache) {
            if (ctx.fetch_content != NULL) {
                goto save_cachefile;
            } else if (ctx.do_cachefile) {
                goto do_cachefile;
            }
        }

        goto done;
    } else {
        goto error;
    }
    /* }}} */

    goto done;

fetch_fail:
    dd("fail-usecache: %d, %d", (int)ctx.scheme->fail_usecache, (int)ctx.fail_usecache);

    if (ctx.scheme->fail_usecache && ctx.fail_usecache != -1) {
        /* 删除 */
        if (ctx.fail_usecache != -2) {
            ngx_delete_file(ctx.cachefile->name.data);

            rv = NULL;
            goto error;

        } else if (ctx.fail_usecache >= 0) {
            ngx_file_t  *file;

            file = ctx.cachefile;

            /* 获取文件信息 FAIL */
            if (ngx_file_info(file->name.data, &file->info) == -1) {
                ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                        "%V: get file \"%V\" info in fetch_fail error: %s.",
                        cmd_name, file->name, strerror(errno));

                rv = NULL;
                goto error;
            /* 获取文件信息 OK, 有没可能是个 目录 ?? ,如果谁这么配置 !!! */
            } else {
                int     now;

                /* 只要文件存在就用 */
                if (ctx.fail_usecache == 0) {
                    goto do_cachefile;
                }

                ngx_time_update();
                now = (int)ngx_time();

                dd("fail-usecache now: %d, mtime: %d, diff: %d, pref: %d.",
                        now, (int)file->info.st_mtime, now - (int)file->info.st_mtime, (int)ctx.fail_usecache);

                if (now - file->info.st_mtime <= ctx.fail_usecache) {
                    goto do_cachefile;
                }
            }
        } else {
            /* 不可能 */

            rv = NULL;
            goto error;
        }
    }

    rv = NULL;
    goto error;

save_cachefile:
    {
        int rc;

        ctx.cachefile->fd = ngx_open_file(ctx.cachefile->name.data, O_WRONLY, O_CREAT | O_TRUNC , S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);

        if (ctx.cachefile->fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%V: open (%V) error: \"%s\".",
                    cmd_name, &ctx.cachefile->name, strerror(errno));

            rv = NULL;
            goto error;
        }

        dd("open cachefd: %s, %d", (char *)ctx.cachefile->name.data, ctx.cachefile->fd);

        rc = ngx_write_fd(ctx.cachefile->fd, ctx.fetch_content->data, ctx.fetch_content->len);
        if (rc == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%V: write data to (%V) error: \"%s\".",
                    cmd_name, ctx.cachefile->name, strerror(errno));

            rv = NULL;
            goto error;
        } else if ((size_t)rc != ctx.fetch_content->len) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%V: write data to (%V) incomplete: %z of %uz.",
                    cmd_name, ctx.cachefile->name, rc, ctx.fetch_content->len);

            rv = NULL;
            goto error;
        }

        if (ngx_close_file(ctx.cachefile->fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                    "%: close cachefile error.",
                    cmd_name);

            rv = NULL;
            goto error;
        }

        goto do_cachefile;
    }

do_cachefile:
    if (! scheme->usecache) {
        ngx_log_error(NGX_LOG_ERR, cf->log, 0,
                "%V: current scheme \"%V\" can not usecache.",
                cmd_name, &scheme->name);

        rv = NULL;
        goto error;
    }

    dd("do cachefile");
    rv = ngx_conf_parse(cf, &ctx.cachefile->name);

    if (rv != NGX_CONF_OK) {
        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
                "%V: do cachefile \"%V\" error.",
                cmd_name, &ctx.cachefile->name);

        /* 删除解析出错的 cachefile */
        if (! ctx.keep_error_cachefile) {
            if (ngx_delete_file(ctx.cachefile->name.data) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_WARN, cf->log, 0,
                            "%V: delete cachefile \"%V\" error.",
                            cmd_name, &ctx.cachefile->name);
            }
        }

        goto error;
    }

    goto done;

done:
    lua_close(L);

    return NGX_CONF_OK;

unknow_opt:
    ngx_log_error(NGX_LOG_ERR, cf->log, 0,
            "%V: unknown option [%V].",
            cmd_name, &arg[i]);

    return NGX_CONF_ERROR;

error:
    lua_close(L);

    return rv == NULL ? NGX_CONF_ERROR : rv;
}
Exemple #20
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    u_char       errstr[NGX_MAX_ERROR_STR];
    ngx_uint_t   wrote_stderr, debug_connection;

    last = errstr + NGX_MAX_ERROR_STR;

    ngx_memcpy(errstr, ngx_cached_err_log_time.data,
               ngx_cached_err_log_time.len);

    p = errstr + ngx_cached_err_log_time.len;

    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    while (log) {

        if (log->log_level < level && !debug_connection) {
            break;
        }

        (void) ngx_write_fd(log->file->fd, errstr, p - errstr);

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr)
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
Exemple #21
0
inline void NWriteDebugLog(const char* log, int size){
	if(g_biz_debuger!=NULL && g_biz_debuger->fd > 0){
		ngx_write_fd(g_biz_debuger->fd, (void*)log,size);
	}
}
Exemple #22
0
void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
    ssize_t           n, len;
    ngx_fd_t          fd;
    ngx_uint_t        i;
    ngx_list_part_t  *part;
    ngx_open_file_t  *file;

    part = &cycle->open_files.part;
    file = part->elts;

    for (i = 0; /* void */ ; i++) {

        if (i >= part->nelts) {
            if (part->next == NULL) {
                break;
            }
            part = part->next;
            file = part->elts;
            i = 0;
        }

        if (file[i].name.data == NULL) {
            continue;
        }

        len = file[i].pos - file[i].buffer;

        if (file[i].buffer && len != 0) {

            n = ngx_write_fd(file[i].fd, file[i].buffer, len);

            if (n == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                              ngx_write_fd_n " to \"%s\" failed",
                              file[i].name.data);

            } else if (n != len) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
                          file[i].name.data, n, len);
            }

            file[i].pos = file[i].buffer;
        }

        fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR,
                           NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND,
                           NGX_FILE_DEFAULT_ACCESS);

        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                       "reopen file \"%s\", old:%d new:%d",
                       file[i].name.data, file[i].fd, fd);

        if (fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          ngx_open_file_n " \"%s\" failed", file[i].name.data);
            continue;
        }

#if (NGX_WIN32)
        if (ngx_file_append_mode(fd) == NGX_ERROR) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          ngx_file_append_mode_n " \"%s\" failed",
                          file[i].name.data);

            if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              ngx_close_file_n " \"%s\" failed",
                              file[i].name.data);
            }

            continue;
        }
#else
        if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) {
            ngx_file_info_t  fi;

            if (ngx_file_info((const char *) file[i].name.data, &fi) == -1) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              ngx_file_info_n " \"%s\" failed",
                              file[i].name.data);

                if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                  ngx_close_file_n " \"%s\" failed",
                                  file[i].name.data);
                }
            }

            if (fi.st_uid != user) {
                if (chown((const char *) file[i].name.data, user, -1) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                  "chown(\"%s\", %d) failed",
                                  file[i].name.data, user);

                    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                      ngx_close_file_n " \"%s\" failed",
                                      file[i].name.data);
                    }
                }
            }

            if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) {

                fi.st_mode |= (S_IRUSR|S_IWUSR);

                if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                  "chmod() \"%s\" failed", file[i].name.data);

                    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                                      ngx_close_file_n " \"%s\" failed",
                                      file[i].name.data);
                    }
                }
            }
        }

        if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "fcntl(FD_CLOEXEC) \"%s\" failed",
                          file[i].name.data);

            if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                              ngx_close_file_n " \"%s\" failed",
                              file[i].name.data);
            }

            continue;
        }
#endif

        if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed",
                          file[i].name.data);
        }

        file[i].fd = fd;
    }

#if !(NGX_WIN32)

    if (cycle->log->file->fd != STDERR_FILENO) {
        if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          "dup2(STDERR) failed");
        }
    }

#endif
}
static ngx_int_t
ngx_http_prelog_handler(ngx_http_request_t* r){

    ngx_http_prelog_loc_conf_t *prelog_loc_conf;
    size_t                      len;
    ssize_t                     ret;
    u_char                      *line, *p;
    ngx_http_log_op_t           *op;
    ngx_uint_t                  i;
    time_t                      now;
    ngx_err_t                   err;
    u_char                      *name;

    prelog_loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_prelog_module);

    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http prelog handler");

    if (prelog_loc_conf->enable == 0){
        return NGX_DECLINED;
    }

    if (r->internal == 1){
        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http prelog hit internal redirect, pass");
        return NGX_DECLINED;
    }

    len = 0;
    op = prelog_loc_conf->format->ops->elts;
    for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) {
        if (op[i].len == 0) {
            len += op[i].getlen(r, op[i].data);

        } else {
            len += op[i].len;
        }
    }
    len += NGX_LINEFEED_SIZE;

    line = ngx_pnalloc(r->pool, len);
    if (line == NULL) {
        return NGX_ERROR;
    }
    p = line;

    for (i = 0; i < prelog_loc_conf->format->ops->nelts; i++) {
        p = op[i].run(r, p, &op[i]);
    }

    ngx_linefeed(p);
    ret = ngx_write_fd(prelog_loc_conf->file->fd, line, p - line);

    name = prelog_loc_conf->file->name.data;
    now = ngx_time();

    if (ret == (ssize_t)len){
        goto ok;
    }

    if (ret == -1) {
        err = ngx_errno;

        if (now - prelog_loc_conf->error_log_time > 59) {
            ngx_log_error(NGX_LOG_ALERT, r->connection->log, err,
                          ngx_write_fd_n " to \"%s\" failed", name);

            prelog_loc_conf->error_log_time = now;
        }
        goto ok;
    }

    if (now - prelog_loc_conf->error_log_time > 59) {
        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                      ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz",
                      name, ret, len);

        prelog_loc_conf->error_log_time = now;
    }

ok:
    return NGX_DECLINED;
}
Exemple #24
0
void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
    ssize_t           n, len;
    ngx_fd_t          fd;
    ngx_uint_t        i;
    ngx_list_part_t  *part;
    ngx_open_file_t  *file;

    part = &cycle->open_files.part;
    file = part->elts;

    for (i = 0; /* void */ ; i++) {
        if (i >= part->nelts) {//大于等于总文件数
            if (part->next == NULL) {
                break;//如果没有了,就返回
            }
            part = part->next;//如果还有,标记i = 0,重新来
            file = part->elts;
            i = 0;
        }
        if (file[i].name.len == 0) {
            continue;
        }
        len = file[i].pos - file[i].buffer;
        if (file[i].buffer && len != 0) {//要写进去吗,确认?
            n = ngx_write_fd(file[i].fd, file[i].buffer, len);
            if (n == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, ngx_write_fd_n " to \"%s\" failed", file[i].name.data);
            } else if (n != len) {
                ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_write_fd_n " to \"%s\" was incomplete: %z of %uz", file[i].name.data, n, len);
            }

            file[i].pos = file[i].buffer;
        }
//再次打开以下这个文件
        fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS);
        ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reopen file \"%s\", old:%d new:%d", file[i].name.data, file[i].fd, fd);
        if (fd == NGX_INVALID_FILE) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,  ngx_open_file_n " \"%s\" failed", file[i].name.data);
            continue;
        }

#if !(NGX_WIN32)//如果是unix系的操作系统,需要设置文件拥有者啥的
        if (user != (ngx_uid_t) NGX_CONF_UNSET_UINT) {
            ngx_file_info_t  fi;
//得到文件的信息
            if (ngx_file_info((const char *) file[i].name.data, &fi) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_file_info_n " \"%s\" failed",  file[i].name.data);
                if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data);
                }
            }
//修改文件所有者
            if (fi.st_uid != user) {
                if (chown((const char *) file[i].name.data, user, -1) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chown(\"%s\", %d) failed", file[i].name.data, user);
                    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data);
                    }
                }
            }
//修改文件权限
            if ((fi.st_mode & (S_IRUSR|S_IWUSR)) != (S_IRUSR|S_IWUSR)) { fi.st_mode |= (S_IRUSR|S_IWUSR);
                if (chmod((const char *) file[i].name.data, fi.st_mode) == -1) {
                    ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "chmod() \"%s\" failed", file[i].name.data);
                    if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed",  file[i].name.data);
                    }
                }
            }
        }

        if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "fcntl(FD_CLOEXEC) \"%s\" failed", file[i].name.data);
            if (ngx_close_file(fd) == NGX_FILE_ERROR) {
                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed", file[i].name.data);
            }
            continue;
        }
#endif
        if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) {//关闭掉老的文件句柄
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, ngx_close_file_n " \"%s\" failed",file[i].name.data);
        }
//赋值为新的文件句柄。放心吧,没有别的地方使用这个fd的,就我一个进程,多线程版本不在此
        file[i].fd = fd;
    }

#if !(NGX_WIN32)
    if (cycle->log->file->fd != STDERR_FILENO) {//int dup2(int oldfd, int newfd);
        if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) {//标准错误输出也设置为日志.那程序的fprint(stderr,)将输出到日志文件
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,"dup2(STDERR) failed");
        }
    }
#endif
}
static ngx_int_t
ngx_rtmp_mpegts_write_file(ngx_rtmp_mpegts_file_t *file, u_char *in,
                           size_t in_size)
{
    u_char   *out;
    size_t    out_size, n;
    ssize_t   rc;

    static u_char  buf[1024];

    if (!file->encrypt) {
        ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
                       "mpegts: write %uz bytes", in_size);

        rc = ngx_write_fd(file->fd, in, in_size);
        if (rc < 0) {
            return NGX_ERROR;
        }

        return NGX_OK;
    }

    /* encrypt */

    ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0,
                   "mpegts: write %uz encrypted bytes", in_size);

    out = buf;
    out_size = sizeof(buf);

    if (file->size > 0 && file->size + in_size >= 16) {
        ngx_memcpy(file->buf + file->size, in, 16 - file->size);

        in += 16 - file->size;
        in_size -= 16 - file->size;

        AES_cbc_encrypt(file->buf, out, 16, &file->key, file->iv, AES_ENCRYPT);

        out += 16;
        out_size -= 16;

        file->size = 0;
    }

    for ( ;; ) {
        n = in_size & ~0x0f;

        if (n > 0) {
            if (n > out_size) {
                n = out_size;
            }

            AES_cbc_encrypt(in, out, n, &file->key, file->iv, AES_ENCRYPT);

            in += n;
            in_size -= n;

        } else if (out == buf) {
            break;
        }

        rc = ngx_write_fd(file->fd, buf, out - buf + n);
        if (rc < 0) {
            return NGX_ERROR;
        }

        out = buf;
        out_size = sizeof(buf);
    }

    if (in_size) {
        ngx_memcpy(file->buf + file->size, in, in_size);
        file->size += in_size;
    }

    return NGX_OK;
}
static void
ngx_http_groonga_logger_log(grn_ctx *ctx, grn_log_level level,
                            const char *timestamp, const char *title,
                            const char *message, const char *location,
                            void *user_data)
{
  ngx_open_file_t *file = user_data;
  const char level_marks[] = " EACewnid-";
  u_char buffer[NGX_MAX_ERROR_STR];
  u_char *last;
  size_t prefix_size;
  size_t message_size;
  size_t location_size;
  size_t postfix_size;
  size_t log_message_size;

  if (!file) {
    return;
  }

#define LOG_PREFIX_FORMAT "%s|%c|%s"
  prefix_size =
    strlen(timestamp) +
    1 /* | */ +
    1 /* %c */ +
    1 /* | */ +
    strlen(title) +
    1 /* a space */;
  message_size = strlen(message);
  if (location && *location) {
    location_size = 1 /* a space */ + strlen(location);
  } else {
    location_size = 0;
  }
  postfix_size = 1 /* \n */;
  log_message_size = prefix_size + message_size + location_size + postfix_size;

  if (log_message_size > NGX_MAX_ERROR_STR) {
    last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
                        LOG_PREFIX_FORMAT,
                        timestamp, *(level_marks + level), title);
    ngx_write_fd(file->fd, buffer, last - buffer);
    ngx_http_groonga_write_fd(file->fd,
                              buffer, NGX_MAX_ERROR_STR,
                              message, message_size);
    if (location_size > 0) {
      ngx_write_fd(file->fd, " ", 1);
      ngx_http_groonga_write_fd(file->fd,
                                buffer, NGX_MAX_ERROR_STR,
                                location, location_size);
    }
    ngx_write_fd(file->fd, "\n", 1);
  } else {
    if (location && *location) {
      last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
                          LOG_PREFIX_FORMAT " %s %s\n",
                          timestamp, *(level_marks + level), title, message,
                          location);
    } else {
      last = ngx_slprintf(buffer, buffer + NGX_MAX_ERROR_STR,
                          LOG_PREFIX_FORMAT " %s\n",
                          timestamp, *(level_marks + level), title, message);
    }
    ngx_write_fd(file->fd, buffer, last - buffer);
  }
#undef LOG_PREFIX_FORMAT
}
Exemple #27
0
ngx_int_t
ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf)
{
    char             *buf;
    off_t             size;
    size_t            len;
    ssize_t           n;
    ngx_fd_t          fd, nfd;
    ngx_int_t         rc;
    ngx_file_info_t   fi;

    rc = NGX_ERROR;
    buf = NULL;
    nfd = NGX_INVALID_FILE;

    fd = ngx_open_file(from, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);

    if (fd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", from);
        goto failed;
    }

    if (cf->size != -1) {
        size = cf->size;

    } else {
        if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_fd_info_n " \"%s\" failed", from);

            goto failed;
        }

        size = ngx_file_size(&fi);
    }

    len = cf->buf_size ? cf->buf_size : 65536;

    if ((off_t) len > size) {
        len = (size_t) size;
    }

    buf = ngx_alloc(len, cf->log);
    if (buf == NULL) {
        goto failed;
    }

    nfd = ngx_open_file(to, NGX_FILE_WRONLY, NGX_FILE_CREATE_OR_OPEN,
                        cf->access);

    if (nfd == NGX_INVALID_FILE) {
        ngx_log_error(NGX_LOG_CRIT, cf->log, ngx_errno,
                      ngx_open_file_n " \"%s\" failed", to);
        goto failed;
    }

    while (size > 0) {

        if ((off_t) len > size) {
            len = (size_t) size;
        }

        n = ngx_read_fd(fd, buf, len);

        if (n == -1) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_read_fd_n " \"%s\" failed", from);
            goto failed;
        }

        if ((size_t) n != len) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
                          ngx_read_fd_n " has read only %z of %uz from %s",
                          n, size, from);
            goto failed;
        }

        n = ngx_write_fd(nfd, buf, len);

        if (n == -1) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_write_fd_n " \"%s\" failed", to);
            goto failed;
        }

        if ((size_t) n != len) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, 0,
                          ngx_write_fd_n " has written only %z of %uz to %s",
                          n, size, to);
            goto failed;
        }

        size -= n;
    }

    if (cf->time != -1) {
        if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_set_file_time_n " \"%s\" failed", to);
            goto failed;
        }
    }

    rc = NGX_OK;

failed:

    if (nfd != NGX_INVALID_FILE) {
        if (ngx_close_file(nfd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed", to);
        }
    }

    if (fd != NGX_INVALID_FILE) {
        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed", from);
        }
    }

    if (buf) {
        ngx_free(buf);
    }

    return rc;
}
void
ngx_log_error_coreall(ngx_uint_t level, ngx_log_t *log, const char* filename, int lineno, ngx_err_t err,
    const char *fmt, va_list args)

#endif

{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list      args;
#endif
    u_char      *p, *last, *msg;
    ssize_t      n;
    ngx_uint_t   wrote_stderr, debug_connection;
    u_char       errstr[NGX_MAX_ERROR_STR];
    char filebuf[52];

    last = errstr + NGX_MAX_ERROR_STR;
    
    p = ngx_cpymem(errstr, ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);

    snprintf(filebuf, sizeof(filebuf), "[%35s, %5d][yangyazhou @@@ test]", filename, lineno);

    p = ngx_slprintf(p, last, "%s ", filebuf);  
    
    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ", ngx_log_pid, ngx_log_tid); //进程ID和线程ID(在开启线程池的时候线程ID和进程ID不同)
    
    if (log->connection) {
        p = ngx_slprintf(p, last, "*%uA ", log->connection);
    }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    wrote_stderr = 0;
    debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

    while (log) {

        if (log->writer) {
            log->writer(log, level, errstr, p - errstr);
            goto next;
        }

        if (ngx_time() == log->disk_full_time) {

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */

            goto next;
        }

        n = ngx_write_fd(log->file->fd, errstr, p - errstr); //写到log文件中

        if (n == -1 && ngx_errno == NGX_ENOSPC) {
            log->disk_full_time = ngx_time();
        }

        if (log->file->fd == ngx_stderr) {
            wrote_stderr = 1;
        }

    next:

        log = log->next;
    }

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || wrote_stderr) /* 如果满足这些条件,则不会输出打印到前台,只会写到errlog文件中 */
    {
        return;
    }

    msg -= (7 + err_levels[level].len + 3);

    (void) ngx_sprintf(msg, "nginx: [%V] ", &err_levels[level]);
    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
Exemple #29
0
void
ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err,
    const char *fmt, va_list args)

#endif
{
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list  args;
#endif
    u_char  *p, *last, *msg;
    u_char   errstr[NGX_MAX_ERROR_STR];

    if (log->file->fd == NGX_INVALID_FILE) {
        return;
    }

    last = errstr + NGX_MAX_ERROR_STR;

    p = errstr ;

    p = ngx_slprintf(p, last, " [%V] ", &err_levels[level]);

    /* pid#tid */
    p = ngx_slprintf(p, last, "%P#" NGX_TID_T_FMT ": ",
                    ngx_log_pid, ngx_log_tid);

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)

    va_start(args, fmt);
    p = ngx_vslprintf(p, last, fmt, args);
    va_end(args);

#else

    p = ngx_vslprintf(p, last, fmt, args);

#endif

    if (err) {
        p = ngx_log_errno(p, last, err);
    }

    if (level != NGX_LOG_DEBUG && log->handler) {
        p = log->handler(log, p, last - p);
    }

    if (p > last - NGX_LINEFEED_SIZE) {
        p = last - NGX_LINEFEED_SIZE;
    }

    ngx_linefeed(p);

    (void) ngx_write_fd(log->file->fd, errstr, p - errstr);

    if (!ngx_use_stderr
        || level > NGX_LOG_WARN
        || log->file->fd == ngx_stderr)
    {
        return;
    }

    msg -= (err_levels[level].len + 4);

    (void) ngx_sprintf(msg, "[%V]: ", &err_levels[level]);

    (void) ngx_write_console(ngx_stderr, msg, p - msg);
}
void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, ...){

#else

void ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, const char *fmt, va_list args){

#endif
#if (NGX_HAVE_VARIADIC_MACROS)
    va_list args;
#endif
    u_char *p,*last,*msg;
    ssize_t n;
    ngx_uint_t wrote_stderr,debug_connection;
    u_char errstr[NGX_MAX_ERROR_STR];
    last = errstr + NGX_MAX_ERROR_STR;
    //it seems do not set the ngx_cached_err_log_time.len value
    p = ngx_cpymem(errstr,ngx_cached_err_log_time.data,
                   ngx_cached_err_log_time.len);
    p = ngx_slprintf(p,last,"[%V]",&err_levels[level]);
   //just for making the datastructure can work correctly,comment the next function
    /* pid#tid */
    // p = ngx_slprintf(p,last,"%P#" NGX_TID_T_FMT ": ",
    // ngx_log_pid,ngx_log_tid);
    if (log->connection) {
        p = ngx_slprintf(p,last,"*%uA ",log->connection);
   }

    msg = p;

#if (NGX_HAVE_VARIADIC_MACROS)
    va_start (args,fmt);
    p = ngx_vslprintf(p,last,fmt,args);
    va_end (args);

#else
    p = ngx_vslprintf(p,last,fmt,args);
#endif

    if (err) {
        p = ngx_log_errno(p,last,err);
    }

   if (level != NGX_LOG_DEBUG && log->handler){
       p = log->handler(log,p,last  - p);
   }

   if (p > last - NGX_LINEFEED_SIZE){
       p = last - NGX_LINEFEED_SIZE;
   }

   ngx_linefeed(p);

   wrote_stderr = 0;
   debug_connection = (log->log_level & NGX_LOG_DEBUG_CONNECTION) != 0;

   while(log){
       if (log->log_level < level && !debug_connection){
           break;
       }

      if(log->writer){
          log->writer(log,level,errstr,p - errstr);
          goto next;
      }

      if (ngx_time() == log->disk_full_time){

            /*
             * on FreeBSD writing to a full filesystem with enabled softupdates
             * may block process for much longer time than writing to non-full
             * filesystem, so we skip writing to a log for one second
             */
          goto next;
      }
      n = ngx_write_fd(log->file->fd,errstr,p - errstr);

      if (n == -1 && ngx_errno == NGX_ENOSPC){
          log->disk_full_time = ngx_time();
      }

      if (log->file->fd == ngx_stderr){
          wrote_stderr = 1;
      }
next:

      log = log->next;
   }

   if (!ngx_use_stderr || level > NGX_LOG_WARN || wrote_stderr){
       return;
   }

   msg -= (7 + err_levels[level].len + 3);

   (void)ngx_sprintf(msg,"nginx: [%V]",&err_levels[level]);

   (void) ngx_write_console(ngx_stderr,msg,p - msg);
}