
/* 0123456789012345678901234567890123456789012345678901234567890123456789789 */

/*
 * edc_file.java
 *
 * This file is part of cd_create.
 *
 * cd_create 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.
 *
 * cd_create 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 cd_create; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Copyright 2004 Abi Arroyo
 */

import java.io.*;
 
 public class utility {
 	
   // Create an bat file to execute custom external commands
   // Useful note:
   //    - To make script file creation easier, add a path variable assignment
   //    
   public static boolean createFile (String name, Object contents[]) {
      String newFile;
      File f;
      BufferedWriter outBuf;

      newFile = CDCase.tempDir + File.separator + name;
      f = new File (newFile);

      try {
         f.createNewFile();
         outBuf = new BufferedWriter (new FileWriter(f));
       
         // write contents of array to a bat file
         for (int i = 0; i < contents.length; i++) {
            outBuf.write((String) contents[i], 0, ((String) contents[i]).length());
            outBuf.newLine();
         }
         outBuf.close();
      
         return true;
      }
      catch (IOException e) {
         return false;
      }
   }
   
   // execute the string
   public static boolean exec (String file) {
      String cmd[]; 
      
      cmd = new String[1];
   
      cmd[0] = CDCase.tempDir + File.separator + file;
      
      int val = TestExec.runCmd (cmd);
      
      if (val != 0) {
         return false;
      }
      
      return true;
   }

   // execute command in array (elements used as arguments)
   public static boolean exec (String stuff[]) {
      int val = TestExec.runCmd (stuff);
      
      if (val != 0) {
         return false;
      }

      return true;
   }
   
   // wrapper function that returns the real size of a file
   public static long sizeOf (String someFile) {
      File f = new File(someFile);
      return (utility.sizeOf_real(f));
   }
   
   // This function computes the size of a file including the size of its
   // contents if it is a directory.
   // Returns:
   //    -1: If the given file is larger than MAX_CD_SIZE
   //     N: The size of the file
   private static long sizeOf_real (File someFile) {

      long sum = 0;                                    // the size of a given path
      final long err = -999999999;
      
      // logger.log(Level.SEVERE, "CDCase.sizeOf_real(): computing the size of: " + someFile.toString() + '\n');

      // file is unreadable
      if (!someFile.canRead() && CDCase.stopOnFailure) {

        // handle cases with sticky bit set (-rws--x--x)

         return err;
      }
      // compute size of individual file
      else if (!someFile.isDirectory()) {       

         try {
           if (!(someFile.getCanonicalPath()).equals(someFile.getAbsolutePath()) && !CDCase.isWindows) {
             // logger.log (Level.SEVERE, "CDCase.sizeOf_reall(): found symbolic link: " + someFile.toString() + '\n');
             String real_f = (someFile.getCanonicalFile()).toString();
             String link_f = (someFile.getAbsoluteFile()).toString();
           
             int link_i = link_f.lastIndexOf("/");
              int real_i = real_f.lastIndexOf("/");

              // a problem arises with double indirect links...
              // the function will not compute actual size of 1st level symbolic
              // link... this is because the real_f will point to the final destination, and not the
              // intermediary level link...
         
             sum = real_f.length() - (++real_i);
            }
           else
               sum = someFile.length();
        }
        catch (IOException e) {
           // logger.log (Level.SEVERE, "CDCase.sizeOf_real(): " + someFile.toString());
           // logger.log (Level.SEVERE, "CDCase.sizeOf_real(): exception caught: " + e + '\n');
            sum = err;
         }

        return sum;
      }
      else {      
         // At this point we now know we are dealing with a directory    
         String[] filesInDir = someFile.list();     // all of the files in a given path     
         File sizeCheck;                            // object used to check the size of files
         long temp;
            
        // sum += this.sizeOfDir();

         // check for empty directory    
         if ((filesInDir == null) && CDCase.stopOnFailure)  {
            // logger.log(Level.SEVERE, "CDCase.sizeOf_real(): error reading contents of directory: " + someFile.toString());
            return err;
         }

        // logger.log(Level.WARNING, "CDCase.sizeOf_real(): number of contents in dir " + someFile.toString() + " " + filesInDir.length + '\n');
        for (int i = 0; i < filesInDir.length; i++) {
           String subfile = someFile.toString() + File.separator + filesInDir[i];   
           sizeCheck = new File (subfile);
              
           // what happens when you can't read a directories file?!
           // how do you properly handle that error?
              
           // ... with the I/O Exception...
           temp = utility.sizeOf_real (sizeCheck);
           // logger.log(Level.WARNING, "CDCase.sizeOf_real(): subfile: " + subfile + " " + temp + '\n');
            if ((temp < 0) && CDCase.stopOnFailure) {
               return temp;
            }
            else if (temp >= 0) {      
               sum += temp;
            }
         }
      }
     
      return sum;
   }
 }
