7

Thinking creation of the file in question lags a bit behind the offending function, I tried running a while loop to buy a little time before calling rename.

$no_file = 1;   
while($no_file && $no_file < 300)
{   // generation of Worksheet.xls may lag behind function -- WAIT FOR IT
    if(file_exists($old_path))
    {   $no_file = 0;
        rename($old_path, $new_path);
    }   else $no_file++;
}
if($no_file) die("Error: Worksheet.xls not found");

In this configuration, I'm thinking rename() can only be called if file_exists() returns true, but for the life of me I can't figure out how / why then rename() gets called and then fails returning...

PHP Warning: rename(C:\wamp\www\demox/wp-content/plugins/cat-man/store-manager/summary/worksheets/Worksheet.xls,C:\wamp\www\demox/wp-content/plugins/cat-man/store-manager/summary/statements/TESTING/2012/Worksheet.xls) No such file or directory...

WallabyKid
  • 503
  • 2
  • 5
  • 16
  • I'm not sure this will corect the problem, but try replacing forward slashes with DIRECTORY_SEPARATOR constant. – JanLikar Jan 18 '13 at 23:41

3 Answers3

14

It's probably telling you statements/TESTING/2012/ doesn't exist. Create those directories with mkdir() so it will be able to save the file.

mkdir( 'C:\wamp\www\demox/wp-content/plugins/cat-man/store-manager/summary/statements/TESTING/2012/', 777, true);
nickb
  • 59,313
  • 13
  • 108
  • 143
  • Thanks for the follow-up! Strange... sometimes it works... sometimes it doesn't and creating the directory first only seems to complicate things further. I read somewhere just a bit ago (can't find where now) something about a problem with rename on a windows platform once a file has has been opened... read... renamed before in a given session? I'll have to do some more digging. – WallabyKid Jan 19 '13 at 00:15
2

However remote, this code opens the possibility of a race condition where your file could change between checking it exists and attempting to rename it. Better to attempt the rename immediately from a try/catch block and deal with failure directly.

You should explicitly exit the loop with a break statement after the rename. And setting $no_file = 0; before the rename is celebrating victory prematurely.

Also, if you're looping with the intention of delaying, you need to sleep execution, otherwise the loop will complete as fast as PHP can process it. Take a look at time_nanosleep. If you time that while loop you'll see it finishes very, very quickly:

$time_start = microtime(true);
$x = 0;
while ($x < 300) {
    file_exists("index.php");
    $x++;
}
echo sprintf("300 loops in %.9f seconds", microtime(true) - $time_start);

// 300 loops in 0.000626087 seconds
joemaller
  • 19,579
  • 7
  • 67
  • 84
1

Ok, mkdir() did solve the problem! Here's the solution in context.

$old_path = $smry_dir."worksheets/Worksheet.xls";
if(@$store_options->paypal_live ==='false')
{   $new_path = $smry_dir."statements/TESTING/$reporting_year";
}   else $new_path = $smry_dir."statements/$reporting_year";
if(!is_dir($new_path)) mkdir($new_path, 777, true);
rename($old_path, $new_path."/Worksheet.xls");

Thanks again for all the help! The statements DIR always exists, and I found that while rename() would write the single new sub-directory $reporting_year without complaint, it wouldn't/couldn't write recursive subs "TESTING/$reporting_year".

mkdir's recursive parameter to the rescue!

WallabyKid
  • 503
  • 2
  • 5
  • 16