merge r3138, r3139, r3157, r3158, r3159, r3164, r3165,

r3202, r3203, r3383, r3388, r3417, r3418:

Win32 (mostly) and some Unix file related fixes:

*) preserve errno while ngx_free()
*) win32 ngx_file_info() utf8 support
*) delete Win95 code
*) log file name for read/write errors
*) test incomplete WriteFile()
*) handle short pwrite() to log an error cause: ENOSPC, EDQUOT, or EFBIG
*) uniform ngx_directio_on/off() interface with other file functions
*) do not create Win32 drive letter in ngx_create_full_path()
*) ignore EACCES errors for top level directories in ngx_create_full_path()
*) fix Win32 error messages when an temporary file replaces an existent file:
   *) do not rename an already renamed file
   *) now ngx_win32_rename_file() returns error code
   *) do not log failure inside ngx_win32_rename_file()
*) fix Win32 error message when an temporary file replaces an existent file:
   return at once if ngx_win32_rename_file() was not failed
   and do not try to delete already the renamed temporary file
*) skip URI trailing spaces under Win32
*) disable Win32 short file names
This commit is contained in:
Igor Sysoev 2010-02-01 15:06:25 +00:00
parent 45ccf9336a
commit 553388bca1
7 changed files with 176 additions and 177 deletions

View File

@ -183,7 +183,15 @@ ngx_create_full_path(u_char *dir, ngx_uint_t access)
u_char *p, ch;
ngx_err_t err;
for (p = dir + 1; *p; p++) {
err = 0;
#if (NGX_WIN32)
p = dir + 3;
#else
p = dir + 1;
#endif
for ( /* void */ ; *p; p++) {
ch = *p;
if (ch != '/') {
@ -194,7 +202,14 @@ ngx_create_full_path(u_char *dir, ngx_uint_t access)
if (ngx_create_dir(dir, access) == NGX_FILE_ERROR) {
err = ngx_errno;
if (err != NGX_EEXIST) {
switch (err) {
case NGX_EEXIST:
err = 0;
case NGX_EACCES:
break;
default:
return err;
}
}
@ -202,7 +217,7 @@ ngx_create_full_path(u_char *dir, ngx_uint_t access)
*p = '/';
}
return 0;
return err;
}
@ -576,16 +591,10 @@ ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to, ngx_ext_rename_file_t *ext)
#if (NGX_WIN32)
if (err == NGX_EEXIST) {
if (ngx_win32_rename_file(src, to, ext->log) == NGX_OK) {
err = ngx_win32_rename_file(src, to, ext->log);
if (ngx_rename_file(src->data, to->data) != NGX_FILE_ERROR) {
return NGX_OK;
}
err = ngx_errno;
} else {
err = 0;
if (err == 0) {
return NGX_OK;
}
}

View File

@ -525,7 +525,7 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
of->fd = fd;
if (of->directio <= ngx_file_size(&fi)) {
if (ngx_directio_on(fd) == -1) {
if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
ngx_directio_on_n " \"%s\" failed", name);

View File

@ -510,7 +510,7 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx)
#if (NGX_HAVE_ALIGNED_DIRECTIO)
if (ctx->unaligned) {
if (ngx_directio_off(src->file->fd) == -1) {
if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
ngx_directio_off_n " \"%s\" failed",
src->file->name.data);
@ -528,7 +528,7 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx)
err = ngx_errno;
if (ngx_directio_on(src->file->fd) == -1) {
if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
ngx_directio_on_n " \"%s\" failed",
src->file->name.data);

View File

@ -784,9 +784,11 @@ ngx_http_process_request_line(ngx_event_t *rev)
p = r->uri.data + r->uri.len - 1;
if (*p == '.') {
if (*p == '.' || *p == ' ') {
while (--p > r->uri.data && *p == '.') { /* void */ }
while (--p > r->uri.data && (*p == '.' || *p == ' ')) {
/* void */
}
r->uri.len = p + 1 - r->uri.data;

View File

@ -22,7 +22,7 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"pread() failed, file \"%s\"", file->name.data);
"pread() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
@ -30,7 +30,8 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
if (file->sys_offset != offset) {
if (lseek(file->fd, offset, SEEK_SET) == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"lseek() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
@ -40,7 +41,8 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
n = read(file->fd, buf, size);
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed");
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"read() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
@ -57,57 +59,66 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
ssize_t
ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
{
ssize_t n;
ssize_t n, written;
ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
"write: %d, %p, %uz, %O", file->fd, buf, size, offset);
written = 0;
#if (NGX_HAVE_PWRITE)
n = pwrite(file->fd, buf, size, offset);
for ( ;; ) {
n = pwrite(file->fd, buf, size, offset);
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed");
return NGX_ERROR;
}
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"pwrite() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
if ((size_t) n != size) {
ngx_log_error(NGX_LOG_CRIT, file->log, 0,
"pwrite() has written only %z of %uz", n, size);
return NGX_ERROR;
file->offset += n;
written += n;
if ((size_t) n == size) {
return written;
}
offset += n;
size -= n;
}
#else
if (file->sys_offset != offset) {
if (lseek(file->fd, offset, SEEK_SET) == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"lseek() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
file->sys_offset = offset;
}
n = write(file->fd, buf, size);
for ( ;; ) {
n = write(file->fd, buf, size);
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed");
return NGX_ERROR;
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"write() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
file->offset += n;
written += n;
if ((size_t) n == size) {
return written;
}
size -= n;
}
if ((size_t) n != size) {
ngx_log_error(NGX_LOG_CRIT, file->log, 0,
"write() has written only %z of %uz", n, size);
return NGX_ERROR;
}
file->sys_offset += n;
#endif
file->offset += n;
return n;
}
@ -191,7 +202,7 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
if (file->sys_offset != offset) {
if (lseek(file->fd, offset, SEEK_SET) == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"lseek() failed");
"lseek() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
@ -202,13 +213,14 @@ ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
if (n == -1) {
ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
"writev() failed");
"writev() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
if ((size_t) n != size) {
ngx_log_error(NGX_LOG_CRIT, file->log, 0,
"writev() has written only %z of %uz", n, size);
"writev() \"%s\" has written only %z of %uz",
file->name.data, n, size);
return NGX_ERROR;
}
@ -393,7 +405,7 @@ ngx_directio_on(ngx_fd_t fd)
flags = fcntl(fd, F_GETFL);
if (flags == -1) {
return -1;
return NGX_FILE_ERROR;
}
return fcntl(fd, F_SETFL, flags | O_DIRECT);
@ -408,7 +420,7 @@ ngx_directio_off(ngx_fd_t fd)
flags = fcntl(fd, F_GETFL);
if (flags == -1) {
return -1;
return NGX_FILE_ERROR;
}
return fcntl(fd, F_SETFL, flags & ~O_DIRECT);

View File

@ -10,7 +10,7 @@
#define NGX_UTF16_BUFLEN 256
static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t len);
static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len);
/* FILE_FLAG_BACKUP_SEMANTICS allows to obtain a handle to a directory */
@ -18,24 +18,60 @@ static u_short *ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t len);
ngx_fd_t
ngx_open_file(u_char *name, u_long mode, u_long create, u_long access)
{
u_short *u;
ngx_fd_t fd;
u_short utf16[NGX_UTF16_BUFLEN];
size_t len;
u_long n;
u_short *u, *lu;
ngx_fd_t fd;
ngx_err_t err;
u_short utf16[NGX_UTF16_BUFLEN];
u = ngx_utf8_to_utf16(utf16, name, NGX_UTF16_BUFLEN);
len = NGX_UTF16_BUFLEN;
u = ngx_utf8_to_utf16(utf16, name, &len);
if (u == NULL) {
return INVALID_HANDLE_VALUE;
}
fd = INVALID_HANDLE_VALUE;
lu = NULL;
if (create == NGX_FILE_OPEN) {
lu = malloc(len * 2);
if (lu == NULL) {
goto failed;
}
n = GetLongPathNameW(u, lu, len);
if (n == 0) {
goto failed;
}
if (n != len - 1 || ngx_memcmp(u, lu, n) != 0) {
ngx_set_errno(NGX_ENOENT);
goto failed;
}
}
fd = CreateFileW(u, mode,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, create, FILE_FLAG_BACKUP_SEMANTICS, NULL);
failed:
err = ngx_errno;
if (lu) {
ngx_free(lu);
}
if (u != utf16) {
ngx_free(u);
}
ngx_set_errno(err);
return fd;
}
@ -43,56 +79,17 @@ ngx_open_file(u_char *name, u_long mode, u_long create, u_long access)
ssize_t
ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
{
long high_offset;
u_long n;
ngx_err_t err;
OVERLAPPED ovlp, *povlp;
if (ngx_win32_version < NGX_WIN_NT) {
ovlp.Internal = 0;
ovlp.InternalHigh = 0;
ovlp.Offset = (u_long) offset;
ovlp.OffsetHigh = (u_long) (offset >> 32);
ovlp.hEvent = NULL;
/*
* under Win9X the overlapped pointer must be NULL
* so we have to use SetFilePointer() to set the offset
*/
if (file->offset != offset) {
/*
* the maximum file size on the FAT16 is 2G, but on the FAT32
* the size is 4G so we have to use the high_offset
* because a single offset is signed value
*/
high_offset = (long) (offset >> 32);
if (SetFilePointer(file->fd, (long) offset, &high_offset,
FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
/*
* INVALID_SET_FILE_POINTER is 0xffffffff and it can be valid
* value for large file so we need also to check GetLastError()
*/
err = ngx_errno;
if (err != NO_ERROR) {
ngx_log_error(NGX_LOG_ERR, file->log, err,
"SeekFilePointer() failed");
return NGX_ERROR;
}
}
}
povlp = NULL;
} else {
ovlp.Internal = 0;
ovlp.InternalHigh = 0;
ovlp.Offset = (u_long) offset;
ovlp.OffsetHigh = (u_long) (offset >> 32);
ovlp.hEvent = NULL;
povlp = &ovlp;
}
povlp = &ovlp;
if (ReadFile(file->fd, buf, size, &n, povlp) == 0) {
err = ngx_errno;
@ -101,7 +98,8 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
return 0;
}
ngx_log_error(NGX_LOG_ERR, file->log, err, "ReadFile() failed");
ngx_log_error(NGX_LOG_ERR, file->log, err,
"ReadFile() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
@ -114,58 +112,27 @@ ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
ssize_t
ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
{
long high_offset;
u_long n;
ngx_err_t err;
OVERLAPPED ovlp, *povlp;
if (ngx_win32_version < NGX_WIN_NT) {
ovlp.Internal = 0;
ovlp.InternalHigh = 0;
ovlp.Offset = (u_long) offset;
ovlp.OffsetHigh = (u_long) (offset >> 32);
ovlp.hEvent = NULL;
/*
* under Win9X the overlapped pointer must be NULL
* so we have to use SetFilePointer() to set the offset
*/
if (file->offset != offset) {
/*
* the maximum file size on the FAT16 is 2G, but on the FAT32
* the size is 4G so we have to use high_offset
* because a single offset is signed value
*/
high_offset = (long) (offset >> 32);
if (SetFilePointer(file->fd, (long) offset, &high_offset,
FILE_BEGIN) == INVALID_SET_FILE_POINTER)
{
/*
* INVALID_SET_FILE_POINTER is 0xffffffff and it can be valid
* value for large file so we need also to check GetLastError()
*/
err = ngx_errno;
if (err != NO_ERROR) {
ngx_log_error(NGX_LOG_ERR, file->log, err,
"SeekFilePointer() failed");
return NGX_ERROR;
}
}
}
povlp = NULL;
} else {
ovlp.Internal = 0;
ovlp.InternalHigh = 0;
ovlp.Offset = (u_long) offset;
ovlp.OffsetHigh = (u_long) (offset >> 32);
ovlp.hEvent = NULL;
povlp = &ovlp;
}
povlp = &ovlp;
if (WriteFile(file->fd, buf, size, &n, povlp) == 0) {
ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno, "WriteFile() failed");
ngx_log_error(NGX_LOG_ERR, file->log, ngx_errno,
"WriteFile() \"%s\" failed", file->name.data);
return NGX_ERROR;
}
if (n != size) {
ngx_log_error(NGX_LOG_CRIT, file->log, 0,
"WriteFile() \"%s\" has written only %ul of %uz",
file->name.data, n, size);
return NGX_ERROR;
}
@ -253,17 +220,17 @@ ngx_write_console(ngx_fd_t fd, void *buf, size_t size)
}
ngx_int_t
ngx_err_t
ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log)
{
u_char *name;
ngx_int_t rc;
ngx_err_t err;
ngx_uint_t collision;
ngx_atomic_uint_t num;
name = ngx_alloc(to->len + 1 + 10 + 1 + sizeof("DELETE"), log);
if (name == NULL) {
return NGX_ERROR;
return NGX_ENOMEM;
}
ngx_memcpy(name, to->data, to->len);
@ -288,10 +255,10 @@ ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log)
}
if (MoveFile((const char *) from->data, (const char *) to->data) == 0) {
rc = NGX_ERROR;
err = ngx_errno;
} else {
rc = NGX_OK;
err = 0;
}
if (DeleteFile((const char *) name) == 0) {
@ -299,31 +266,40 @@ ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log)
"DeleteFile() \"%s\" failed", name);
}
if (rc == NGX_ERROR) {
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
"MoveFile() \"%s\" to \"%s\" failed",
from->data, to->data);
}
/* mutex_unlock() */
ngx_free(name);
return rc;
return err;
}
ngx_int_t
ngx_file_info(u_char *file, ngx_file_info_t *sb)
{
WIN32_FILE_ATTRIBUTE_DATA fa;
size_t len;
long rc;
u_short *u;
ngx_err_t err;
WIN32_FILE_ATTRIBUTE_DATA fa;
u_short utf16[NGX_UTF16_BUFLEN];
/* NT4 and Win98 */
len = NGX_UTF16_BUFLEN;
if (GetFileAttributesEx((char *) file, GetFileExInfoStandard, &fa) == 0) {
u = ngx_utf8_to_utf16(utf16, file, &len);
if (u == NULL) {
return NGX_FILE_ERROR;
}
rc = GetFileAttributesExW(u, GetFileExInfoStandard, &fa);
if (u != utf16) {
err = ngx_errno;
ngx_free(u);
ngx_set_errno(err);
}
sb->dwFileAttributes = fa.dwFileAttributes;
sb->ftCreationTime = fa.ftCreationTime;
sb->ftLastAccessTime = fa.ftLastAccessTime;
@ -331,7 +307,7 @@ ngx_file_info(u_char *file, ngx_file_info_t *sb)
sb->nFileSizeHigh = fa.nFileSizeHigh;
sb->nFileSizeLow = fa.nFileSizeLow;
return ~NGX_FILE_ERROR;
return rc;
}
@ -533,14 +509,14 @@ ngx_de_link_info(u_char *name, ngx_dir_t *dir)
ngx_int_t
ngx_directio_on(ngx_fd_t fd)
{
return 0;
return ~NGX_FILE_ERROR;
}
ngx_int_t
ngx_directio_off(ngx_fd_t fd)
{
return 0;
return ~NGX_FILE_ERROR;
}
@ -564,7 +540,7 @@ ngx_fs_bsize(u_char *name)
static u_short *
ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t len)
ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t *len)
{
u_char *p;
u_short *u, *last;
@ -572,18 +548,18 @@ ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t len)
p = utf8;
u = utf16;
last = utf16 + len;
last = utf16 + *len;
while (u < last) {
if (*p < 0x80) {
*u = (u_short) *p;
*u++ = (u_short) *p;
if (*p == 0) {
*len = u - utf16;
return utf16;
}
u++;
p++;
continue;
@ -607,21 +583,21 @@ ngx_utf8_to_utf16(u_short *utf16, u_char *utf8, size_t len)
return NULL;
}
ngx_memcpy(u, utf16, len * 2);
ngx_memcpy(u, utf16, *len * 2);
utf16 = u;
u += len;
u += *len;
for ( ;; ) {
if (*p < 0x80) {
*u = (u_short) *p;
*u++ = (u_short) *p;
if (*p == 0) {
*len = u - utf16;
return utf16;
}
u++;
p++;
continue;

View File

@ -111,7 +111,7 @@ ssize_t ngx_write_console(ngx_fd_t fd, void *buf, size_t size);
#define ngx_rename_file(o, n) MoveFile((const char *) o, (const char *) n)
#define ngx_rename_file_n "MoveFile()"
ngx_int_t ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log);
ngx_err_t ngx_win32_rename_file(ngx_str_t *from, ngx_str_t *to, ngx_log_t *log);