001package com.hfg.util;
002
003import java.io.File;
004import java.io.IOException;
005import java.util.regex.Pattern;
006
007//------------------------------------------------------------------------------
008/**
009 * Unix utilities.
010 *
011 * @author J. Alex Taylor, hairyfatguy.com
012 */
013//------------------------------------------------------------------------------
014// com.hfg XML/HTML Coding Library
015//
016// This library is free software; you can redistribute it and/or
017// modify it under the terms of the GNU Lesser General Public
018// License as published by the Free Software Foundation; either
019// version 2.1 of the License, or (at your option) any later version.
020//
021// This library is distributed in the hope that it will be useful,
022// but WITHOUT ANY WARRANTY; without even the implied warranty of
023// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
024// Lesser General Public License for more details.
025//
026// You should have received a copy of the GNU Lesser General Public
027// License along with this library; if not, write to the Free Software
028// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
029//
030// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
031// jataylor@hairyfatguy.com
032//------------------------------------------------------------------------------
033
034public class UnixUtil
035{
036   //--------------------------------------------------------------------------
037   /**
038    Function to create a symbolic link.
039    @param inFrom the file being linked to.
040    @param inLink the file that will become the symbolic link.
041    @throws IOException
042    */
043   public static void symlink(File inFrom, File inLink)
044      throws IOException
045   {
046      boolean createLink = true;
047
048      if (isSymlink(inLink))
049      {
050         if (readlink(inLink).equals(inFrom.getPath()))
051         {
052            // The requested link already exists.
053            createLink = false;
054         }
055      }
056      else if (inLink.exists())
057      {
058         throw new IOException("Cannot replace regular file " + StringUtil.singleQuote(inFrom.getPath())
059               + " with a symlink!");
060      }
061
062      if (createLink)
063      {
064         String parent = inLink.getParent();
065         if (! StringUtil.isSet(parent)) parent = ".";
066
067         Executor exe = new Executor();
068         exe.setCommand("cd " + StringUtil.singleQuote(parent) + "; ln -s "
069               + StringUtil.singleQuote(inFrom.getPath()) + " " + StringUtil.singleQuote(inLink.getName()));
070
071         if (exe.exec() != 0)
072         {
073            throw new IOException("Error executing \"" + exe.getCommand() + "\": " + exe.getSTDERR());
074         }
075      }
076   }
077
078   //--------------------------------------------------------------------------
079   /**
080    Uses the 'stat' command to test if the specified file is a symbolic link.
081    */
082   public static boolean isSymlink(File inFile)
083   {
084      boolean result = false;
085
086      Executor exe = new Executor();
087
088      if (OS.value() == OS.Mac)
089      {
090         exe.setCommand("stat -f '%HT' " + StringUtil.singleQuote(inFile.getPath()));
091         if (exe.exec() != 0
092               && exe.getSTDERR().indexOf("No such file") < 0)
093         {
094            throw new RuntimeException("Error executing \"" + exe.getCommand() + "\": " + exe.getSTDERR());
095         }
096         else if (exe.getSTDOUT().trim().equals("Symbolic Link"))
097         {
098            result = true;
099         }
100      }
101      else
102      {
103         exe.setCommand("stat " + StringUtil.singleQuote(inFile.getPath()));
104         if (exe.exec() != 0
105               && exe.getSTDERR().indexOf("No such file") < 0)
106         {
107            throw new RuntimeException("Error executing \"" + exe.getCommand() + "\": " + exe.getSTDERR());
108         }
109         else if (exe.getSTDOUT().contains("symbolic link"))
110         {
111            result = true;
112         }
113      }
114
115      return result;
116   }
117
118   //--------------------------------------------------------------------------
119   /**
120    Uses the 'readlink' command to read the contents of a symbolic link.
121    */
122   public static String readlink(File inFile)
123         throws IOException
124   {
125      if (! isSymlink(inFile))
126      {
127         throw new IOException(StringUtil.singleQuote(inFile.getPath()) + " is not a symlink!");
128      }
129
130      Executor exe = new Executor();
131      exe.setCommand("readlink " + StringUtil.singleQuote(inFile.getPath()));
132
133      if (exe.exec() != 0)
134      {
135         throw new IOException("Error executing \"" + exe.getCommand() + "\": " + exe.getSTDERR());
136      }
137
138      return exe.getSTDOUT().trim();
139   }
140}