diff --git a/upload.pm b/upload.pm index 75353cc..814d300 100644 --- a/upload.pm +++ b/upload.pm @@ -128,42 +128,52 @@ sub handle_put_body { return HTTP_FORBIDDEN; # Assume EACCES. } - if (sysopen(my $fh, $file_path, O_WRONLY|O_CREAT|O_EXCL, $file_mode)) { - if (not binmode($fh)) { - $r->log_error($!, "Cannot set binary mode for $file_path"); - return HTTP_INTERNAL_SERVER_ERROR; - } + my $request_body = $r->request_body; + my $request_body_file = $r->request_body_file; - my $request_body = $r->request_body; - my $request_body_file = $r->request_body_file; - - if ($request_body) { + if ($request_body) { + if (sysopen(my $fh, $file_path, O_WRONLY|O_CREAT|O_EXCL, $file_mode)) { + if (not binmode($fh)) { + $r->log_error($!, "Cannot set binary mode for $file_path"); + return HTTP_INTERNAL_SERVER_ERROR; + } if (not syswrite($fh, $request_body)) { $r->log_error($!, "Cannot write $file_path"); return HTTP_INTERNAL_SERVER_ERROR; } - } elsif ($request_body_file) { - if (not move($request_body_file, $fh)) { - $r->log_error($!, "Cannot move data to $file_path"); + if (not close($fh)) { + $r->log_error($!, "Cannot close $file_path"); return HTTP_INTERNAL_SERVER_ERROR; } - } else { # Huh? - $r->log_error(0, "Got no data to write to $file_path"); - return HTTP_BAD_REQUEST; - } - if (not close($fh)) { - $r->log_error($!, "Cannot close $file_path"); + } elsif ($!{EEXIST}) { + $r->log_error($!, "Won't overwrite $file_path"); + return HTTP_CONFLICT; + } elsif ($!{EACCES}) { + $r->log_error($!, "Cannot create $file_path"); + return HTTP_FORBIDDEN; + } else { + $r->log_error($!, "Cannot open $file_path"); return HTTP_INTERNAL_SERVER_ERROR; } - } elsif ($!{EEXIST}) { - $r->log_error($!, "Won't overwrite $file_path"); - return HTTP_CONFLICT; - } elsif ($!{EACCES}) { - $r->log_error($!, "Cannot create $file_path"); - return HTTP_FORBIDDEN; - } else { - $r->log_error($!, "Cannot open $file_path"); - return HTTP_INTERNAL_SERVER_ERROR; + } elsif ($request_body_file) { + # We could hand over the file handle created by the above sysopen() as + # the second argument to move(), but we want to let move() use rename() + # if possible. + if (-e $file_path) { + $r->log_error(0, "Won't overwrite $file_path"); + return HTTP_CONFLICT; + } + if (not move($request_body_file, $file_path)) { + $r->log_error($!, "Cannot move data to $file_path"); + return HTTP_INTERNAL_SERVER_ERROR; + } + if (chmod($file_mode, $file_path) < 1) { + $r->log_error($!, "Cannot change permissions of $file_path"); + return HTTP_INTERNAL_SERVER_ERROR; + } + } else { # Huh? + $r->log_error(0, "Got no data to write to $file_path"); + return HTTP_BAD_REQUEST; } return HTTP_CREATED; }