Commit fffe6137 fffe6137e227c5af157b7520fb4aa73aad00dd8e by Sam Roberts

Implemented symlink unrolling before locking.

1 parent 7eb2aa3d
...@@ -84,6 +84,7 @@ typedef void *(*mu_retrieve_fp) __P((void *)); ...@@ -84,6 +84,7 @@ typedef void *(*mu_retrieve_fp) __P((void *));
84 extern void mu_register_retriever __P((list_t *pflist, mu_retrieve_fp fun)); 84 extern void mu_register_retriever __P((list_t *pflist, mu_retrieve_fp fun));
85 extern void * mu_retrieve __P((list_t flist, void *data)); 85 extern void * mu_retrieve __P((list_t flist, void *data));
86 86
87 extern int mu_unroll_symlink __P((char *out, size_t outsz, const char *in));
87 88
88 #ifdef __cplusplus 89 #ifdef __cplusplus
89 } 90 }
......
...@@ -100,21 +100,26 @@ int locker_set_default_flags(int flags) ...@@ -100,21 +100,26 @@ int locker_set_default_flags(int flags)
100 } 100 }
101 101
102 int 102 int
103 locker_create (locker_t *plocker, const char *filename, int flags) 103 locker_create (locker_t *plocker, const char *filename_, int flags)
104 { 104 {
105 locker_t l; 105 locker_t l;
106 char filename[_POSIX_PATH_MAX];
107 int err = 0;
106 108
107 if (plocker == NULL) 109 if (plocker == NULL)
108 return MU_ERR_OUT_PTR_NULL; 110 return MU_ERR_OUT_PTR_NULL;
109 111
110 if (filename == NULL) 112 if (filename_ == NULL)
111 return EINVAL; 113 return EINVAL;
112 114
115 if((err = mu_unroll_symlink(filename, sizeof(filename), filename_)))
116 return err;
117
113 l = calloc (1, sizeof (*l)); 118 l = calloc (1, sizeof (*l));
119
114 if (l == NULL) 120 if (l == NULL)
115 return ENOMEM; 121 return ENOMEM;
116 122
117 /* Should make l->file be the result of following the symlinks. */
118 l->file = strdup(filename); 123 l->file = strdup(filename);
119 124
120 if (l->file == NULL) 125 if (l->file == NULL)
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
21 #endif 21 #endif
22 22
23 #include <errno.h> 23 #include <errno.h>
24 #include <limits.h>
24 #include <netdb.h> 25 #include <netdb.h>
25 #include <pwd.h> 26 #include <pwd.h>
26 #include <signal.h> 27 #include <signal.h>
...@@ -776,3 +777,74 @@ int mu_spawnvp (const char* prog, const char* const av_[], int* stat) ...@@ -776,3 +777,74 @@ int mu_spawnvp (const char* prog, const char* const av_[], int* stat)
776 return err; 777 return err;
777 } 778 }
778 779
780
781 /* The result of readlink() may be a path relative to that link,
782 * qualify it if necessary.
783 */
784 static void
785 mu_qualify_link (const char *path, const char *link, char *qualified)
786 {
787 const char *lb = NULL;
788 size_t len;
789
790 /* link is full path */
791 if (*link == '/')
792 {
793 mu_cpystr (qualified, link, _POSIX_PATH_MAX);
794 return;
795 }
796
797 if ((lb = strrchr (path, '/')) == NULL)
798 {
799 /* no path in link */
800 mu_cpystr (qualified, link, _POSIX_PATH_MAX);
801 return;
802 }
803
804 len = lb - path + 1;
805 memcpy (qualified, path, len);
806 mu_cpystr (qualified + len, link, _POSIX_PATH_MAX - len);
807 }
808
809 #ifndef _POSIX_SYMLOOP_MAX
810 # define _POSIX_SYMLOOP_MAX 255
811 #endif
812
813 int
814 mu_unroll_symlink (char *out, size_t outsz, const char *in)
815 {
816 char path[_POSIX_PATH_MAX];
817 int symloops = 0;
818
819 while (symloops++ < _POSIX_SYMLOOP_MAX)
820 {
821 struct stat s;
822 char link[_POSIX_PATH_MAX];
823 char qualified[_POSIX_PATH_MAX];
824 int len;
825
826 if (lstat (in, &s) == -1)
827 return errno;
828
829 if (!S_ISLNK (s.st_mode))
830 {
831 mu_cpystr (path, in, sizeof (path));
832 break;
833 }
834
835 if ((len = readlink (in, link, sizeof (link))) == -1)
836 return errno;
837
838 link[(len >= sizeof (link)) ? (sizeof (link) - 1) : len] = '\0';
839
840 mu_qualify_link (in, link, qualified);
841
842 mu_cpystr (path, qualified, sizeof (path));
843
844 in = path;
845 }
846
847 mu_cpystr (out, path, outsz);
848
849 return 0;
850 }
......