Click to See Complete Forum and Search --> : Simple Create New File
telconstar99
11-12-2006, 03:48 AM
Hello,
This is my first attempt to create a new file in perl. I have this code sitting in my cgi-bin directory of my webserver:
#!/usr/bin/perl
use CGI ':standard';
print header();
open (COLOURS,">colours.txt");
print COLOURS "My favourite colour is red\n";
close COLOURS;
However, when I run this with my browser I get an empty screen (which is what I would expect) but no file seems to be created. I'm assuming the file would be created in my cgi-bin directory. My path to perl is 100% correct. Any ideas?
It runs as expected on Windows & Linux. Are you sure "colours.txt" was "NOT" created in your cgi-bin?
What output do you get when you run the code below?
#!/usr/bin/perl
use strict;
use Cwd 'realpath';
use CGI ':standard';
use CGI::Carp 'fatalsToBrowser';
my $file = 'cyco_colours.txt';
open COLOURS, ">$file" or die $!;
print COLOURS "My favourite colour is blue\n";
close COLOURS;
print header, "Full path to $file: ", realpath($file);
telconstar99
11-12-2006, 11:53 AM
I appreciate such a fast response.
I'm positive it's not creating the file in the cgi-bin directory. I copy and pasted your code into a file called test.cgi and when I ran it I got this.
Software error:
Permission denied at /web/sites/www.domain.com/cgi-bin/test.cgi line 10.
For help, please send mail to the webmaster (webmaster@domain.com), giving this error message and the time and date of the error.
OK, now we're getting somewhere. The error is very helpful in troubleshooting the problem, which is a permission issue. My guess is that your umask setting (configured on the server) is denying write access at the default level.
Add this line right after opening the file.chmod 0666, $file;
If that doesn't do it, then we'll need to check your umask value and go from there.
telconstar99
11-12-2006, 05:20 PM
Thanks for the reply CyCo. I added your line and still have the same problem. Just to double check my code now looks like this:
#!/usr/bin/perl
use strict;
use Cwd 'realpath';
use CGI ':standard';
use CGI::Carp 'fatalsToBrowser';
my $file = 'cyco_colours.txt';
open COLOURS, ">$file" or die $!;
chmod 0666, $file;
print COLOURS "My favourite colour is blue\n";
close COLOURS;
print header, "Full path to $file: ", realpath($file);
What's the next debug step?
Bummer!
What output do you get when you run this little snippet?#!/usr/bin/perl
use CGI ':standard';
use CGI::Carp 'fatalsToBrowser';
print header, umask;
telconstar99
11-12-2006, 06:32 PM
It outputted this:
18
What does that mean?
telconstar99
11-18-2006, 02:19 PM
BUMP...Anybody know what this means? Google isn't helping much.
yitzle
11-18-2006, 07:53 PM
Idea:
Change
open (COLOURS,">colours.txt");
to
open (COLOURS,">./colours.txt");
telconstar99
11-19-2006, 03:28 PM
Nope that still doesn't work. Any ideas where the problem is? Might this be a server config error?
After re-reading this thread, I believe the best way to get to the bottom of this is to contact your host and find out what restrictions they have configured for your site. If you are on a free host or some other type of restricted hosting plan, then you probably won't be allowed to do certain things.
rocknbil
11-24-2006, 03:24 AM
There is one more thing to try. This is a nuts and bolts method, but it works for me.
Remember you are trying to write to the directory in which the script is being executed,
my $file = 'cyco_colours.txt';
You may not have permissions to write to that directory. Another possibility is that depending on the server configuration, if the current path is not in @INC it may be trying to write to wherever perl thinks you are at that moment - which may be #!/usr/bin/perl. You certainly won't be allowed to write a file there. :D
So begin by a) defining and using the full path to where you want to write, and b) making sure you have permissions to write to that location. In this scenario create a directory called data outside of your cgi-bin:
/web/sites/www.domain.com/data/
Chmod it to 666, if that doesn't work test chmod it to 777 just to see if it's a permissions issue.
Second I like to write my own error handlers to avoid code and module bloat, but that's just me. Note my change in the or, and the added error subroutine. One last note - the $! variable holds system errors, so if the error is permission denied you can see it immediately in the response via the error sub.
#!/usr/bin/perl
$file = '/web/sites/www.domain.com/data/cyco_colours.txt';
open COLOURS, ">$file" or &error("cannot write file $!");
print COLOURS "My favourite colour is blue\n";
close COLOURS;
print "content-type: text/html\n\n";
print "If you see this, $file was printed";
sub error {
my ($err);
$err = shift(@_);
print "content-type: text/html\n\n";
print "Here is your error, fix it: $err";
exit 0; ## to stop script immediately if you encounter an error
}
JohnGH
11-27-2006, 08:17 AM
...
I have this code sitting in my cgi-bin directory of my webserver:
#!/usr/bin/perl
...
open (COLOURS,">colours.txt");
...
However, when I run this with my browser
...
no file seems to be created. I'm assuming the file would be created in my cgi-bin directory.
This is *hopefully* because the webserver process doesn't have write access to the directory the script is running in (as your say - presumably your cgi-bin directory)
This is a ***GOOD*** thing.
Your cgi-bin directory should *NOT* be writable by the user that the webserver runs the scripts as, otherwise, when someone finds something exploitable in one of your scripts (yes, I said "when", not "if" - because these things happen!) it will be simple for them to use that to create their own script in your cgi-bin directory and then run it to do whatever they want on your server that the user that your webserver runs as has access to do.
Data files should either be created manually first
(e.g. use 'touch colours.txt' on Linux/Unix, or 'type nul > colours.txt' on windows or create an empty colours.txt locally and upload it if you don't have shell access)
and made so that the web process can write to them (if they need to be written to)
(on Linux/Unix this is chown [WEBSERVER_USER] colours.txt and/or chmod +w colours.txt)
(read http://www.linuxmanpages.com/man1/chown.1.php and http://www.linuxmanpages.com/man1/chmod.1.php )
Or... better still, they should preferrably be stored in another directory that the webserver process can read from/write to but not execute programs in.
(if someone could write to colours.txt they may be able to write code into that and run it too if it is executable (??[x]??[x]??[x] on Linux/Unix) - unless your webserver only runs scripts by extension (e.g. will run .cgi or .pl but not .txt) ( as per AddHandler cgi-script (whatever) and ExecCGI )
John
JohnGH
11-27-2006, 08:44 AM
So begin by a) defining and using the full path to where you want to write, and b) making sure you have permissions to write to that location. In this scenario create a directory called data outside of your cgi-bin:
/web/sites/www.domain.com/data/
Chmod it to 666, if that doesn't work test chmod it to 777 just to see if it's a permissions issue.
Don't chmod dirs to 666 - dirs need to be executable to be used... try this:
$ mkdir test
$ chmod 666 test
$ touch test/file
touch: cannot touch `test/file': Permission denied
$ cd test
-bash: cd: test: Permission denied
$ chmod +x test
$ touch test/file
$ cd test/
$ pwd
/home/john/test
$ ls -la .
total 8
drwxrwxrwx 2 john john 4096 2006-11-27 14:21 .
drwxr-xr-x 10 john john 4096 2006-11-27 14:19 ..
-rw-r--r-- 1 john john 0 2006-11-27 14:21 file
IHTH
Kind regards,
John
yitzle
11-27-2006, 09:46 AM
I don't think that is wise.
You got +rwx or 777 for your directories
That means you are letting anyone do anything
Directories should be 711 or 755 (eXecute or Read + eXecute)
Don't give write permission on a directory.
Only on select files.
rocknbil
11-28-2006, 12:49 PM
A directory does not need to be executable to write to it.
yitzle
11-28-2006, 01:38 PM
It does need to be executable for a browser to read a document (eg HTML) from it.
Not sure what permissions are needed for PHP to read from it...
JohnGH
11-29-2006, 05:27 AM
A directory does not need to be executable to write to it.
Have you tested what you're saying?
or are you just giving advice off the top of your head?
What OS are you referring to?
On Linux I get this:
$ mkdir test
$ chmod -x test
$ touch test/file
touch: cannot touch `test/file': Permission denied
$ echo > test/file
bash: test/file: Permission denied
It certainly does need to be executable to write to it on my machine!
When in doubt, unit test :)
yitzle
11-29-2006, 09:07 AM
Why doesn't anyone chmod with numerical values? eg 666 (no exec)?
rocknbil
11-29-2006, 06:54 PM
You all sounded so self confident you almost had me convinced. Here you go. Only the paths, machine names, and dates were changed.
Script:
#/usr/bin/perl -w
$root = '/path/to/domain/root';
$testdir = "$root/test_dir";
$ver = `/path/to/server/software -v`;
print "Tested on:\n $ver\n";
if (! -e $testdir) {
print "creating directory . . .\n";
mkdir ("$testdir", "0666") || &error("Cannot create directory $!");
}
print "printing to file . . .\n";
open (FILE,">$testdir/test.txt") || &error("Cannot create file $!");
print FILE "Hello. 0777 is evil.";
close (FILE);
print "did it write?\n";
open (FILE,"$testdir/test.txt") || &error("Cannot read file $!");
$line = <FILE>;
close (FILE);
if ($line) {
print "yep.\n";
print "\nFile contents: $line \n";
}
else{ print " Nope\n"; }
print "deleting test stuff\n";
unlink "$testdir/test.txt";
rmdir ($testdir);
sub error {
my ($err);
$err=shift(@_);
print "oops. Error. $err";
exit 0;
}
And here is my output.
[*******@server-name cgi]# perl testwrite.pl
Tested on:
Server version: Apache/1.3.27 (Unix)
Server built: **************
creating directory . . .
printing to file . . .
did it write?
yep.
File contents: Hello. 0777 is evil.
deleting test stuff
Executed from domain cgi-bin. Directory created at domain root. Checked after running, file and directory were successfully deleted.
rocknbil
11-29-2006, 07:11 PM
If you have further doubts, see attached, although I did crop it down so VB software doesn't resize it and make it illegible. The yellow blocks are as above, for anonymity.
JohnGH
11-30-2006, 12:32 PM
I'm sorry, maybe I should have been more specific...
when in doubt, unit test using an appropriate context...
i.e. same rights/permissions etc...
notice the pretty # prompt???
Now try running that as someone other than root...
It will fail:
$ ./test.pl
creating directory . . .
printing to file . . .
oops. Error. Cannot create file Permission denied
$ su -
# cd ~/john/test_dir_perms/
# ./test.pl
printing to file . . .
did it write?
yep.
File contents: Hello. 0777 is evil.
deleting test stuff
Please tell me your webserver doesn't run as root!
John
JohnGH
11-30-2006, 01:40 PM
Why doesn't anyone chmod with numerical values? eg 666 (no exec)?
You can... the "numerical values" are also called "octal mode" and also "Absolute mode" - that's because it trashes what ever was set previously.
A lot of people don't find it easy to understand octal modes.
I remember somewhere a long time ago reading that it was preferred to use the 'rwxXstugo' syntax and I thought I once read or was told that octal modes were being deprecated, but personally I don't think that's likely to happen (or a good idea!)
Modes and how to set them in octal were one of the first things I remember having explained to me on Unix - so I probably learned them in my first week, but I do recall trying to remember whether I was supposed to be reading man ls or man chmod to find out about sticky bits and setuid etc.
Specifying the mode in octal is fine if you don't care what it was already, but if it's set the way it is for a particular reason (let's say people in the file's group need +w) and you only to turn on or off a bit for "other" and not affect user and group then it's simpler to specify your change as 'o [+-][rwx?]' than having to figure out what user and group are already and make that part of the number you set...
Another example... let's say you're writing a shell script to install some software you're distributing, and you need to set a particular file or directory that already exists to be writable by group... the mode on the machine it's being installed on could be anything... let's say it's sticky or setuid already - if you go along and do chmod 755 file then you're going to trash those special bits.
Also, if you read man chmod on Solaris you will find it says this at the bottom:
"NOTES
Absolute changes don't work for the set-group-ID bit of a directory.
You must use g+s or g-s."
- that's because once you get into +s or +t the mode numbers get much more complicated.
Have a play with this:
http://pastebin.ca/262651
IHTH
John
yitzle
11-30-2006, 03:16 PM
That makes sense, I guess.
Thanks for the post!