tags:

views:

278

answers:

6

OK, so this is so simple but for the life of me I can't figure out why the code below doesn't work.

I'm trying to simply write a CGI script that creates sequentially numbered files. I'm using a counter (stored in a separate file) to keep track of the last ordinal used, and then generating a unique filename using sprintf. The uniquely named file is NOT created. I suspect it's an issue with sprintf(...) not correctly converting $ordinal to a scalar?

If I assign $ordinal by say replacing the line $ordinal = <NUMPHOTOS>; with $ordinal=42; the code works fine and a file named 00000042.jpg is created.

What am I doing wrong here?

Help!

my ($filename, $ordinal);

local $| = 1;
print "Content-type: text/plain\n\n";

# NOTE: $ordinal is set to zero if the file doesn't exist
open (NUMPHOTOS, "<numpics.dat");
$ordinal = <NUMPHOTOS>;
print "ordinal = $ordinal";
$filename = sprintf("%08d.jpg", $ordinal );
close (NUMPHOTOS);

open (NUMPHOTOS, ">numpics.dat");
$ordinal += 1;
print NUMPHOTOS $ordinal;
close (NUMPHOTOS);

open ( UPLOADFILE, ">$filename" ) or die "ERROR: can't open $filename: $! \n"; 
print "writing out file $filename...\n";
print UPLOADFILE 'hello world';
close UPLOADFILE;
+1  A: 

Perl have no problem sprintf() a string-number --- it is not strongly typed.

Make sure you have the permission to create files with CGI. Some web hosting require chmod 755 on the directory you write.

J-16 SDiZ
A good idea might be to add error checking (always check errors on system commands like open()) on the open call for the NUMPHOTOS file when you are writing to it. also: what is the error message when the file is not created and what is the filename which is generated?
Knut Haugen
adding 'use strict;' and 'use warnings;' to script could also give you some clues to what is wrong.
Knut Haugen
+3  A: 

First add "use strict;use warnings;use diagnostics;use Fatal qw/:void open close/;" at start of your code, after #!.

my $ordinal=0;
if (-e 'numpics.dat') {
 open (my $NUMPHOTOS, "<","numpics.dat");
 $ordinal = <$NUMPHOTOS>;
 close ($NUMPHOTOS);
}
print "ordinal = $ordinal\n";
my $filename = sprintf("%08d.jpg", $ordinal );

Also it is a good idea to read Ovid's CGI Course.

Alexandr Ciornii
+1  A: 

As everybody mentioned, you should:

Use strictures --

use strict;
use warnings;
use diagnostics; # will help you understand the error messages

Check the file name, the current directory and the permissions on writing the filename;

Use the 3-parameter open, and lexical filehandles, AND check the operations --

open my $uploadfile, '>', $filename or die "could not open $filename: $!";
print $uploadfile "Hello, uploadfile!\n" or die "could not print at $filename: $!";
close $uploadfile or die "could not close $filename: $!";
Massa
A: 
  1. Does print "ordinal = $ordinal"; print "ordinal = 42"?
  2. What number is getting stored in numpics.dat after a run?
  3. Is it possible the script is writing 00000000.jpg over and over again?
10rd_n3r0
A: 

Is there a newline in the file? What happens to $ordinal if you change:

$ordinal = <NUMPHOTOS>;

to

<NUMPHOTOS> =~ /(\d+)/ and $ordinal = $1;

?

A: 

Here is my attempt to fix up your program.

I think your problem was the lack of chomp();

use strict;
use warnings;
use autodie; # don't need to check the return value of open() or close()

my( $filename, $ordinal );

local $| = 1;
print "Content-type: text/plain\n\n";

# NOTE: $ordinal is set to zero if the file doesn't exist
{
  open( my $num_photos, '<', 'numpics.dat' );
  $ordinal = <$num_photos>;
  chomp $ordinal; # <--

  print "ordinal = $ordinal\n";
  $filename = sprintf("%08d.jpg", $ordinal );
  print "filename = $filename\n";
  close ($num_photos);
}
{
  open( my $num_photos, '>', 'numpics.dat' );
  $ordinal += 1;
  print {$num_photos} $ordinal;
  close( $num_photos );
}
{
  open( my $upload_file, '>', $filename );
  print "writing out file $filename...\n";
  print {$upload_file} 'hello world';
  close $upload_file;
}

Note that this still doesn't attempt to resolve locking problems. So if this needs to be atomic, you may want to ask another question

Brad Gilbert
See `perldoc -q "I still don't get locking."` http://perldoc.perl.org/perlfaq5.html#I-still-don%27t-get-locking.--I-just-want-to-increment-the-number-in-the-file.--How-can-I-do-this%3f
Sinan Ünür
That wasn't the problem, the problem was the lack of `chomp()`.
Brad Gilbert