Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.daemon.vfs » [javadoc | source]
    1   /*
    2    *  SSHTools - Java SSH2 API
    3    *
    4    *  Copyright (C) 2002-2003 Lee David Painter and Contributors.
    5    *
    6    *  Contributions made by:
    7    *
    8    *  Brett Smith
    9    *  Richard Pernavas
   10    *  Erwin Bolwidt
   11    *
   12    *  This program is free software; you can redistribute it and/or
   13    *  modify it under the terms of the GNU General Public License
   14    *  as published by the Free Software Foundation; either version 2
   15    *  of the License, or (at your option) any later version.
   16    *
   17    *  This program is distributed in the hope that it will be useful,
   18    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   19    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20    *  GNU General Public License for more details.
   21    *
   22    *  You should have received a copy of the GNU General Public License
   23    *  along with this program; if not, write to the Free Software
   24    *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   25    */
   26   package com.sshtools.daemon.vfs;
   27   
   28   import com.sshtools.daemon.configuration.PlatformConfiguration;
   29   import com.sshtools.daemon.platform.InvalidHandleException;
   30   import com.sshtools.daemon.platform.NativeAuthenticationProvider;
   31   import com.sshtools.daemon.platform.NativeFileSystemProvider;
   32   import com.sshtools.daemon.platform.PermissionDeniedException;
   33   import com.sshtools.daemon.platform.UnsupportedFileOperationException;
   34   
   35   import com.sshtools.j2ssh.SshThread;
   36   import com.sshtools.j2ssh.configuration.ConfigurationException;
   37   import com.sshtools.j2ssh.configuration.ConfigurationLoader;
   38   import com.sshtools.j2ssh.io.UnsignedInteger32;
   39   import com.sshtools.j2ssh.io.UnsignedInteger64;
   40   import com.sshtools.j2ssh.sftp.FileAttributes;
   41   import com.sshtools.j2ssh.sftp.SftpFile;
   42   
   43   import org.apache.commons.logging.Log;
   44   import org.apache.commons.logging.LogFactory;
   45   
   46   import java.io.EOFException;
   47   import java.io.File;
   48   import java.io.FileNotFoundException;
   49   import java.io.IOException;
   50   import java.io.RandomAccessFile;
   51   
   52   import java.util.HashMap;
   53   import java.util.Iterator;
   54   import java.util.Map;
   55   
   56   
   57   /**
   58    *
   59    *
   60    * @author $author$
   61    * @version $Revision: 1.32 $
   62    */
   63   public class VirtualFileSystem extends NativeFileSystemProvider {
   64       private static String USER_HOME = "/home/";
   65       private static Map vfsmounts;
   66       private static VFSMount vfsroot;
   67       private static Log log = LogFactory.getLog(VirtualFileSystem.class);
   68       private static VFSPermissionHandler permissionHandler = null;
   69   
   70       static {
   71           try {
   72               vfsmounts = ((PlatformConfiguration) ConfigurationLoader.getConfiguration(PlatformConfiguration.class)).getVFSMounts();
   73               vfsroot = ((PlatformConfiguration) ConfigurationLoader.getConfiguration(PlatformConfiguration.class)).getVFSRoot();
   74           } catch (ConfigurationException ex) {
   75               log.error("Failed to initialize the Virtual File System", ex);
   76           }
   77       }
   78   
   79       private Map openFiles = new HashMap();
   80   
   81       /**
   82    * Creates a new VirtualFileSystem object.
   83    *
   84    * @throws IOException
   85    */
   86       public VirtualFileSystem() throws IOException {
   87           if (!ConfigurationLoader.isConfigurationAvailable(
   88                       PlatformConfiguration.class)) {
   89               throw new IOException("No valid platform configuration available");
   90           }
   91       }
   92   
   93       public static void setPermissionHandler(
   94           VFSPermissionHandler permissionHandler) {
   95           VirtualFileSystem.permissionHandler = permissionHandler;
   96       }
   97   
   98       private static String getVFSHomeDirectory(String username)
   99           throws FileNotFoundException {
  100           if (permissionHandler != null) {
  101               return permissionHandler.getVFSHomeDirectory(username);
  102           } else {
  103               return USER_HOME + username;
  104           }
  105       }
  106   
  107       private static String getNFSHomeDirectory() throws FileNotFoundException {
  108           try {
  109               if (Thread.currentThread() instanceof SshThread &&
  110                       SshThread.hasUserContext()) {
  111                   NativeAuthenticationProvider nap = NativeAuthenticationProvider.getInstance();
  112   
  113                   return nap.getHomeDirectory(SshThread.getCurrentThreadUser());
  114               } else {
  115                   throw new FileNotFoundException("There is no user logged in");
  116               }
  117           } catch (IOException e) {
  118               throw new FileNotFoundException(e.getMessage());
  119           }
  120       }
  121   
  122       /**
  123    *
  124    *
  125    * @param str
  126    * @param with
  127    *
  128    * @return
  129    */
  130       public static boolean startsWithIgnoreCase(String str, String with) {
  131           return str.substring(0,
  132               (with.length() > str.length()) ? str.length() : with.length())
  133                     .equalsIgnoreCase(with);
  134       }
  135   
  136       /**
  137    *
  138    *
  139    * @param nfspath
  140    *
  141    * @return
  142    *
  143    * @throws FileNotFoundException
  144    */
  145       public static String translateNFSPath(String nfspath)
  146           throws FileNotFoundException {
  147           nfspath = nfspath.replace('\\', '/');
  148   
  149           // ./ means home
  150           if (nfspath.startsWith("./")) {
  151               nfspath = nfspath.substring(2);
  152           }
  153   
  154           //if (startsWithIgnoreCase(nfspath, nfshome)) {
  155           try {
  156               String nfshome = getNFSHomeDirectory().replace('\\', '/');
  157               nfshome = translateCanonicalPath(nfshome, nfshome);
  158   
  159               String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());
  160   
  161               // First check for the userhome
  162               log.debug("NFSPath=" + nfspath);
  163               log.debug("NFSHome=" + nfshome);
  164               nfspath = translateCanonicalPath(nfspath, nfshome);
  165   
  166               int idx = nfspath.indexOf(nfshome);
  167   
  168               return vfshome + nfspath.substring(nfshome.length());
  169   
  170               //            StringBuffer buf = new StringBuffer(nfspath);
  171               //            buf = buf.replace(idx, idx + nfshome.length(), vfshome);
  172               //            return buf.toString(); /*nfspath.replaceFirst(nfshome, vfshome);*/
  173               //}
  174           } catch (FileNotFoundException ex) { /* Ignore as we will try other mounts */
  175           }
  176   
  177           // Now lets translate from the available mounts
  178           Iterator it = vfsmounts.entrySet().iterator();
  179           Map.Entry entry;
  180           String mount;
  181           String path;
  182           VFSMount m;
  183   
  184           while (it.hasNext()) {
  185               entry = (Map.Entry) it.next();
  186               mount = (String) entry.getKey();
  187               m = (VFSMount) entry.getValue();
  188               path = m.getPath();
  189               log.debug(m.getMount() + "=" + m.getPath());
  190   
  191               // if (startsWithIgnoreCase(nfspath, path)) {
  192               try {
  193                   nfspath = translateCanonicalPath(nfspath, path);
  194   
  195                   int idx = nfspath.indexOf(path);
  196                   StringBuffer buf = new StringBuffer(nfspath);
  197                   buf = buf.replace(idx, idx + path.length(), mount);
  198   
  199                   return buf.toString();
  200               } catch (FileNotFoundException ex) {
  201                   /* Ingore as we will try other mounts */
  202               }
  203   
  204               // }
  205           }
  206   
  207           // if (startsWithIgnoreCase(nfspath, vfsroot.getPath())) {
  208           log.debug("VFSRoot=" + vfsroot.getPath());
  209           nfspath = translateCanonicalPath(nfspath, vfsroot.getPath());
  210           path = nfspath.substring(vfsroot.getPath().length()); //replaceFirst(vfsroot.getPath(), "");
  211   
  212           return (path.startsWith("/") ? path : ("/" + path));
  213   
  214           //  } else {
  215           //      throw new FileNotFoundException(nfspath + " could not be found");
  216           //  }
  217       }
  218   
  219       private static VFSMount getMount(String vfspath)
  220           throws FileNotFoundException, IOException {
  221           String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());
  222           VFSMount m;
  223   
  224           if (vfspath.startsWith("/")) {
  225               if (vfspath.startsWith(vfshome)) {
  226                   m = new VFSMount(vfshome, getNFSHomeDirectory());
  227                   m.setPermissions(new VFSPermission(
  228                           SshThread.getCurrentThreadUser(), "rwx"));
  229   
  230                   return m;
  231               } else {
  232                   Iterator it = vfsmounts.entrySet().iterator();
  233                   Map.Entry entry;
  234                   String mount;
  235   
  236                   while (it.hasNext()) {
  237                       entry = (Map.Entry) it.next();
  238                       mount = (String) entry.getKey();
  239   
  240                       if (vfspath.startsWith(mount)) {
  241                           return (VFSMount) entry.getValue();
  242                       }
  243                   }
  244   
  245                   if (vfsroot != null) {
  246                       return vfsroot;
  247                   } else {
  248                       throw new FileNotFoundException("The path was not found");
  249                   }
  250               }
  251           } else {
  252               m = new VFSMount(vfshome, getNFSHomeDirectory());
  253               m.setPermissions(new VFSPermission(vfshome.substring(
  254                           vfshome.lastIndexOf("/")), "rwx"));
  255   
  256               return m;
  257           }
  258       }
  259   
  260       /**
  261    *
  262    *
  263    * @param vfspath
  264    *
  265    * @return
  266    *
  267    * @throws FileNotFoundException
  268    */
  269       public static String translateVFSPath(String vfspath)
  270           throws FileNotFoundException {
  271           return translateVFSPath(vfspath, null);
  272       }
  273   
  274       public static String translateVFSPath(String vfspath, String vfscwd)
  275           throws FileNotFoundException {
  276           // Translate any backslashes for sanity
  277           vfspath = vfspath.replace('\\', '/').trim();
  278   
  279           try {
  280               if (!vfspath.startsWith("/")) {
  281                   // Work out the path using the current directory
  282                   String path = (((vfscwd == null) || vfscwd.trim().equals(""))
  283                       ? getVFSHomeDirectory(SshThread.getCurrentThreadUser())
  284                       : vfscwd);
  285                   vfspath = path + (path.endsWith("/") ? "" : "/") + vfspath;
  286               }
  287   
  288               String nfshome = getNFSHomeDirectory().replace('\\', '/');
  289               String vfshome = getVFSHomeDirectory(SshThread.getCurrentThreadUser());
  290   
  291               if (vfspath.startsWith(vfshome)) {
  292                   // Return the canonicalized system dependent path
  293                   if (vfspath.length() > vfshome.length()) {
  294                       return translateCanonicalPath(nfshome +
  295                           (nfshome.endsWith("/") ? "" : "/") +
  296                           vfspath.substring(vfshome.length() + 1), nfshome);
  297                   } else {
  298                       return translateCanonicalPath(nfshome, nfshome);
  299                   }
  300               }
  301           } catch (FileNotFoundException ex) {
  302               // Ignore since we dont always need to be running as a user
  303           }
  304   
  305           // The path does not refer to the absolute USER_HOME
  306           // so we will look up using the platform.xml VFS mounts
  307           Iterator it = vfsmounts.entrySet().iterator();
  308           Map.Entry entry;
  309           String mount;
  310           String path;
  311           VFSMount m;
  312   
  313           while (it.hasNext()) {
  314               entry = (Map.Entry) it.next();
  315               mount = (String) entry.getKey();
  316               m = (VFSMount) entry.getValue();
  317               path = m.getPath();
  318   
  319               if (vfspath.startsWith(mount)) {
  320                   // Lets translate the path, making sure we do not move outside
  321                   // vfs with ..
  322                   String str = path + vfspath.substring(mount.length());
  323   
  324                   // vfspath.replaceFirst(mount,
  325                   //        path)
  326                   return translateCanonicalPath(str, path);
  327               }
  328           }
  329   
  330           // If we reached here then the VFS path did not refer to an optional mount
  331           // or the users home directory, so lets attempt to use the VFS root is there
  332           // is one defined
  333           if (vfsroot != null) {
  334               path = vfsroot.getPath() +
  335                   (vfsroot.getPath().endsWith("/") ? vfspath.substring(1) : vfspath);
  336   
  337               return translateCanonicalPath(path, vfsroot.getPath());
  338           } else {
  339               throw new FileNotFoundException("The file could not be found");
  340           }
  341       }
  342   
  343       /*else {
  344     try {
  345       String nfshome = (nfscwd == null || nfscwd.trim().equals("") ? getNFSHomeDirectory() : nfscwd);
  346       String path = nfshome + (nfshome.endsWith("/") ? "" : "/") + vfspath;
  347       return translateCanonicalPath(path, nfshome);
  348     }
  349     catch (FileNotFoundException ex1) {
  350       throw new FileNotFoundException(
  351        "Only fully qualified VFS paths can be translated outside of a user context");
  352     }
  353     /*  String path = nfshome + (nfshome.endsWith("/") ? "" : "/")
  354            + vfspath;
  355        return translateCanonicalPath(path, nfshome);*/
  356   
  357       //}
  358   
  359       /**
  360    *
  361    *
  362    * @param path
  363    * @param securemount
  364    *
  365    * @return
  366    *
  367    * @throws FileNotFoundException
  368    */
  369       public static String translateCanonicalPath(String path, String securemount)
  370           throws FileNotFoundException {
  371           try {
  372               log.debug("Translating for canonical path " + path +
  373                   " against secure mount " + securemount);
  374   
  375               File f = new File(path);
  376               String canonical = f.getCanonicalPath().replace('\\', '/');
  377               File f2 = new File(securemount);
  378               String canonical2 = f2.getCanonicalPath().replace('\\', '/');
  379   
  380               // Verify that the canonical path does not exit out of the mount
  381               if (canonical.startsWith(canonical2)) {
  382                   return canonical;
  383               } else {
  384                   throw new FileNotFoundException(path + " could not be found");
  385               }
  386           } catch (IOException ex) {
  387               throw new FileNotFoundException(path + " could not be found");
  388           }
  389       }
  390   
  391       /**
  392    *
  393    *
  394    * @param path
  395    *
  396    * @return
  397    *
  398    * @throws PermissionDeniedException
  399    * @throws FileNotFoundException
  400    * @throws IOException
  401    */
  402       public boolean makeDirectory(String path)
  403           throws PermissionDeniedException, FileNotFoundException, IOException {
  404           //    String realPath = path;
  405           path = VirtualFileSystem.translateVFSPath(path);
  406   
  407           File f = new File(path);
  408           verifyPermissions(SshThread.getCurrentThreadUser(), path, "rw");
  409           log.debug("Creating directory " + f.getAbsolutePath());
  410   
  411           return f.mkdir();
  412       }
  413   
  414       /**
  415    *
  416    *
  417    * @param path
  418    *
  419    * @return
  420    *
  421    * @throws FileNotFoundException
  422    * @throws IOException
  423    */
  424       public VFSPermission getVFSPermission(String path)
  425           throws FileNotFoundException, IOException {
  426           VFSMount mount = getMount(translateNFSPath(path));
  427   
  428           if (mount.getPermissions().containsKey(SshThread.getCurrentThreadUser())) {
  429               return (VFSPermission) mount.getPermissions().get(SshThread.getCurrentThreadUser());
  430           } else {
  431               return (VFSPermission) mount.getPermissions().get("default");
  432           }
  433       }
  434   
  435       /**
  436    *
  437    *
  438    * @param handle
  439    *
  440    * @return
  441    *
  442    * @throws IOException
  443    * @throws InvalidHandleException
  444    */
  445       public FileAttributes getFileAttributes(byte[] handle)
  446           throws IOException, InvalidHandleException {
  447           String shandle = new String(handle);
  448   
  449           if (openFiles.containsKey(shandle)) {
  450               Object obj = openFiles.get(shandle);
  451               File f;
  452   
  453               if (obj instanceof OpenFile) {
  454                   f = ((OpenFile) obj).getFile();
  455               } else if (obj instanceof OpenDirectory) {
  456                   f = ((OpenDirectory) obj).getFile();
  457               } else {
  458                   throw new IOException("Unexpected open file handle");
  459               }
  460   
  461               VFSPermission permissions = getVFSPermission(f.getAbsolutePath());
  462   
  463               if (permissions == null) {
  464                   throw new IOException("No default permissions set");
  465               }
  466   
  467               FileAttributes attrs = new FileAttributes();
  468               attrs.setSize(new UnsignedInteger64(String.valueOf(f.length())));
  469               attrs.setTimes(new UnsignedInteger32(f.lastModified() / 1000),
  470                   new UnsignedInteger32(f.lastModified() / 1000));
  471   
  472               boolean canExec = true;
  473   
  474               try {
  475                   if (System.getSecurityManager() != null) {
  476                       System.getSecurityManager().checkExec(f.getCanonicalPath());
  477                   }
  478               } catch (SecurityException ex1) {
  479                   canExec = false;
  480               }
  481   
  482               attrs.setPermissions((((f.canRead() && permissions.canRead()) ? "r"
  483                                                                             : "-") +
  484                   ((f.canWrite() && permissions.canWrite()) ? "w" : "-") +
  485                   ((canExec && permissions.canExecute()) ? "x" : "-")));
  486               attrs.setPermissions(new UnsignedInteger32(attrs.getPermissions()
  487                                                               .longValue() |
  488                       (f.isDirectory() ? FileAttributes.S_IFDIR
  489                                        : FileAttributes.S_IFREG)));
  490   
  491               return attrs;
  492           } else {
  493               throw new InvalidHandleException("The handle is invalid");
  494           }
  495       }
  496   
  497       /**
  498    *
  499    *
  500    * @param path
  501    *
  502    * @return
  503    *
  504    * @throws IOException
  505    * @throws FileNotFoundException
  506    */
  507       public FileAttributes getFileAttributes(String path)
  508           throws IOException, FileNotFoundException {
  509           log.debug("Getting file attributes for " + path);
  510           path = translateVFSPath(path);
  511   
  512           // Look up the VFS mount attributes
  513           File f = new File(path);
  514           path = f.getCanonicalPath();
  515   
  516           if (!f.exists()) {
  517               throw new FileNotFoundException(path + " doesn't exist");
  518           }
  519   
  520           VFSPermission permissions = getVFSPermission(path);
  521   
  522           if (permissions == null) {
  523               throw new IOException("No default permissions set");
  524           }
  525   
  526           FileAttributes attrs = new FileAttributes();
  527           attrs.setSize(new UnsignedInteger64(String.valueOf(f.length())));
  528           attrs.setTimes(new UnsignedInteger32(f.lastModified() / 1000),
  529               new UnsignedInteger32(f.lastModified() / 1000));
  530   
  531           boolean canExec = true;
  532   
  533           try {
  534               if (System.getSecurityManager() != null) {
  535                   System.getSecurityManager().checkExec(f.getCanonicalPath());
  536               }
  537           } catch (SecurityException ex1) {
  538               canExec = false;
  539           }
  540   
  541           attrs.setPermissions((((f.canRead() && permissions.canRead()) ? "r" : "-") +
  542               ((f.canWrite() && permissions.canWrite()) ? "w" : "-") +
  543               ((canExec && permissions.canExecute()) ? "x" : "-")));
  544           attrs.setPermissions(new UnsignedInteger32(attrs.getPermissions()
  545                                                           .longValue() |
  546                   (f.isDirectory() ? FileAttributes.S_IFDIR : FileAttributes.S_IFREG)));
  547   
  548           return attrs;
  549       }
  550   
  551       /**
  552    *
  553    *
  554    * @param path
  555    *
  556    * @return
  557    *
  558    * @throws PermissionDeniedException
  559    * @throws FileNotFoundException
  560    * @throws IOException
  561    */
  562       public byte[] openDirectory(String path)
  563           throws PermissionDeniedException, FileNotFoundException, IOException {
  564           String realPath = path;
  565           path = VirtualFileSystem.translateVFSPath(path);
  566   
  567           File f = new File(path);
  568           verifyPermissions(SshThread.getCurrentThreadUser(), path, "r");
  569   
  570           if (f.exists()) {
  571               if (f.isDirectory()) {
  572                   openFiles.put(f.toString(), new OpenDirectory(realPath, path, f));
  573   
  574                   return f.toString().getBytes("US-ASCII");
  575               } else {
  576                   throw new IOException(translateNFSPath(path) +
  577                       " is not a directory");
  578               }
  579           } else {
  580               throw new FileNotFoundException(translateNFSPath(path) +
  581                   " does not exist");
  582           }
  583       }
  584   
  585       /**
  586    *
  587    *
  588    * @param handle
  589    *
  590    * @return
  591    *
  592    * @throws InvalidHandleException
  593    * @throws EOFException
  594    * @throws IOException
  595    */
  596       public SftpFile[] readDirectory(byte[] handle)
  597           throws InvalidHandleException, EOFException, IOException {
  598           String shandle = new String(handle);
  599   
  600           if (openFiles.containsKey(shandle)) {
  601               Object obj = openFiles.get(shandle);
  602   
  603               if (obj instanceof OpenDirectory) {
  604                   OpenDirectory dir = (OpenDirectory) obj;
  605                   int pos = dir.getPosition();
  606                   File[] children = dir.getChildren();
  607   
  608                   if (children == null) {
  609                       throw new IOException("Permission denined.");
  610                   }
  611   
  612                   int count = ((children.length - pos) < 100)
  613                       ? (children.length - pos) : 100;
  614   
  615                   if (count > 0) {
  616                       SftpFile[] files = new SftpFile[count];
  617   
  618                       for (int i = 0; i < files.length; i++) {
  619                           File f = children[pos + i];
  620                           String absolutePath = dir.realPath + "/" + f.getName();
  621                           SftpFile sftpfile = new SftpFile(f.getName(),
  622                                   getFileAttributes(absolutePath));
  623                           files[i] = sftpfile;
  624                       }
  625   
  626                       dir.readpos = pos + files.length;
  627   
  628                       return files;
  629                   } else {
  630                       throw new EOFException("There are no more files");
  631                   }
  632               } else {
  633                   throw new InvalidHandleException(
  634                       "Handle is not an open directory");
  635               }
  636           } else {
  637               throw new InvalidHandleException("The handle is invalid");
  638           }
  639       }
  640   
  641       /**
  642    *
  643    *
  644    * @param path
  645    * @param flags
  646    * @param attrs
  647    *
  648    * @return
  649    *
  650    * @throws PermissionDeniedException
  651    * @throws FileNotFoundException
  652    * @throws IOException
  653    */
  654       public byte[] openFile(String path, UnsignedInteger32 flags,
  655           FileAttributes attrs)
  656           throws PermissionDeniedException, FileNotFoundException, IOException {
  657           path = VirtualFileSystem.translateVFSPath(path);
  658   
  659           File f = new File(path);
  660           verifyPermissions(SshThread.getCurrentThreadUser(), path, "r");
  661   
  662           // Check if the file does not exist and process according to flags
  663           if (!f.exists()) {
  664               if ((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) {
  665                   // The file does not exist and the create flag is present so lets create it
  666                   if (!f.createNewFile()) {
  667                       throw new IOException(translateNFSPath(path) +
  668                           " could not be created");
  669                   }
  670               } else {
  671                   // The file does not exist and no create flag present
  672                   throw new FileNotFoundException(translateNFSPath(path) +
  673                       " does not exist");
  674               }
  675           } else {
  676               if (((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) &&
  677                       ((flags.intValue() &
  678                       NativeFileSystemProvider.OPEN_EXCLUSIVE) == NativeFileSystemProvider.OPEN_EXCLUSIVE)) {
  679                   // The file exists but the EXCL flag is set which requires that the
  680                   // file should not exist prior to creation, so throw a status exception
  681                   throw new IOException(translateNFSPath(path) +
  682                       " already exists");
  683               }
  684           }
  685   
  686           // The file now exists so open the file according to the flags yb building the relevant
  687           // flags for the RandomAccessFile class
  688           String mode = "r" +
  689               (((flags.intValue() & NativeFileSystemProvider.OPEN_WRITE) == NativeFileSystemProvider.OPEN_WRITE)
  690               ? "ws" : "");
  691           RandomAccessFile raf = new RandomAccessFile(f, mode);
  692   
  693           // Determine whether we need to truncate the file
  694           if (((flags.intValue() & NativeFileSystemProvider.OPEN_CREATE) == NativeFileSystemProvider.OPEN_CREATE) &&
  695                   ((flags.intValue() & NativeFileSystemProvider.OPEN_TRUNCATE) == NativeFileSystemProvider.OPEN_TRUNCATE)) {
  696               // Set the length to zero
  697               raf.setLength(0);
  698           }
  699   
  700           // Record the open file
  701           openFiles.put(raf.toString(), new OpenFile(f, raf, flags));
  702   
  703           // Return the handle
  704           return raf.toString().getBytes("US-ASCII");
  705       }
  706   
  707       /**
  708    *
  709    *
  710    * @param handle
  711    * @param offset
  712    * @param len
  713    *
  714    * @return
  715    *
  716    * @throws InvalidHandleException
  717    * @throws EOFException
  718    * @throws IOException
  719    */
  720       public byte[] readFile(byte[] handle, UnsignedInteger64 offset,
  721           UnsignedInteger32 len)
  722           throws InvalidHandleException, EOFException, IOException {
  723           String shandle = new String(handle);
  724   
  725           if (openFiles.containsKey(shandle)) {
  726               Object obj = openFiles.get(shandle);
  727   
  728               if (obj instanceof OpenFile) {
  729                   OpenFile file = (OpenFile) obj;
  730   
  731                   if ((file.getFlags().intValue() &
  732                           NativeFileSystemProvider.OPEN_READ) == NativeFileSystemProvider.OPEN_READ) {
  733                       byte[] buf = new byte[len.intValue()];
  734   
  735                       if (file.getRandomAccessFile().getFilePointer() != offset.longValue()) {
  736                           file.getRandomAccessFile().seek(offset.longValue());
  737                       }
  738   
  739                       int read = file.getRandomAccessFile().read(buf);
  740   
  741                       if (read >= 0) {
  742                           if (read == buf.length) {
  743                               return buf;
  744                           } else {
  745                               byte[] tmp = new byte[read];
  746                               System.arraycopy(buf, 0, tmp, 0, read);
  747   
  748                               return tmp;
  749                           }
  750                       } else {
  751                           throw new EOFException("The file is EOF");
  752                       }
  753                   } else {
  754                       throw new InvalidHandleException(
  755                           "The file handle was not opened for reading");
  756                   }
  757               } else {
  758                   throw new InvalidHandleException("Handle is not an open file");
  759               }
  760           } else {
  761               throw new InvalidHandleException("The handle is invalid");
  762           }
  763       }
  764   
  765       /**
  766    *
  767    *
  768    * @param handle
  769    * @param offset
  770    * @param data
  771    * @param off
  772    * @param len
  773    *
  774    * @throws InvalidHandleException
  775    * @throws IOException
  776    */
  777       public void writeFile(byte[] handle, UnsignedInteger64 offset, byte[] data,
  778           int off, int len) throws InvalidHandleException, IOException {
  779           String shandle = new String(handle);
  780   
  781           if (openFiles.containsKey(shandle)) {
  782               Object obj = openFiles.get(shandle);
  783   
  784               if (obj instanceof OpenFile) {
  785                   OpenFile file = (OpenFile) obj;
  786   
  787                   if ((file.getFlags().intValue() &
  788                           NativeFileSystemProvider.OPEN_WRITE) == NativeFileSystemProvider.OPEN_WRITE) {
  789                       if ((file.getFlags().intValue() &
  790                               NativeFileSystemProvider.OPEN_APPEND) == NativeFileSystemProvider.OPEN_APPEND) {
  791                           // Force the data to be written to the end of the file by seeking to the end
  792                           file.getRandomAccessFile().seek(file.getRandomAccessFile()
  793                                                               .length());
  794                       } else if (file.getRandomAccessFile().getFilePointer() != offset.longValue()) {
  795                           // Move the file pointer if its not in the write place
  796                           file.getRandomAccessFile().seek(offset.longValue());
  797                       }
  798   
  799                       file.getRandomAccessFile().write(data, off, len);
  800                   } else {
  801                       throw new InvalidHandleException(
  802                           "The file was not opened for writing");
  803                   }
  804               } else {
  805                   throw new InvalidHandleException("Handle is not an open file");
  806               }
  807           } else {
  808               throw new InvalidHandleException("The handle is invalid");
  809           }
  810       }
  811   
  812       /**
  813    *
  814    *
  815    * @param handle
  816    *
  817    * @throws InvalidHandleException
  818    * @throws IOException
  819    */
  820       public void closeFile(byte[] handle)
  821           throws InvalidHandleException, IOException {
  822           String shandle = new String(handle);
  823   
  824           if (openFiles.containsKey(shandle)) {
  825               Object obj = openFiles.get(shandle);
  826   
  827               if (obj instanceof OpenDirectory) {
  828                   openFiles.remove(shandle);
  829               } else if (obj instanceof OpenFile) {
  830                   ((OpenFile) obj).getRandomAccessFile().close();
  831                   openFiles.remove(shandle);
  832               } else {
  833                   throw new InvalidHandleException("Internal server error");
  834               }
  835           } else {
  836               throw new InvalidHandleException("The handle is invalid");
  837           }
  838       }
  839   
  840       /**
  841    *
  842    *
  843    * @param path
  844    *
  845    * @throws PermissionDeniedException
  846    * @throws IOException
  847    * @throws FileNotFoundException
  848    */
  849       public void removeFile(String path)
  850           throws PermissionDeniedException, IOException, FileNotFoundException {
  851           path = VirtualFileSystem.translateVFSPath(path);
  852   
  853           File f = new File(path);
  854   
  855           if (f.exists()) {
  856               try {
  857                   if (f.isFile()) {
  858                       if (!f.delete()) {
  859                           throw new IOException("Failed to delete " +
  860                               translateNFSPath(path));
  861                       }
  862                   } else {
  863                       throw new IOException(translateNFSPath(path) +
  864                           " is a directory, use remove directory command to remove");
  865                   }
  866               } catch (SecurityException se) {
  867                   throw new PermissionDeniedException("Permission denied");
  868               }
  869           } else {
  870               throw new FileNotFoundException(translateNFSPath(path) +
  871                   " does not exist");
  872           }
  873       }
  874   
  875       /**
  876    *
  877    *
  878    * @param oldpath
  879    * @param newpath
  880    *
  881    * @throws PermissionDeniedException
  882    * @throws FileNotFoundException
  883    * @throws IOException
  884    */
  885       public void renameFile(String oldpath, String newpath)
  886           throws PermissionDeniedException, FileNotFoundException, IOException {
  887           oldpath = VirtualFileSystem.translateVFSPath(oldpath);
  888           newpath = VirtualFileSystem.translateVFSPath(newpath);
  889   
  890           File f = new File(oldpath);
  891           verifyPermissions(SshThread.getCurrentThreadUser(), oldpath, "rw");
  892           verifyPermissions(SshThread.getCurrentThreadUser(), newpath, "rw");
  893   
  894           if (f.exists()) {
  895               File f2 = new File(newpath);
  896   
  897               if (!f2.exists()) {
  898                   if (!f.renameTo(f2)) {
  899                       throw new IOException("Failed to rename file " +
  900                           translateNFSPath(oldpath));
  901                   }
  902               } else {
  903                   throw new IOException(translateNFSPath(newpath) +
  904                       " already exists");
  905               }
  906           } else {
  907               throw new FileNotFoundException(translateNFSPath(oldpath) +
  908                   " does not exist");
  909           }
  910       }
  911   
  912       /**
  913    *
  914    *
  915    * @param path
  916    *
  917    * @throws PermissionDeniedException
  918    * @throws FileNotFoundException
  919    * @throws IOException
  920    */
  921       public void removeDirectory(String path)
  922           throws PermissionDeniedException, FileNotFoundException, IOException {
  923           path = VirtualFileSystem.translateVFSPath(path);
  924   
  925           File f = new File(path);
  926           verifyPermissions(SshThread.getCurrentThreadUser(), path, "rw");
  927   
  928           if (f.isDirectory()) {
  929               if (f.exists()) {
  930                   if (f.listFiles().length == 0) {
  931                       if (!f.delete()) {
  932                           throw new IOException("Failed to remove directory " +
  933                               translateNFSPath(path));
  934                       }
  935                   } else {
  936                       throw new IOException(translateNFSPath(path) +
  937                           " is not an empty directory");
  938                   }
  939               } else {
  940                   throw new FileNotFoundException(translateNFSPath(path) +
  941                       " does not exist");
  942               }
  943           } else {
  944               throw new IOException(translateNFSPath(path) +
  945                   " is not a directory");
  946           }
  947       }
  948   
  949       /**
  950    *
  951    *
  952    * @param path
  953    * @param attrs
  954    *
  955    * @throws PermissionDeniedException
  956    * @throws IOException
  957    * @throws FileNotFoundException
  958    */
  959       public void setFileAttributes(String path, FileAttributes attrs)
  960           throws PermissionDeniedException, IOException, FileNotFoundException {
  961           // Since we cannot really set permissions, this should be ignored as we
  962           // do not want applications to fail.
  963   
  964           /*String realPath = VirtualFileSystem.translateVFSPath(path);
  965        throw new PermissionDeniedException(
  966       "Cannot set file attributes using virtual file system for file "
  967       + realPath);*/
  968       }
  969   
  970       /**
  971    *
  972    *
  973    * @param handle
  974    * @param attrs
  975    *
  976    * @throws PermissionDeniedException
  977    * @throws IOException
  978    * @throws InvalidHandleException
  979    */
  980       public void setFileAttributes(byte[] handle, FileAttributes attrs)
  981           throws PermissionDeniedException, IOException, InvalidHandleException {
  982       }
  983   
  984       /**
  985    *
  986    *
  987    * @param path
  988    *
  989    * @return
  990    *
  991    * @throws UnsupportedFileOperationException
  992    * @throws FileNotFoundException
  993    * @throws IOException
  994    * @throws PermissionDeniedException
  995    */
  996       public SftpFile readSymbolicLink(String path)
  997           throws UnsupportedFileOperationException, FileNotFoundException, 
  998               IOException, PermissionDeniedException {
  999           throw new UnsupportedFileOperationException(
 1000               "Symbolic links are not supported by the Virtual File System");
 1001       }
 1002   
 1003       /**
 1004    *
 1005    *
 1006    * @param link
 1007    * @param target
 1008    *
 1009    * @throws UnsupportedFileOperationException
 1010    * @throws FileNotFoundException
 1011    * @throws IOException
 1012    * @throws PermissionDeniedException
 1013    */
 1014       public void createSymbolicLink(String link, String target)
 1015           throws UnsupportedFileOperationException, FileNotFoundException, 
 1016               IOException, PermissionDeniedException {
 1017           throw new UnsupportedFileOperationException(
 1018               "Symbolic links are not supported by the Virtual File System");
 1019       }
 1020   
 1021       /**
 1022    *
 1023    *
 1024    * @param path
 1025    *
 1026    * @return
 1027    *
 1028    * @throws IOException
 1029    */
 1030       public boolean fileExists(String path) throws IOException {
 1031           File f = new File(VirtualFileSystem.translateVFSPath(path));
 1032   
 1033           return f.exists();
 1034       }
 1035   
 1036       public String getDefaultPath(String username) throws FileNotFoundException {
 1037           return getVFSHomeDirectory(username);
 1038       }
 1039   
 1040       /**
 1041    *
 1042    *
 1043    * @param path
 1044    *
 1045    * @return
 1046    *
 1047    * @throws IOException
 1048    * @throws FileNotFoundException
 1049    */
 1050       public String getCanonicalPath(String path)
 1051           throws IOException, FileNotFoundException {
 1052           File f = new File(VirtualFileSystem.translateVFSPath(path));
 1053   
 1054           return f.getCanonicalPath();
 1055       }
 1056   
 1057       /**
 1058    *
 1059    *
 1060    * @param path
 1061    *
 1062    * @return
 1063    *
 1064    * @throws FileNotFoundException
 1065    */
 1066       public String getRealPath(String path) throws FileNotFoundException {
 1067           log.debug("Get real path for '" + path + "'");
 1068           path = VirtualFileSystem.translateVFSPath(path);
 1069           log.debug("Translated VFS is '" + path + "'");
 1070           path = VirtualFileSystem.translateNFSPath(path);
 1071           log.debug("Translated NFS is '" + path + "'");
 1072   
 1073           return path;
 1074       }
 1075   
 1076       /**
 1077    *
 1078    *
 1079    * @param username
 1080    * @param path
 1081    * @param permissions
 1082    *
 1083    * @throws PermissionDeniedException
 1084    * @throws FileNotFoundException
 1085    * @throws IOException
 1086    */
 1087       public void verifyPermissions(String username, String path,
 1088           String permissions)
 1089           throws PermissionDeniedException, FileNotFoundException, IOException {
 1090           String vfspath = translateNFSPath(path);
 1091   
 1092           if (permissionHandler == null) {
 1093               VFSMount mount = getMount(vfspath);
 1094               VFSPermission perm;
 1095   
 1096               if (mount.getPermissions().containsKey(SshThread.getCurrentThreadUser())) {
 1097                   perm = (VFSPermission) mount.getPermissions().get(SshThread.getCurrentThreadUser());
 1098               } else if (mount.getPermissions().containsKey("default")) {
 1099                   perm = (VFSPermission) mount.getPermissions().get("default");
 1100               } else {
 1101                   throw new PermissionDeniedException(
 1102                       "No permissions set for mount");
 1103               }
 1104   
 1105               if (!perm.verifyPermissions(permissions)) {
 1106                   throw new PermissionDeniedException("Permission denied for " +
 1107                       translateNFSPath(path));
 1108               }
 1109           } else {
 1110               permissionHandler.verifyPermissions(username, path, permissions);
 1111           }
 1112       }
 1113   
 1114       class OpenFile {
 1115           File f;
 1116           RandomAccessFile raf;
 1117           UnsignedInteger32 flags;
 1118   
 1119           public OpenFile(File f, RandomAccessFile raf, UnsignedInteger32 flags) {
 1120               this.f = f;
 1121               this.raf = raf;
 1122               this.flags = flags;
 1123           }
 1124   
 1125           public File getFile() {
 1126               return f;
 1127           }
 1128   
 1129           public RandomAccessFile getRandomAccessFile() {
 1130               return raf;
 1131           }
 1132   
 1133           public UnsignedInteger32 getFlags() {
 1134               return flags;
 1135           }
 1136       }
 1137   
 1138       class OpenDirectory {
 1139           File f;
 1140           File[] children;
 1141           int readpos = 0;
 1142           String path;
 1143           String realPath;
 1144   
 1145           public OpenDirectory(String realPath, String path, File f) {
 1146               this.path = path;
 1147               this.realPath = realPath;
 1148               this.f = f;
 1149               this.children = f.listFiles();
 1150           }
 1151   
 1152           public File getFile() {
 1153               return f;
 1154           }
 1155   
 1156           public File[] getChildren() {
 1157               return children;
 1158           }
 1159   
 1160           public int getPosition() {
 1161               return readpos;
 1162           }
 1163   
 1164           public void setPosition(int readpos) {
 1165               this.readpos = readpos;
 1166           }
 1167       }
 1168   }

Save This Page
Home » j2ssh-0.2.9-src » com.sshtools.daemon.vfs » [javadoc | source]