X-Git-Url: http://sjero.net/git/?a=blobdiff_plain;f=src%2Futils.c;h=faae62e1b334b93422dd0fa2f5fb8f1880b99e79;hb=b1838bdfd197ec970d834ce5042995df92516841;hp=634e41ffec0b3b296be0c039957cebd79c84cc03;hpb=179dacd7350cef30f0de730cc54647baaf95a6c3;p=wget diff --git a/src/utils.c b/src/utils.c index 634e41ff..faae62e1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -42,22 +42,29 @@ as that of the covered work. */ #ifdef HAVE_PROCESS_H # include /* getpid() */ #endif -#ifdef HAVE_UTIME_H -# include -#endif #include #include #include #include #include +#if HAVE_UTIME +# include +# ifdef HAVE_UTIME_H +# include +# endif + +# ifdef HAVE_SYS_UTIME_H +# include +# endif +#endif + #include +#include /* For TIOCGWINSZ and friends: */ -#ifdef HAVE_SYS_IOCTL_H -# include -#endif +#include #ifdef HAVE_TERMIOS_H # include #endif @@ -66,6 +73,11 @@ as that of the covered work. */ #include #include +#include +#ifdef HAVE_LIBPCRE +# include +#endif + #ifndef HAVE_SIGSETJMP /* If sigsetjmp is a macro, configure won't pick it up. */ # ifdef sigsetjmp @@ -488,15 +500,40 @@ fork_to_background (void) void touch (const char *file, time_t tm) { - struct timeval timevals[2]; +#if HAVE_UTIME +# ifdef HAVE_STRUCT_UTIMBUF + struct utimbuf times; +# else + struct { + time_t actime; + time_t modtime; + } times; +# endif + times.modtime = tm; + times.actime = time (NULL); + if (utime (file, ×) == -1) + logprintf (LOG_NOTQUIET, "utime(%s): %s\n", file, strerror (errno)); +#else + struct timespec timespecs[2]; + int fd; + + fd = open (file, O_WRONLY); + if (fd < 0) + { + logprintf (LOG_NOTQUIET, "open(%s): %s\n", file, strerror (errno)); + return; + } + + timespecs[0].tv_sec = time (NULL); + timespecs[0].tv_nsec = 0L; + timespecs[1].tv_sec = tm; + timespecs[1].tv_nsec = 0L; - timevals[0].tv_sec = time (NULL); - timevals[0].tv_usec = 0L; - timevals[1].tv_sec = tm; - timevals[1].tv_usec = 0L; + if (futimens (fd, timespecs) == -1) + logprintf (LOG_NOTQUIET, "futimens(%s): %s\n", file, strerror (errno)); - if (utimes (file, timevals) == -1) - logprintf (LOG_NOTQUIET, "utimes(%s): %s\n", file, strerror (errno)); + close (fd); +#endif } /* Checks if FILE is a symbolic link, and removes it if it is. Does @@ -737,8 +774,7 @@ fopen_excl (const char *fname, int binary) open_id = 13; fd = open( fname, /* File name. */ flags, /* Flags. */ - 0777, /* Mode for default protection. -*/ + 0777, /* Mode for default protection. */ "rfm=stmlf", /* Stream_LF. */ OPEN_OPT_ARGS); /* Access callback. */ } @@ -866,6 +902,9 @@ acceptable (const char *s) { int l = strlen (s); + if (opt.output_document && strcmp (s, opt.output_document) == 0) + return true; + while (l && s[l] != '/') --l; if (s[l] == '/') @@ -883,6 +922,19 @@ acceptable (const char *s) return true; } +/* Determine whether an URL is acceptable to be followed, according to + regex patterns to accept/reject. */ +bool +accept_url (const char *s) +{ + if (opt.acceptregex && !opt.regex_match_fun (opt.acceptregex, s)) + return false; + if (opt.rejectregex && opt.regex_match_fun (opt.rejectregex, s)) + return false; + + return true; +} + /* Check if D2 is a subdirectory of D1. E.g. if D1 is `/something', subdir_p() will return true if and only if D2 begins with `/something/' or is exactly '/something'. */ @@ -1791,6 +1843,17 @@ number_to_static_string (wgint number) ringpos = (ringpos + 1) % RING_SIZE; return buf; } + +/* Converts the byte to bits format if --report-bps option is enabled + */ +wgint +convert_to_bits (wgint num) +{ + if (opt.report_bps) + return num * 8; + return num; +} + /* Determine the width of the terminal we're running on. If that's not possible, return 0. */ @@ -1918,9 +1981,10 @@ abort_run_with_timeout (int sig) /* We don't have siglongjmp to preserve the set of blocked signals; if we longjumped out of the handler at this point, SIGALRM would remain blocked. We must unblock it manually. */ - int mask = siggetmask (); - mask &= ~sigmask (SIGALRM); - sigsetmask (mask); + sigset_t set; + sigemptyset (&set); + sigaddset (&set, SIGALRM); + sigprocmask (SIG_BLOCK, &set, NULL); /* Now it's safe to longjump. */ longjmp (run_with_timeout_env, -1); @@ -2263,6 +2327,89 @@ base64_decode (const char *base64, void *dest) return q - (char *) dest; } +#ifdef HAVE_LIBPCRE +/* Compiles the PCRE regex. */ +void * +compile_pcre_regex (const char *str) +{ + const char *errbuf; + int erroffset; + pcre *regex = pcre_compile (str, 0, &errbuf, &erroffset, 0); + if (! regex) + { + fprintf (stderr, _("Invalid regular expression %s, %s\n"), + quote (str), errbuf); + return false; + } + return regex; +} +#endif + +/* Compiles the POSIX regex. */ +void * +compile_posix_regex (const char *str) +{ + regex_t *regex = xmalloc (sizeof (regex_t)); + int errcode = regcomp ((regex_t *) regex, str, REG_EXTENDED | REG_NOSUB); + if (errcode != 0) + { + int errbuf_size = regerror (errcode, (regex_t *) regex, NULL, 0); + char *errbuf = xmalloc (errbuf_size); + regerror (errcode, (regex_t *) regex, errbuf, errbuf_size); + fprintf (stderr, _("Invalid regular expression %s, %s\n"), + quote (str), errbuf); + xfree (errbuf); + return NULL; + } + + return regex; +} + +#ifdef HAVE_LIBPCRE +#define OVECCOUNT 30 +/* Matches a PCRE regex. */ +bool +match_pcre_regex (const void *regex, const char *str) +{ + int l = strlen (str); + int ovector[OVECCOUNT]; + + int rc = pcre_exec ((pcre *) regex, 0, str, l, 0, 0, ovector, OVECCOUNT); + if (rc == PCRE_ERROR_NOMATCH) + return false; + else if (rc < 0) + { + logprintf (LOG_VERBOSE, _("Error while matching %s: %d\n"), + quote (str), rc); + return false; + } + else + return true; +} +#undef OVECCOUNT +#endif + +/* Matches a POSIX regex. */ +bool +match_posix_regex (const void *regex, const char *str) +{ + int rc = regexec ((regex_t *) regex, str, 0, NULL, 0); + if (rc == REG_NOMATCH) + return false; + else if (rc == 0) + return true; + else + { + int errbuf_size = regerror (rc, opt.acceptregex, NULL, 0); + char *errbuf = xmalloc (errbuf_size); + regerror (rc, opt.acceptregex, errbuf, errbuf_size); + logprintf (LOG_VERBOSE, _("Error while matching %s: %d\n"), + quote (str), rc); + xfree (errbuf); + return false; + } +} + #undef IS_ASCII #undef NEXT_CHAR @@ -2347,6 +2494,60 @@ print_decimal (double number) return buf; } +/* Get the maximum name length for the given path. */ +/* Return 0 if length is unknown. */ +size_t +get_max_length (const char *path, int length, int name) +{ + long ret; + char *p, *d; + + /* Make a copy of the path that we can modify. */ + p = path ? strdupdelim (path, path + length) : strdup (""); + + for (;;) + { + errno = 0; + /* For an empty path query the current directory. */ +#if HAVE_PATHCONF + ret = pathconf (*p ? p : ".", name); + if (!(ret < 0 && errno == ENOENT)) + break; +#else + ret = PATH_MAX; +#endif + + /* The path does not exist yet, but may be created. */ + /* Already at current or root directory, give up. */ + if (!*p || strcmp (p, "/") == 0) + break; + + /* Remove one directory level and try again. */ + d = strrchr (p, '/'); + if (d == p) + p[1] = '\0'; /* check root directory */ + else if (d) + *d = '\0'; /* remove last directory part */ + else + *p = '\0'; /* check current directory */ + } + + xfree (p); + + if (ret < 0) + { + /* pathconf() has a message for us. */ + if (errno != 0) + perror ("pathconf"); + + /* If (errno == 0) then there is no max length. + Even on error return 0 so the caller can continue. */ + return 0; + } + + return ret; +} + #ifdef TESTING const char *