X-Git-Url: http://git.madism.org/?p=apps%2Fmadmutt.git;a=blobdiff_plain;f=dotlock.c;h=abf92f0f341ba912c76741f119f3b035122704d5;hp=eb799d596fabf0569db05fd2a57be4e241bbfb75;hb=68edc972742930c4003e554144bfe197ba6199aa;hpb=6833ce8bdca2d64e14485118f2a4417b7e1cb1b1 diff --git a/dotlock.c b/dotlock.c index eb799d5..abf92f0 100644 --- a/dotlock.c +++ b/dotlock.c @@ -1,67 +1,27 @@ /* + * Copyright notice from original mutt: * Copyright (C) 1996-2000 Michael R. Elkins * Copyright (C) 1998-2000 Thomas Roessler - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - */ - -/* - * This module either be compiled into Mutt, or it can be - * built as a separate program. For building it - * separately, define the DL_STANDALONE preprocessor - * macro. + * + * This file is part of mutt-ng, see http://www.muttng.org/. + * It's licensed under the GNU General Public License, + * please see the file GPL in the top level source directory. */ -#include -#include -#include +#include -#include -#include -#include -#include #include -#include -#include -#include -#include - -#ifndef _POSIX_PATH_MAX -#include -#endif - #include "dotlock.h" -#include "config.h" #ifdef HAVE_GETOPT_H #include #endif -#ifdef DL_STANDALONE -# include "reldate.h" -#endif - -#define MAXLINKS 1024 /* maximum link depth */ - -#ifdef DL_STANDALONE +#define MAXLINKS 1024 /* maximum link depth */ # define LONG_STRING 1024 # define MAXLOCKATTEMPT 5 -# define strfcpy(A,B,C) strncpy (A,B,C), *(A+(C)-1)=0 - # ifdef USE_SETGID # ifdef HAVE_SETEGID @@ -75,27 +35,10 @@ # endif -# ifndef HAVE_SNPRINTF -extern int snprintf (char *, size_t, const char *, ...); -# endif - -#else /* DL_STANDALONE */ - -# ifdef USE_SETGID -# error Do not try to compile dotlock as a mutt module when requiring egid switching! -# endif - -# include "mutt.h" -# include "mx.h" - -#endif /* DL_STANDALONE */ - static int DotlockFlags; static int Retry = MAXLOCKATTEMPT; -#ifdef DL_STANDALONE static char *Hostname; -#endif #ifdef USE_SETGID static gid_t UserGid; @@ -103,14 +46,12 @@ static gid_t MailGid; #endif static int dotlock_deference_symlink (char *, size_t, const char *); -static int dotlock_prepare (char *, size_t, const char *, int fd); +static int dotlock_prepare (char *, ssize_t, const char *, int fd); static int dotlock_check_stats (struct stat *, struct stat *); static int dotlock_dispatch (const char *, int fd); -#ifdef DL_STANDALONE static int dotlock_init_privs (void); static void usage (const char *); -#endif static void dotlock_expand_link (char *, const char *, const char *); static void BEGIN_PRIVILEGED (void); @@ -127,8 +68,6 @@ static int dotlock_unlink (const char *); static int dotlock_lock (const char *); -#ifdef DL_STANDALONE - #define check_flags(a) if (a & DL_FL_ACTIONS) usage (argv[0]) int main (int argc, char **argv) @@ -138,15 +77,15 @@ int main (int argc, char **argv) struct utsname utsname; /* first, drop privileges */ - + if (dotlock_init_privs () == -1) return DL_EX_ERROR; /* determine the system's host name */ - + uname (&utsname); - if (!(Hostname = strdup (utsname.nodename))) /* __MEM_CHECKED__ */ + if (!(Hostname = strdup (utsname.nodename))) /* __MEM_CHECKED__ */ return DL_EX_ERROR; if ((p = strchr (Hostname, '.'))) *p = '\0'; @@ -154,22 +93,37 @@ int main (int argc, char **argv) /* parse the command line options. */ DotlockFlags = 0; - - while ((i = getopt (argc, argv, "dtfupr:")) != EOF) - { - switch (i) - { + + while ((i = getopt (argc, argv, "dtfupr:")) != EOF) { + switch (i) { /* actions, mutually exclusive */ - case 't': check_flags (DotlockFlags); DotlockFlags |= DL_FL_TRY; break; - case 'd': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLINK; break; - case 'u': check_flags (DotlockFlags); DotlockFlags |= DL_FL_UNLOCK; break; + case 't': + check_flags (DotlockFlags); + DotlockFlags |= DL_FL_TRY; + break; + case 'd': + check_flags (DotlockFlags); + DotlockFlags |= DL_FL_UNLINK; + break; + case 'u': + check_flags (DotlockFlags); + DotlockFlags |= DL_FL_UNLOCK; + break; /* other flags */ - case 'f': DotlockFlags |= DL_FL_FORCE; break; - case 'p': DotlockFlags |= DL_FL_USEPRIV; break; - case 'r': DotlockFlags |= DL_FL_RETRY; Retry = atoi (optarg); break; - - default: usage (argv[0]); + case 'f': + DotlockFlags |= DL_FL_FORCE; + break; + case 'p': + DotlockFlags |= DL_FL_USEPRIV; + break; + case 'r': + DotlockFlags |= DL_FL_RETRY; + Retry = atoi (optarg); + break; + + default: + usage (argv[0]); } } @@ -192,12 +146,11 @@ int main (int argc, char **argv) */ -static int -dotlock_init_privs (void) +static int dotlock_init_privs (void) { # ifdef USE_SETGID - + UserGid = getgid (); MailGid = getegid (); @@ -208,44 +161,11 @@ dotlock_init_privs (void) return 0; } - - -#else /* DL_STANDALONE */ - -/* - * This function is intended to be invoked from within - * mutt instead of mx.c's invoke_dotlock (). - */ - -int dotlock_invoke (const char *path, int fd, int flags, int retry) -{ - int currdir; - int r; - - DotlockFlags = flags; - - if ((currdir = open (".", O_RDONLY)) == -1) - return DL_EX_ERROR; - - if (!(DotlockFlags & DL_FL_RETRY) || retry) - Retry = MAXLOCKATTEMPT; - else - Retry = 0; - - r = dotlock_dispatch (path, fd); - - fchdir (currdir); - close (currdir); - - return r; -} - -#endif /* DL_STANDALONE */ static int dotlock_dispatch (const char *f, int fd) { - char realpath[_POSIX_PATH_MAX]; + char frealpath[_POSIX_PATH_MAX]; /* If dotlock_prepare () succeeds [return value == 0], * realpath contains the basename of f, and we have @@ -258,7 +178,7 @@ static int dotlock_dispatch (const char *f, int fd) * lengthy comment below. */ - if (dotlock_prepare (realpath, sizeof (realpath), f, fd) != 0) + if (dotlock_prepare (frealpath, sizeof (frealpath), f, fd) != 0) return DL_EX_ERROR; /* Actually perform the locking operation. */ @@ -266,14 +186,14 @@ static int dotlock_dispatch (const char *f, int fd) if (DotlockFlags & DL_FL_TRY) return dotlock_try (); else if (DotlockFlags & DL_FL_UNLOCK) - return dotlock_unlock (realpath); + return dotlock_unlock (frealpath); else if (DotlockFlags & DL_FL_UNLINK) - return dotlock_unlink (realpath); - else /* lock */ - return dotlock_lock (realpath); + return dotlock_unlink (frealpath); + else /* lock */ + return dotlock_lock (frealpath); } - + /* * Get privileges * @@ -285,14 +205,11 @@ static int dotlock_dispatch (const char *f, int fd) * */ -static void -BEGIN_PRIVILEGED (void) +static void BEGIN_PRIVILEGED (void) { #ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (MailGid) != 0) - { + if (DotlockFlags & DL_FL_USEPRIV) { + if (SETEGID (MailGid) != 0) { /* perror ("setegid"); */ exit (DL_EX_ERROR); } @@ -309,14 +226,11 @@ BEGIN_PRIVILEGED (void) * */ -static void -END_PRIVILEGED (void) +static void END_PRIVILEGED (void) { #ifdef USE_SETGID - if (DotlockFlags & DL_FL_USEPRIV) - { - if (SETEGID (UserGid) != 0) - { + if (DotlockFlags & DL_FL_USEPRIV) { + if (SETEGID (UserGid) != 0) { /* perror ("setegid"); */ exit (DL_EX_ERROR); } @@ -324,8 +238,6 @@ END_PRIVILEGED (void) #endif } -#ifdef DL_STANDALONE - /* * Usage information. * @@ -333,30 +245,23 @@ END_PRIVILEGED (void) * */ -static void -usage (const char *av0) +static void usage (const char *av0) { - fprintf (stderr, "dotlock [Mutt %s (%s)]\n", VERSION, ReleaseDate); - fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r ] file\n", - av0); + fprintf (stderr, "dotlock [Madmutt %s]\n", VERSION); + fprintf (stderr, "usage: %s [-t|-f|-u|-d] [-p] [-r ] file\n", av0); fputs ("\noptions:" - "\n -t\t\ttry" - "\n -f\t\tforce" - "\n -u\t\tunlock" - "\n -d\t\tunlink" - "\n -p\t\tprivileged" + "\n -t\t\ttry" + "\n -f\t\tforce" + "\n -u\t\tunlock" "\n -d\t\tunlink" "\n -p\t\tprivileged" #ifndef USE_SETGID - " (ignored)" + " (ignored)" #endif - "\n -r \tRetry locking" - "\n", stderr); - + "\n -r \tRetry locking" "\n", stderr); + exit (DL_EX_ERROR); } -#endif - /* * Access checking: Let's avoid to lock other users' mail * spool files if we aren't permitted to read them. @@ -405,8 +310,7 @@ usage (const char *av0) * tlr, Jul 15 1998 */ -static int -dotlock_check_stats (struct stat *fsb, struct stat *lsb) +static int dotlock_check_stats (struct stat *fsb, struct stat *lsb) { /* S_ISLNK (fsb->st_mode) should actually be impossible, * but we may have mixed up the parameters somewhere. @@ -415,70 +319,65 @@ dotlock_check_stats (struct stat *fsb, struct stat *lsb) if (S_ISLNK (lsb->st_mode) || S_ISLNK (fsb->st_mode)) return -1; - + if ((lsb->st_dev != fsb->st_dev) || - (lsb->st_ino != fsb->st_ino) || - (lsb->st_mode != fsb->st_mode) || - (lsb->st_nlink != fsb->st_nlink) || - (lsb->st_uid != fsb->st_uid) || - (lsb->st_gid != fsb->st_gid) || - (lsb->st_rdev != fsb->st_rdev) || - (lsb->st_size != fsb->st_size)) - { + (lsb->st_ino != fsb->st_ino) || + (lsb->st_mode != fsb->st_mode) || + (lsb->st_nlink != fsb->st_nlink) || + (lsb->st_uid != fsb->st_uid) || + (lsb->st_gid != fsb->st_gid) || + (lsb->st_rdev != fsb->st_rdev) || (lsb->st_size != fsb->st_size)) { /* something's fishy */ return -1; } - + return 0; } -static int -dotlock_prepare (char *bn, size_t l, const char *f, int _fd) +static int dotlock_prepare (char *bn, ssize_t l, const char *f, int _fd) { struct stat fsb, lsb; - char realpath[_POSIX_PATH_MAX]; - char *basename, *dirname; + char frealpath[_POSIX_PATH_MAX]; + char *fbasename, *dirname; char *p; int fd; int r; - - if (dotlock_deference_symlink (realpath, sizeof (realpath), f) == -1) + + if (dotlock_deference_symlink (frealpath, sizeof (frealpath), f) == -1) return -1; - - if ((p = strrchr (realpath, '/'))) - { + + if ((p = strrchr (frealpath, '/'))) { *p = '\0'; - basename = p + 1; - dirname = realpath; + fbasename = p + 1; + dirname = frealpath; } - else - { - basename = realpath; - dirname = "."; + else { + fbasename = frealpath; + dirname = m_strdup("."); } - if (strlen (basename) + 1 > l) + if (m_strlen(fbasename) + 1 > l) return -1; - - strfcpy (bn, basename, l); - + + m_strcpy(bn, l, fbasename); + if (chdir (dirname) == -1) return -1; if (_fd != -1) fd = _fd; - else if ((fd = open (basename, O_RDONLY)) == -1) + else if ((fd = open (fbasename, O_RDONLY)) == -1) return -1; - + r = fstat (fd, &fsb); - + if (_fd == -1) close (fd); - + if (r == -1) return -1; - - if (lstat (basename, &lsb) == -1) + + if (lstat (fbasename, &lsb) == -1) return -1; if (dotlock_check_stats (&fsb, &lsb) == -1) @@ -495,29 +394,27 @@ dotlock_prepare (char *bn, size_t l, const char *f, int _fd) * */ -static void -dotlock_expand_link (char *newpath, const char *path, const char *link) +static void +dotlock_expand_link (char *newpath, const char *path, const char *flink) { const char *lb = NULL; size_t len; /* link is full path */ - if (*link == '/') - { - strfcpy (newpath, link, _POSIX_PATH_MAX); + if (*flink == '/') { + m_strcpy(newpath, _POSIX_PATH_MAX, flink); return; } - if ((lb = strrchr (path, '/')) == NULL) - { + if ((lb = strrchr (path, '/')) == NULL) { /* no path in link */ - strfcpy (newpath, link, _POSIX_PATH_MAX); + m_strcpy(newpath, _POSIX_PATH_MAX, flink); return; } len = lb - path + 1; memcpy (newpath, path, len); - strfcpy (newpath + len, link, _POSIX_PATH_MAX - len); + m_strcpy(newpath + len, _POSIX_PATH_MAX - len, flink); } @@ -528,44 +425,39 @@ dotlock_expand_link (char *newpath, const char *path, const char *link) * */ -static int -dotlock_deference_symlink (char *d, size_t l, const char *path) +static int dotlock_deference_symlink (char *d, size_t l, const char *path) { struct stat sb; - char realpath[_POSIX_PATH_MAX]; + char frealpath[_POSIX_PATH_MAX]; const char *pathptr = path; int count = 0; - - while (count++ < MAXLINKS) - { - if (lstat (pathptr, &sb) == -1) - { + + while (count++ < MAXLINKS) { + if (lstat (pathptr, &sb) == -1) { /* perror (pathptr); */ return -1; } - - if (S_ISLNK (sb.st_mode)) - { + + if (S_ISLNK (sb.st_mode)) { char linkfile[_POSIX_PATH_MAX]; char linkpath[_POSIX_PATH_MAX]; int len; - if ((len = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) - { - /* perror (pathptr); */ - return -1; + if ((len = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) { + /* perror (pathptr); */ + return -1; } - + linkfile[len] = '\0'; dotlock_expand_link (linkpath, pathptr, linkfile); - strfcpy (realpath, linkpath, sizeof (realpath)); - pathptr = realpath; + m_strcpy(frealpath, sizeof(frealpath), linkpath); + pathptr = frealpath; } else break; } - strfcpy (d, pathptr, l); + m_strcpy(d, l, pathptr); return 0; } @@ -580,56 +472,51 @@ dotlock_deference_symlink (char *d, size_t l, const char *path) #define HARDMAXATTEMPTS 10 -static int -dotlock_lock (const char *realpath) +static int dotlock_lock (const char *frealpath) { char lockfile[_POSIX_PATH_MAX + LONG_STRING]; char nfslockfile[_POSIX_PATH_MAX + LONG_STRING]; - size_t prev_size = 0; + ssize_t prev_size = 0; int fd; int count = 0; int hard_count = 0; struct stat sb; time_t t; - + snprintf (nfslockfile, sizeof (nfslockfile), "%s.%s.%d", - realpath, Hostname, (int) getpid ()); - snprintf (lockfile, sizeof (lockfile), "%s.lock", realpath); + frealpath, Hostname, (int) getpid ()); + snprintf (lockfile, sizeof (lockfile), "%s.lock", frealpath); + - BEGIN_PRIVILEGED (); unlink (nfslockfile); - while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) - { + while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) { END_PRIVILEGED (); - - if (errno != EAGAIN) - { + + if (errno != EAGAIN) { /* perror ("cannot open NFS lock file"); */ return DL_EX_ERROR; } - + BEGIN_PRIVILEGED (); } END_PRIVILEGED (); - + close (fd); - - while (hard_count++ < HARDMAXATTEMPTS) - { + + while (hard_count++ < HARDMAXATTEMPTS) { BEGIN_PRIVILEGED (); link (nfslockfile, lockfile); END_PRIVILEGED (); - if (stat (nfslockfile, &sb) != 0) - { + if (stat (nfslockfile, &sb) != 0) { /* perror ("stat"); */ return DL_EX_ERROR; } @@ -640,32 +527,29 @@ dotlock_lock (const char *realpath) if (count == 0) prev_size = sb.st_size; - if (prev_size == sb.st_size && ++count > Retry) - { - if (DotlockFlags & DL_FL_FORCE) - { - BEGIN_PRIVILEGED (); - unlink (lockfile); - END_PRIVILEGED (); + if (prev_size == sb.st_size && ++count > Retry) { + if (DotlockFlags & DL_FL_FORCE) { + BEGIN_PRIVILEGED (); + unlink (lockfile); + END_PRIVILEGED (); - count = 0; - continue; + count = 0; + continue; } - else - { - BEGIN_PRIVILEGED (); - unlink (nfslockfile); - END_PRIVILEGED (); - return DL_EX_EXIST; + else { + BEGIN_PRIVILEGED (); + unlink (nfslockfile); + END_PRIVILEGED (); + return DL_EX_EXIST; } } - + prev_size = sb.st_size; - + /* don't trust sleep (3) as it may be interrupted * by users sending signals. */ - + t = time (NULL); do { sleep (1); @@ -687,42 +571,39 @@ dotlock_lock (const char *realpath) * */ -static int -dotlock_unlock (const char *realpath) +static int dotlock_unlock (const char *frealpath) { char lockfile[_POSIX_PATH_MAX + LONG_STRING]; int i; - snprintf (lockfile, sizeof (lockfile), "%s.lock", - realpath); - + snprintf (lockfile, sizeof (lockfile), "%s.lock", frealpath); + BEGIN_PRIVILEGED (); i = unlink (lockfile); END_PRIVILEGED (); - + if (i == -1) return DL_EX_ERROR; - + return DL_EX_OK; } /* remove an empty file */ -static int -dotlock_unlink (const char *realpath) +static int dotlock_unlink (const char *frealpath) { struct stat lsb; int i = -1; - if (dotlock_lock (realpath) != DL_EX_OK) + if (dotlock_lock (frealpath) != DL_EX_OK) return DL_EX_ERROR; - if ((i = lstat (realpath, &lsb)) == 0 && lsb.st_size == 0) - unlink (realpath); + if ((i = lstat (frealpath, &lsb)) == 0 && lsb.st_size == 0) + unlink (frealpath); - dotlock_unlock (realpath); + dotlock_unlock (frealpath); - return (i == 0) ? DL_EX_OK : DL_EX_ERROR; + return (i == 0) ? DL_EX_OK : DL_EX_ERROR; } @@ -733,8 +614,7 @@ dotlock_unlink (const char *realpath) * */ -static int -dotlock_try (void) +static int dotlock_try (void) { #ifdef USE_SETGID struct stat sb; @@ -744,8 +624,7 @@ dotlock_try (void) return DL_EX_OK; #ifdef USE_SETGID - if (stat (".", &sb) == 0) - { + if (stat (".", &sb) == 0) { if ((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid) return DL_EX_NEED_PRIVS; }