apply umount lazy patch from Mandrake
authorGerald Carter <jerry@samba.org>
Wed, 5 Feb 2003 15:55:08 +0000 (15:55 +0000)
committerGerald Carter <jerry@samba.org>
Wed, 5 Feb 2003 15:55:08 +0000 (15:55 +0000)
source/client/smbumount.c

index 20b6820fb761a8eeb0baa398a909eb3cd63ac507..2c2243528d63e234248c7e4831c88bc8d6b6ef1d 100644 (file)
 #include <linux/smb_mount.h>
 #include <linux/smb_fs.h>
 
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
 /* This is a (hopefully) temporary hack due to the fact that
        sizeof( uid_t ) != sizeof( __kernel_uid_t ) under glibc.
        This may change in the future and smb.h may get fixed in the
@@ -43,9 +47,9 @@ umount_ok(const char *mount_point)
         __kernel_uid_t mount_uid;
        
         if (fid == -1) {
-                fprintf(stderr, "Could not open %s: %s\n",
-                        mount_point, strerror(errno));
-                return -1;
+                /* fprintf(stderr, "Could not open %s: %s\n",
+                        mount_point, strerror(errno)); */
+                return 1;      /* maybe try again */
         }
         
         if (ioctl(fid, SMB_IOC_GETMOUNTUID, &mount_uid) != 0) {
@@ -65,6 +69,92 @@ umount_ok(const char *mount_point)
         return 0;
 }
 
+#define        MAX_READLINKS   32
+/* myrealpath from mount, it could get REAL path under a broken connection */
+char *myrealpath(const char *path, char *resolved_path, int maxreslth)
+{
+       int readlinks = 0,m,n;
+       char *npath,*buf;
+       char link_path[PATH_MAX + 1];
+
+       npath = resolved_path;
+
+       if(*path != '/')
+       {
+               if(!getcwd(npath, maxreslth - 2))
+                       return NULL;
+               npath += strlen(npath);
+               if(npath[-1] != '/')
+                       *(npath++) = '/';
+               else
+               {
+                       *npath++ = '/';
+                       path++;
+               }
+       }
+
+       while(*path != '\0')
+       {
+               if(*path == '/')
+               {
+                       path++;
+                       continue;
+               }
+               if(*path == '.' && (path[1] == '\0' || path[1] == '/'))
+               {
+                       path++;
+                       continue;
+               }
+               if(*path == '.' && path[1] == '.' &&
+                               (path[2] == '\0' || path[2] == '/'))
+               {
+                       path += 2;
+                       while(npath > resolved_path + 1 &&
+                                       (--npath)[-1] != '/');
+                       continue;
+               }
+               while(*path != '\0' && *path != '/')
+               {
+                       if(npath-resolved_path > maxreslth - 2)
+                               return NULL;
+                       *npath++ = *path++;
+               }
+               if(readlinks++ > MAX_READLINKS)
+                       return NULL;
+               *npath = '\0';
+               n = readlink(resolved_path, link_path, PATH_MAX);
+               if(n < 0)
+               {
+                       if(errno != EINVAL) return NULL;
+               }
+               else
+               {
+                       link_path[n] = '\0';
+                       if(*link_path == '/')
+                               npath = resolved_path;
+                       else while(*(--npath) != '/');
+                       m = strlen(path);
+                       if((buf = malloc(m + n + 1)) == NULL)
+                       {
+                               fprintf(stderr,"Not enough memory.\n");
+                               return NULL;
+                       }
+                       memcpy(buf, link_path, n);
+                       memcpy(buf + n, path, m + 1);
+                       path = buf;
+               }
+               *npath++ = '/';
+       }
+       if(npath != resolved_path + 1)
+       {
+           while(npath > resolved_path && npath[-1] == '/')
+               npath--;
+           if(npath == resolved_path) return NULL;
+       }
+       *npath = '\0';
+       return resolved_path;
+}
+
 /* Make a canonical pathname from PATH.  Returns a freshly malloced string.
    It is up the *caller* to ensure that the PATH is sensible.  i.e.
    canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
@@ -73,7 +163,8 @@ umount_ok(const char *mount_point)
 static char *
 canonicalize (char *path)
 {
-       char *canonical = malloc (PATH_MAX + 1);
+       char *npath,*canonical = malloc (PATH_MAX + 1);
+       int i;
 
        if (!canonical) {
                fprintf(stderr, "Error! Not enough memory!\n");
@@ -87,11 +178,18 @@ canonicalize (char *path)
 
        if (path == NULL)
                return NULL;
-  
-       if (realpath (path, canonical))
+
+/*     if (realpath (path, canonical)) */
+       if(myrealpath(path, canonical, PATH_MAX))
                return canonical;
 
        pstrcpy (canonical, path);
+       if((i = strlen(canonical)) > 1 && i <= PATH_MAX)
+       {
+               path = canonical + i;
+               while(*(--path) == '/')
+                       *path = '\0';
+       }
        return canonical;
 }
 
@@ -122,14 +220,34 @@ main(int argc, char *argv[])
                exit(1);
        }
 
-        if (umount_ok(mount_point) != 0) {
-                exit(1);
+        if ((fd = umount_ok(mount_point)) != 0) {
+               if(fd == 1)
+               {
+                       if((fd = umount_ok(mount_point)) != 0)
+                       {
+                               if(fd == 1)
+                               {
+                                       fprintf(stderr, "Could not open %s: %s\n",
+                                               mount_point, strerror(errno));
+                               }
+                               exit(1);
+                       }
+               }
+               else exit(1);
         }
 
+#if !defined(MNT_DETACH)
+ #define       MNT_DETACH      2
+#endif
+       
         if (umount(mount_point) != 0) {
-                fprintf(stderr, "Could not umount %s: %s\n",
-                        mount_point, strerror(errno));
-                exit(1);
+                /* fprintf(stderr, "Could not umount %s: %s\n,Trying lazy umount.\n",
+                        mount_point, strerror(errno)); */
+               if(umount2(mount_point,MNT_DETACH) != 0)
+               {
+                       fprintf(stderr, "Lazy umount failed.\n");
+                       return 1;
+               }
         }
 
         if ((fd = open(MOUNTED"~", O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)