X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=lib.c;h=d07878ae3bb7c303fda5284816b65793fce7836a;hp=e683c6d37b73241feec307097b103bdcd914e674;hb=7b8296cfa5c33fbc73c34c4fe1ff6d7bfbaaba01;hpb=8e037c67a88cb4680c4391134c578e3b55a80f8a diff --git a/lib.c b/lib.c index e683c6d..d07878a 100644 --- a/lib.c +++ b/lib.c @@ -34,15 +34,13 @@ #define EX_OK 0 #endif +#include #include +#include +#include #include "lib.h" -#include "lib/mem.h" -#include "lib/str.h" -#include "lib/debug.h" - -extern short Umask; static struct sysexits { @@ -110,392 +108,6 @@ void mutt_nocurses_error (const char *fmt, ...) fputc ('\n', stderr); } -int safe_fclose (FILE ** f) -{ - int r = 0; - - if (*f) - r = fclose (*f); - - *f = NULL; - return r; -} - -void mutt_unlink (const char *s) -{ - int fd; - int flags; - FILE *f; - struct stat sb, sb2; - char buf[2048]; - - /* Defend against symlink attacks */ - -#ifdef O_NOFOLLOW - flags = O_RDWR | O_NOFOLLOW; -#else - flags = O_RDWR; -#endif - - if (lstat (s, &sb) == 0 && S_ISREG (sb.st_mode)) { - if ((fd = open (s, flags)) < 0) - return; - - if ((fstat (fd, &sb2) != 0) || !S_ISREG (sb2.st_mode) - || (sb.st_dev != sb2.st_dev) || (sb.st_ino != sb2.st_ino)) { - close (fd); - return; - } - - if ((f = fdopen (fd, "r+"))) { - unlink (s); - memset (buf, 0, sizeof (buf)); - while (sb.st_size > 0) { - fwrite (buf, 1, MIN (sizeof (buf), sb.st_size), f); - sb.st_size -= MIN (sizeof (buf), sb.st_size); - } - fclose (f); - } - } -} - -int mutt_copy_bytes (FILE * in, FILE * out, size_t size) -{ - char buf[2048]; - size_t chunk; - - while (size > 0) { - chunk = (size > sizeof (buf)) ? sizeof (buf) : size; - if ((chunk = fread (buf, 1, chunk, in)) < 1) - break; - if (fwrite (buf, 1, chunk, out) != chunk) { - debug_print (1, ("fwrite() returned short byte count\n")); - return (-1); - } - size -= chunk; - } - - return 0; -} - -int mutt_copy_stream (FILE * fin, FILE * fout) -{ - size_t l; - char buf[LONG_STRING]; - - while ((l = fread (buf, 1, sizeof (buf), fin)) > 0) { - if (fwrite (buf, 1, l, fout) != l) - return (-1); - } - - return 0; -} - -static int compare_stat (struct stat *osb, struct stat *nsb) -{ - if (osb->st_dev != nsb->st_dev || osb->st_ino != nsb->st_ino || - osb->st_rdev != nsb->st_rdev) { - return -1; - } - - return 0; -} - -int safe_symlink (const char *oldpath, const char *newpath) -{ - struct stat osb, nsb; - - if (!oldpath || !newpath) - return -1; - - if (unlink (newpath) == -1 && errno != ENOENT) - return -1; - - if (oldpath[0] == '/') { - if (symlink (oldpath, newpath) == -1) - return -1; - } - else { - char abs_oldpath[_POSIX_PATH_MAX]; - - if ((getcwd (abs_oldpath, sizeof abs_oldpath) == NULL) || - (str_len (abs_oldpath) + 1 + str_len (oldpath) + 1 > - sizeof abs_oldpath)) - return -1; - - strcat (abs_oldpath, "/"); /* __STRCAT_CHECKED__ */ - strcat (abs_oldpath, oldpath); /* __STRCAT_CHECKED__ */ - if (symlink (abs_oldpath, newpath) == -1) - return -1; - } - - if (stat (oldpath, &osb) == -1 || stat (newpath, &nsb) == -1 - || compare_stat (&osb, &nsb) == -1) { - unlink (newpath); - return -1; - } - - return 0; -} - -/* - * This function is supposed to do nfs-safe renaming of files. - * - * Warning: We don't check whether src and target are equal. - */ - -int safe_rename (const char *src, const char *target) -{ - struct stat ssb, tsb; - - if (!src || !target) - return -1; - - if (link (src, target) != 0) { - - /* - * Coda does not allow cross-directory links, but tells - * us it's a cross-filesystem linking attempt. - * - * However, the Coda rename call is allegedly safe to use. - * - * With other file systems, rename should just fail when - * the files reside on different file systems, so it's safe - * to try it here. - * - */ - - if (errno == EXDEV) - return rename (src, target); - - return -1; - } - - /* - * Stat both links and check if they are equal. - */ - - if (stat (src, &ssb) == -1) { - return -1; - } - - if (stat (target, &tsb) == -1) { - return -1; - } - - /* - * pretend that the link failed because the target file - * did already exist. - */ - - if (compare_stat (&ssb, &tsb) == -1) { - errno = EEXIST; - return -1; - } - - /* - * Unlink the original link. Should we really ignore the return - * value here? XXX - */ - - unlink (src); - - return 0; -} - -int safe_open (const char *path, int flags) -{ - struct stat osb, nsb; - int fd; - - umask (Umask); - if ((fd = open (path, flags, 0666)) < 0) - return fd; - - /* make sure the file is not symlink */ - if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || - compare_stat (&osb, &nsb) == -1) { - debug_print (1, ("%s is a symlink!\n", path)); - close (fd); - return (-1); - } - - return (fd); -} - -/* when opening files for writing, make sure the file doesn't already exist - * to avoid race conditions. - */ -FILE *safe_fopen (const char *path, const char *mode) -{ - /* first set the current umask */ - umask (Umask); - if (mode[0] == 'w') { - int fd; - int flags = O_CREAT | O_EXCL; - -#ifdef O_NOFOLLOW - flags |= O_NOFOLLOW; -#endif - - if (mode[1] == '+') - flags |= O_RDWR; - else - flags |= O_WRONLY; - - if ((fd = safe_open (path, flags)) < 0) - return (NULL); - - return (fdopen (fd, mode)); - } - else - return (fopen (path, mode)); -} - -static char safe_chars[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%/"; - -void mutt_sanitize_filename (char *f, short slash) -{ - if (!f) - return; - - for (; *f; f++) { - if ((slash && *f == '/') || !strchr (safe_chars, *f)) - *f = '_'; - } -} - -/* these characters must be escaped in regular expressions */ - -static char rx_special_chars[] = "^.[$()|*+?{\\"; - -int mutt_rx_sanitize_string (char *dest, size_t destlen, const char *src) -{ - while (*src && --destlen > 2) { - if (strchr (rx_special_chars, *src)) { - *dest++ = '\\'; - destlen--; - } - *dest++ = *src++; - } - - *dest = '\0'; - - if (*src) - return -1; - else - return 0; -} - -/* Read a line from ``fp'' into the dynamically allocated ``s'', - * increasing ``s'' if necessary. The ending "\n" or "\r\n" is removed. - * If a line ends with "\", this char and the linefeed is removed, - * and the next line is read too. - */ -char *mutt_read_line(char *s, size_t * size, FILE * fp, int *line) -{ - size_t offset = 0; - char *ch; - - if (!s) { - s = p_new(char, STRING); - *size = STRING; - } - - FOREVER { - if (fgets (s + offset, *size - offset, fp) == NULL) { - p_delete(&s); - return NULL; - } - if ((ch = strchr (s + offset, '\n')) != NULL) { - (*line)++; - *ch = 0; - if (ch > s && *(ch - 1) == '\r') - *--ch = 0; - if (ch == s || *(ch - 1) != '\\') - return s; - offset = ch - s - 1; - } - else { - int c; - - c = getc (fp); /* This is kind of a hack. We want to know if the - char at the current point in the input stream is EOF. - feof() will only tell us if we've already hit EOF, not - if the next character is EOF. So, we need to read in - the next character and manually check if it is EOF. */ - if (c == EOF) { - /* The last line of fp isn't \n terminated */ - (*line)++; - return s; - } - else { - ungetc (c, fp); /* undo our dammage */ - /* There wasn't room for the line -- increase ``s'' */ - offset = *size - 1; /* overwrite the terminating 0 */ - *size += STRING; - mem_realloc (&s, *size); - } - } - } -} - -/* prepare a file name to survive the shell's quoting rules. - * From the Unix programming FAQ by way of Liviu. - */ - -size_t mutt_quote_filename (char *d, size_t l, const char *f) -{ - size_t i, j = 0; - - if (!f) { - *d = '\0'; - return 0; - } - - /* leave some space for the trailing characters. */ - l -= 6; - - d[j++] = '\''; - - for (i = 0; j < l && f[i]; i++) { - if (f[i] == '\'' || f[i] == '`') { - d[j++] = '\''; - d[j++] = '\\'; - d[j++] = f[i]; - d[j++] = '\''; - } - else - d[j++] = f[i]; - } - - d[j++] = '\''; - d[j] = '\0'; - - return j; -} - -char *mutt_concat_path (char *d, const char *dir, const char *fname, size_t l) -{ - const char *fmt = "%s/%s"; - - if (!*fname || (*dir && dir[str_len (dir) - 1] == '/')) - fmt = "%s%s"; - - snprintf (d, l, fmt, dir, fname); - return d; -} - -const char *mutt_basename (const char *f) -{ - const char *p = strrchr (f, '/'); - - if (p) - return p + 1; - else - return f; -} const char * mutt_strsysexit(int e)