[ 
https://issues.apache.org/jira/browse/TRANSACTION-19?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#action_12505411
 ] 

Bojan Vukojevic commented on TRANSACTION-19:
--------------------------------------------

Here is the use case:
1. Login in to Linux/Unix box
2. Create a file (i.e. touch /tmp/testFile)
3. Create a symlink in the same directory to this file (i.e. ln -s 
/tmp/testFile /tmp/testFileLink)
  * at the end you should see something like:
     ls -l /tmp/testFile*
     -rw-r--r--  1 bvukojev --- 0 Jun 15 15:58 /tmp/testFile
     lrwxrwxrwx  1 bvukojev ---- 13 Jun 15 15:58 /tmp/testFileLink -> 
/tmp/testFile
4. Then write a simple test program that should first delete the file then the 
link; something like:

                       public static void main(String[] args) {
                
                final Log log = 
LogFactory.getLog(TestJakartaCommons.class.getName());
                final LoggerFacade sLogger = new CommonsLoggingLogger(log);
                // validate setup is right:
                if (new File("/tmp/testFileLink").exists()
                                && (new File("/tmp/testFile").exists())) {
                        FileResourceManager frm = new 
FileResourceManager("/tmp", "work",
                                        false, sLogger);
                        String txId = null;
                        try {
                                frm.start();
                                txId = frm.generatedUniqueTxId();
                                frm.startTransaction(txId);
                                frm.deleteResource(txId, "testFile");
                                frm.deleteResource(txId, "testFileLink");
                                frm.commitTransaction(txId);                    
        
                        } catch (ResourceManagerSystemException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                                try {
                                        frm.rollbackTransaction(txId);
                                } catch (Exception e1) {
                                        e1.printStackTrace();
                                }
                        } catch (ResourceManagerException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                                try {
                                        frm.rollbackTransaction(txId);
                                } catch (Exception e1) {
                                        e1.printStackTrace();
                                }
                        }
                        try {
                                
frm.stop(FileResourceManager.SHUTDOWN_MODE_NORMAL);
                        } catch (ResourceManagerSystemException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                        }
                }
                               }
5. Run the program:
       Jun 15, 2007 4:21:25 PM 
org.apache.commons.transaction.util.CommonsLoggingLogger logInfo
INFO: Starting RM at '/tmp' / 'work'
Jun 15, 2007 4:21:25 PM 
org.apache.commons.transaction.util.CommonsLoggingLogger logInfo
INFO: Started RM
Jun 15, 2007 4:21:25 PM 
org.apache.commons.transaction.util.CommonsLoggingLogger logInfo
INFO: Stopping RM at '/tmp' / 'work'
Jun 15, 2007 4:21:25 PM 
org.apache.commons.transaction.util.CommonsLoggingLogger logInfo
INFO: Stopped RM

6. All was good! No exceptions! Check the file system that both the file and 
the link is gone:
                ls -l /tmp/test*
                lrwxrwxrwx  1 bvukojev ----- 13 Jun 15 15:58 /tmp/testFileLink 
-> /tmp/testFile
7. SURPRISE :) Link is still there, only now it is dangling! 

The issue in in the code below in the applyDeletes method:
    if (targetFile.exists()) {
                        if (!targetFile.delete()) {
                            throw new IOException("Could not delete file " + 
removeFile.getName()
                                    + " in directory targetDir");
                        }
                    } 

After the file is deleted, Java will return "false" for "targetFile.exists()" 
when target file is a link that is dangling. 

So the suggested solution is to modify the above code as follows:

     if (targetFile.exists()) {
                        if (!targetFile.delete()) {
                            throw new IOException("Could not delete file " + 
removeFile.getName()
                                    + " in directory targetDir");
                        }
                    } else if(!targetFile.isFile()){
                        //this is likely a dangling link                        
                        targetFile.delete();
                    }
             
Please let me know if any more details is necessary.. I'll be happy to provide 
more details. I am very pleasantly surprised with the turnaround time... 

Thx!


> applyDeletes method does not delete dangling links
> --------------------------------------------------
>
>                 Key: TRANSACTION-19
>                 URL: https://issues.apache.org/jira/browse/TRANSACTION-19
>             Project: Commons Transaction
>          Issue Type: Bug
>    Affects Versions: 1.2
>         Environment: Linux CentOS, Java 1.5
>            Reporter: Bojan Vukojevic
>            Assignee: Oliver Zeigermann
>
> applyDeletes method will not delete any dangling links. Even if the link was 
> valid, code may run into this situation if the file is passed to be deleted 
> before link is registered for deletion. Code will delete the file 
> effectivelly creating a dangling link that will  not be deleted. 
> The fix might be another change to applyDeletes method i.e. something like:
> protected static void applyDeletes(File removeDir, File targetDir, File 
> rootDir) throws IOException {
>         if (removeDir.isDirectory() && targetDir.isDirectory()) {
>             File[] files = removeDir.listFiles();
>             for (int i = 0; i < files.length; i++) {
>                 File removeFile = files[i];
>                 File targetFile = new File(targetDir, removeFile.getName());
>                 if (!removeFile.isDirectory()) {
>                     if (targetFile.exists()) {
>                         if (!targetFile.delete()) {
>                             throw new IOException("Could not delete file " + 
> removeFile.getName()
>                                     + " in directory targetDir");
>                         }
>                     } else if(!targetFile.isFile()){  //============ CHANGE 
> to delete dangling link=============
>                       //this is likely a dangling link                        
>                       targetFile.delete();  
>                     }
>                     // indicate, this has been done
>                     removeFile.delete();
>                 } else {
>                     applyDeletes(removeFile, targetFile, rootDir);
>                 }
>                 // delete empty target directories, except root dir
>                 if (!targetDir.equals(rootDir) && targetDir.list().length == 
> 0) {
>                     targetDir.delete();
>                 }
>             }
>         }
>     }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to