apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From wr...@apache.org
Subject cvs commit: apr/include/arch/win32 fileio.h
Date Sat, 27 Jan 2001 22:25:11 GMT
wrowe       01/01/27 14:25:11

  Modified:    file_io/win32 dir.c filestat.c open.c
               include  apr.h.in apr.hw
               include/arch/win32 fileio.h
  Log:
    This patch sets the server running once again, except in cases where
    it still expects APR_SUCCESS responses to an APR_FINFO_NORM apr_stat.
    Most of those are gone, those that remain are hiding in the modules.
  
    Radically refactored apr_stat/lstat/getfileinfo/dir_read for Win32
    to assure we are retrieving what we expect to retrieve, and reporting
    the correct result (APR_SUCCESS or APR_INCOMPLETE).  The potential
    for a bit more optimization still remains.
  
    While we have the future opportunity to cache the apr_stat'ed file
    handle for a very fast open (dup handle) on Win32, patched to close
    that file after a stat always.  Needs a new semantic before we leave
    handles dangling when the user intends to rm.
  
    Correct Win32 apr_stat/lstat/getfileinfo/dir_read to all zero out
    the finfo buffer on success (or incomplete success).
  
    Fix Win32/Unix apr_lstat to throw the .valid bit APR_FINFO_LINK to
    indicate we attempted to open the link.  Only the .filetype APR_LNK
    reflects if the file found was, in fact, a link.
  
  Revision  Changes    Path
  1.48      +15 -15    apr/file_io/win32/dir.c
  
  Index: dir.c
  ===================================================================
  RCS file: /home/cvs/apr/file_io/win32/dir.c,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- dir.c	2001/01/24 21:13:13	1.47
  +++ dir.c	2001/01/27 22:25:10	1.48
  @@ -146,6 +146,7 @@
                                          apr_dir_t *thedir)
   {
       apr_status_t rv;
  +    char *fname;
       /* The while loops below allow us to skip all invalid file names, so that
        * we aren't reporting any files where their absolute paths are too long.
        */
  @@ -183,7 +184,7 @@
           if (rv = unicode_to_utf8_path(thedir->name, APR_FILE_MAX * 3 + 1, 
                                         thedir->w.entry->cFileName))
               return rv;
  -        finfo->name = thedir->name;
  +        fname = thedir->name;
       }
       else
   #endif
  @@ -208,28 +209,28 @@
                   return apr_get_os_error();
               }
           }
  -        finfo->name = thedir->n.entry->cFileName;
  +        fname = thedir->n.entry->cFileName;
       }
  -    finfo->valid = APR_FINFO_NAME | APR_FINFO_TYPE | APR_FINFO_CTIME
  -                 | APR_FINFO_ATIME | APR_FINFO_MTIME | APR_FINFO_SIZE;
  -    wanted |= ~finfo->valid;
  -    if (wanted) {
  -        /* Win32 apr_stat() is about to open a handle to this file.
  -         * we must create a full path that doesn't evaporate.
  -         */
  -        const char *fname = finfo->name;
  -        char *fspec = apr_pstrcat(thedir->cntxt, thedir->dirname, 
  -                                  finfo->name, NULL);
  -        finfo->valid = 0;
  +    if (wanted & ~APR_FINFO_WIN32_DIR) {
  +        char fspec[APR_PATH_MAX];
  +        int dirlen = strlen(thedir->dirname);
  +        if (dirlen >= sizeof(fspec))
  +            dirlen = sizeof(fspec) - 1;
  +        apr_cpystrn(fspec, sizeof(fspec), thedir->dirname);
  +        apr_cpystrn(fspec + dirlen, sizeof(fspec) - dirlen, fname);
           rv = apr_stat(finfo, fspec, wanted, thedir->cntxt);
           if (rv == APR_SUCCESS || rv == APR_INCOMPLETE) {
               finfo->valid |= APR_FINFO_NAME;
               finfo->name = fname;
               finfo->fname = fspec;
  +            rv = (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
           }
           return rv;
       }
   
  +    memset(finfo, '\0', sizeof(*finfo));
  +    finfo->name = fname;
  +    finfo->valid = APR_FINFO_WIN32_DIR;
       finfo->cntxt = thedir->cntxt;
   
       /* Do the best job we can determining the file type.
  @@ -255,8 +256,7 @@
       FileTimeToAprTime(&finfo->atime, &thedir->n.entry->ftLastAccessTime);
       finfo->size = (thedir->n.entry->nFileSizeHigh * MAXDWORD)
                   +  thedir->n.entry->nFileSizeLow;
  -    finfo->fname = NULL;
  -    return APR_SUCCESS;
  +    return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS;
   }
   
   APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *dir)
  
  
  
  1.40      +91 -101   apr/file_io/win32/filestat.c
  
  Index: filestat.c
  ===================================================================
  RCS file: /home/cvs/apr/file_io/win32/filestat.c,v
  retrieving revision 1.39
  retrieving revision 1.40
  diff -u -r1.39 -r1.40
  --- filestat.c	2001/01/23 04:10:46	1.39
  +++ filestat.c	2001/01/27 22:25:10	1.40
  @@ -68,75 +68,33 @@
                                             apr_file_t *thefile)
   {
       BY_HANDLE_FILE_INFORMATION FileInformation;
  -    DWORD FileType;
  -    apr_oslevel_e os_level;
   
       if (!GetFileInformationByHandle(thefile->filehand, &FileInformation)) {
           return apr_get_os_error();
       }
   
  -    FileType = GetFileType(thefile->filehand);
  -    if (!FileType) {
  -        return apr_get_os_error();
  -    }
  +    memset(finfo, '\0', sizeof(*finfo));
   
  -    /* If my rudimentary knowledge of posix serves... inode is the absolute
  -     * id of the file (uniquifier) that is returned by NT (not 9x) as follows:
  -     */
  -    if (apr_get_oslevel(thefile->cntxt, &os_level) || os_level >= APR_WIN_NT)

  -    {
  -        finfo->inode = (apr_ino_t) FileInformation.nFileIndexHigh << 16
  -                                 | FileInformation.nFileIndexLow;
  -        finfo->device = FileInformation.dwVolumeSerialNumber;
  -    }
  -    else 
  -    {
  -        /* Since the apr_stat is not implemented with CreateFile(),
  -         * (directories can't be opened with CreateFile() at all)
  -         * the apr_stat always returns 0 - so must apr_getfileinfo().
  -         */
  -        finfo->inode = 0;
  -        finfo->device = 0;
  -    }
  -    /* user and group could be returned as SID's, although this creates
  -     * it's own unique set of issues.  All three fields are significantly
  -     * longer than the posix compatible kernals would ever require.
  -     * TODO: Someday solve this, and fix the executable flag below the
  -     * right way with a security permission test (as well as r/w flags.)
  -     */
  -    finfo->user = 0;
  -    finfo->group = 0;
  -    
  -    /* Filetype - Directory or file: this case _will_ never happen */
  -    if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
  -        finfo->protection = S_IFLNK;
  -        finfo->filetype = APR_LNK;
  -    }
  -    else if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  -        finfo->protection = S_IFDIR;
  -        finfo->filetype = APR_DIR;
  -    }
  -    else if (FileType == FILE_TYPE_DISK) {
  -        finfo->protection = S_IFREG;
  -        finfo->filetype = APR_REG;
  -    }
  -    else if (FileType == FILE_TYPE_CHAR) {
  -        finfo->protection = S_IFCHR;
  -        finfo->filetype = APR_CHR;
  -    }
  -    else if (FileType == FILE_TYPE_PIPE) {
  -        finfo->protection = S_IFIFO;
  -        finfo->filetype = APR_PIPE;
  -    }
  -    else {
  -        finfo->protection = 0;
  -        finfo->filetype = APR_NOFILE;
  -    }
  +    FileTimeToAprTime(&finfo->atime, &FileInformation.ftLastAccessTime);
  +    FileTimeToAprTime(&finfo->ctime, &FileInformation.ftCreationTime);
  +    FileTimeToAprTime(&finfo->mtime, &FileInformation.ftLastWriteTime);
   
  -    /* Read, write execute for owner
  -     * In the Win32 environment, anything readable is executable
  -     * (well, not entirely 100% true, but I'm looking for a way 
  -     * to get at the acl permissions in simplified fashion.)
  +    finfo->inode  =  (apr_ino_t)FileInformation.nFileIndexLow
  +                  | ((apr_ino_t)FileInformation.nFileIndexHigh << 32);
  +    finfo->device = FileInformation.dwVolumeSerialNumber;
  +    finfo->nlink  = FileInformation.nNumberOfLinks;
  +
  +#if APR_HAS_LARGE_FILES
  +    finfo->size =  (apr_off_t)FileInformation.nFileSizeLow
  +                | ((apr_off_t)FileInformation.nFileSizeHigh << 32);
  +#else
  +    finfo->size = FileInformation.nFileSizeLow;
  +#endif
  +    
  +    /* Read, write execute for owner.  In the Win32 environment, 
  +     * anything readable is executable (well, not entirely 100% true, 
  +     * but I'm looking for some obvious logic that would help us here.)
  +     * TODO: The real permissions come from the DACL
        */
       if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
           finfo->protection |= S_IREAD | S_IEXEC;
  @@ -145,15 +103,46 @@
           finfo->protection |= S_IREAD | S_IWRITE | S_IEXEC;
       }
       
  -    /* File times */
  -    FileTimeToAprTime(&finfo->atime, &FileInformation.ftLastAccessTime);
  -    FileTimeToAprTime(&finfo->ctime, &FileInformation.ftCreationTime);
  -    FileTimeToAprTime(&finfo->mtime, &FileInformation.ftLastWriteTime);
  +    /* TODO: return user and group could as * SID's, allocated in the pool.
  +     * [These are variable length objects that will require a 'comparitor'
  +     * and a 'get readable string of' functions.]
  +     */
  +    
  +    finfo->valid = APR_FINFO_ATIME | APR_FINFO_CTIME | APR_FINFO_MTIME
  +                 | APR_FINFO_IDENT | APR_FINFO_NLINK | APR_FINFO_SIZE 
  +                 | APR_FINFO_UPROT;
   
  -    /* File size 
  -     * Note: This cannot handle files greater than can be held by an int */
  -    finfo->size = FileInformation.nFileSizeLow;
   
  +    if (wanted & APR_FINFO_TYPE) 
  +    {
  +        DWORD FileType;
  +        if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
  +            finfo->filetype = APR_LNK;
  +            finfo->valid |= APR_FINFO_TYPE;
  +        }
  +        else if (FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  +            finfo->filetype = APR_DIR;
  +            finfo->valid |= APR_FINFO_TYPE;
  +        }
  +        else if (FileType = GetFileType(thefile->filehand)) {
  +            if (FileType == FILE_TYPE_DISK) {
  +                finfo->filetype = APR_REG;
  +                finfo->valid |= APR_FINFO_TYPE;
  +            }
  +            else if (FileType == FILE_TYPE_CHAR) {
  +                finfo->filetype = APR_CHR;
  +                finfo->valid |= APR_FINFO_TYPE;
  +            }
  +            else if (FileType == FILE_TYPE_PIPE) {
  +                finfo->filetype = APR_PIPE;
  +                finfo->valid |= APR_FINFO_TYPE;
  +            }
  +        }
  +    }
  +
  +    if (wanted & ~finfo->valid)
  +        return APR_INCOMPLETE;
  +
       return APR_SUCCESS;
   }
   
  @@ -174,7 +163,7 @@
        * since in many cases the apr user is testing for 'not found' 
        * and this is not such a case.
        */        
  -    if (!apr_get_oslevel(cont, &os_level) && os_level >= APR_WIN_NT)
  +    if (!apr_get_oslevel(cont, &os_level) && os_level >= APR_WIN_NT) 
       {
           apr_file_t *thefile = NULL;
           apr_status_t rv;
  @@ -187,37 +176,36 @@
            * user, group or permissions.
            */
           
  -        if (rv = apr_open(&thefile, fname, 
  -                          ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0)
  -                        | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
  -                             ? APR_READCONTROL : 0), APR_OS_DEFAULT, cont))
  -        {
  +        if ((rv = apr_open(&thefile, fname, 
  +                           ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0)
  +                         | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER))
  +                               ? APR_READCONTROL : 0),
  +                           APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
  +            rv = apr_getfileinfo(finfo, wanted, thefile);
  +            finfo->filehand = NULL;
  +            apr_close(thefile);
  +        }
  +        else if (APR_STATUS_IS_EACCES(rv) && (wanted & (APR_FINFO_PROT 
  +                                                      | APR_FINFO_OWNER))) {
               /* We have a backup plan.  Perhaps we couldn't grab READ_CONTROL?
  -             * proceed with the alternate...
  +             * proceed without asking for that permission...
                */
  -            if (wanted & (APR_FINFO_PROT | APR_FINFO_OWNER)) {
  -                rv = apr_open(&thefile, fname, 
  -                              ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0),
  -                              APR_OS_DEFAULT, cont);
  -                wanted &= ~(APR_FINFO_PROT | APR_FINFO_OWNER);
  +            if ((rv = apr_open(&thefile, fname, 
  +                               ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0),
  +                               APR_OS_DEFAULT, cont)) == APR_SUCCESS) {
  +                rv = apr_getfileinfo(finfo, wanted & ~(APR_FINFO_PROT 
  +                                                     | APR_FINFO_OWNER),
  +                                     thefile);
  +                finfo->filehand = NULL;
  +                apr_close(thefile);
               }
  -            if (rv)
  -                return rv;
           }
  -
  -        /* 
  -         * NT5 (W2K) only supports symlinks in the same manner as mount points.
  -         * This code should eventually take that into account, for now treat
  -         * every reparse point as a symlink...
  -         *
  -         * We must open the file with READ_CONTROL if we plan to retrieve the
  -         * user, group or permissions.
  -         */
  -        rv = apr_getfileinfo(finfo, wanted, thefile);
  -        finfo->cntxt = thefile->cntxt;
  +        if (rv != APR_SUCCESS && rv != APR_INCOMPLETE)
  +            return (rv);
  +        /* We picked up this case above and had opened the link's properties */
  +        if (wanted & APR_FINFO_LINK)
  +            finfo->valid |= APR_FINFO_LINK;
           finfo->fname = thefile->fname;
  -        finfo->filehand = thefile;
  -        return (rv);
       }
       else
       {
  @@ -230,15 +218,13 @@
           if (strlen(fname) >= MAX_PATH) {
               return APR_ENAMETOOLONG;
           }
  -        else if (os_level >= APR_WIN_98) 
  -        {
  +        else if (os_level >= APR_WIN_98) {
               if (!GetFileAttributesEx(fname, GetFileExInfoStandard, 
                                        &FileInformation)) {
                   return apr_get_os_error();
               }
           }
  -        else 
  -        {
  +        else  {
               /* What a waste of cpu cycles... but we don't have a choice
                */
               HANDLE hFind;
  @@ -247,7 +233,8 @@
               hFind = FindFirstFile(fname, &FileInformation);
               if (hFind == INVALID_HANDLE_VALUE) {
                   return apr_get_os_error();
  -    	    } else {
  +    	    } 
  +            else {
                   FindClose(hFind);
               }
           }
  @@ -301,6 +288,9 @@
           if (finfo->size < 0 || FileInformation.nFileSizeHigh)
               finfo->size = 0x7fffffff;
       }
  +    if (wanted & ~finfo->valid)
  +        return APR_INCOMPLETE;
  +
       return APR_SUCCESS;
   }
   
  
  
  
  1.69      +5 -8      apr/file_io/win32/open.c
  
  Index: open.c
  ===================================================================
  RCS file: /home/cvs/apr/file_io/win32/open.c,v
  retrieving revision 1.68
  retrieving revision 1.69
  diff -u -r1.68 -r1.69
  --- open.c	2001/01/27 17:57:02	1.68
  +++ open.c	2001/01/27 22:25:10	1.69
  @@ -175,7 +175,7 @@
       HANDLE handle = INVALID_HANDLE_VALUE;
       DWORD oflags = 0;
       DWORD createflags = 0;
  -    DWORD attributes = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN;
  +    DWORD attributes = 0 /* FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN*/;
       DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
       apr_oslevel_e os_level;
       apr_status_t rv;
  @@ -189,8 +189,6 @@
       
       if (!apr_get_oslevel(cont, &os_level) && os_level >= APR_WIN_NT) 
           sharemode |= FILE_SHARE_DELETE;
  -    else
  -        os_level = 0;
   
       if (flag & APR_CREATE) {
           if (flag & APR_EXCL) {
  @@ -218,15 +216,14 @@
       if (flag & APR_DELONCLOSE) {
           attributes |= FILE_FLAG_DELETE_ON_CLOSE;
       }
  -    if (flag & APR_OPENLINK) {
  -        attributes |= FILE_FLAG_OPEN_REPARSE_POINT;
  +   if (flag & APR_OPENLINK) {
  +       attributes |= FILE_FLAG_OPEN_REPARSE_POINT;
       }
       if (!(flag & (APR_READ | APR_WRITE)) && (os_level >= APR_WIN_NT)) {
           /* We once failed here, but this is how one opens 
  -         * a directory as a file under winnt.  Accelerate
  -         * further by not hitting storage, we don't need to.
  +         * a directory as a file under winnt
            */
  -        attributes |= FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_NO_RECALL;
  +        attributes |= FILE_FLAG_BACKUP_SEMANTICS;
       }
       if (flag & APR_XTHREAD) {
           /* This win32 specific feature is required 
  
  
  
  1.63      +1 -0      apr/include/apr.h.in
  
  Index: apr.h.in
  ===================================================================
  RCS file: /home/cvs/apr/include/apr.h.in,v
  retrieving revision 1.62
  retrieving revision 1.63
  diff -u -r1.62 -r1.63
  --- apr.h.in	2001/01/19 07:04:35	1.62
  +++ apr.h.in	2001/01/27 22:25:10	1.63
  @@ -108,6 +108,7 @@
   #define APR_HAS_DSO               @aprdso@
   #define APR_HAS_UNICODE_FS        0
   #define APR_HAS_USER              1
  +#define APR_HAS_LARGE_FILES       0
   
   /* This macro tells APR that it is safe to make a file masquerade as a 
    * socket.  This is necessary, because some platforms support poll'ing
  
  
  
  1.48      +1 -0      apr/include/apr.hw
  
  Index: apr.hw
  ===================================================================
  RCS file: /home/cvs/apr/include/apr.hw,v
  retrieving revision 1.47
  retrieving revision 1.48
  diff -u -r1.47 -r1.48
  --- apr.hw	2001/01/19 07:04:35	1.47
  +++ apr.hw	2001/01/27 22:25:10	1.48
  @@ -187,6 +187,7 @@
   #define APR_HAS_DSO               1
   #define APR_HAS_UNICODE_FS        1
   #define APR_HAS_USER              0
  +#define APR_HAS_LARGE_FILES       1
   
   /* Not all platforms have a real INADDR_NONE.  This macro replaces INADDR_NONE
    * on all platforms.
  
  
  
  1.43      +5 -0      apr/include/arch/win32/fileio.h
  
  Index: fileio.h
  ===================================================================
  RCS file: /home/cvs/apr/include/arch/win32/fileio.h,v
  retrieving revision 1.42
  retrieving revision 1.43
  diff -u -r1.42 -r1.43
  --- fileio.h	2001/01/23 19:54:42	1.42
  +++ fileio.h	2001/01/27 22:25:11	1.43
  @@ -135,6 +135,11 @@
   #define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
   #endif
   
  +/* Information bits available from the WIN32 FindFirstFile function */
  +#define APR_FINFO_WIN32_DIR (APR_FINFO_NAME  | APR_FINFO_TYPE \
  +                           | APR_FINFO_CTIME | APR_FINFO_ATIME \
  +                           | APR_FINFO_MTIME | APR_FINFO_SIZE)
  +
   
   /* quick run-down of fields in windows' apr_file_t structure that may have 
    * obvious uses.
  
  
  

Mime
View raw message