Исходные коды спецификаций для LSB Core 3.1

/*
 * Copyright (c) 2005-2006 Institute for System Programming
 * Russian Academy of Sciences
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Portions of this text are reprinted and reproduced in electronic form
 * from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology
 * -- Portable Operating System Interface (POSIX), The Open Group Base
 * Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
 * Electrical and Electronics Engineers, Inc and The Open Group. In the
 * event of any discrepancy between this version and the original IEEE and
 * The Open Group Standard, the original IEEE and The Open Group Standard
 * is the referee document. The original Standard can be obtained online at
 * http://www.opengroup.org/unix/online.html.
 */



#include "system/system/system_model.seh"
#include "system/sysconf/sysconf_model.seh"
#include "system/sysconf/sysconf_media.seh"
#include "fs/meta/meta_model.seh"
#include "data/errno_model.seh"
#include "process/process/process_model.seh"
#include "config/interpretation.seh"
#include "fs/meta/meta_config.h"
#include "data/sys/time_model.seh"

#include <atl/map.h>

#pragma SEC subsystem meta "fs.meta"


int SKIP_LXSTAT_CHECK = 0;

/*
   The group of functions 'fs.meta.meta' consists of:
       __fxstat [1]
       __fxstat64 [1]
       __lxstat [1]
       __lxstat64 [1]
       __xstat [1]
       __xstat64 [1]
       utime [2]
       utimes [2]
 */

/********************************************************************/
/**                      Interface Functions                       **/
/********************************************************************/

/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

NAME

    __xstat -- get File Status

SYNOPSIS

    #include <sys/stat.h> #include <unistd.h>

    int __xstat(int ver, const char * path, struct stat * stat_buf);
    int __lxstat(int ver, const char * path, struct stat * stat_buf);
    int __fxstat(int ver, int fildes, struct stat * stat_buf);

DESCRIPTION

    The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
    POSIX (2003) functions stat(), lstat(), and fstat() respectively.

    ver shall be 3 or the behavior of these functions is undefined.

    __xstat(3, path, stat_buf) shall implement stat(path, stat_buf) as specified
    by ISO POSIX (2003).

    __lxstat(3, path, stat_buf) shall implement lstat(path, stat_buf) as
    specified by ISO POSIX (2003).

    __fxstat(3, fildes, stat_buf) shall implement fstat(fildes, stat_buf) as
    specified by ISO POSIX (2003).

    __xstat(), __lxstat(), and __fxstat() are not in the source standard; they
    are only in the binary standard.

    stat(), lstat(), and fstat() are not in the binary standard; they are only
    in the source standard.
*/
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

  refers

The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Copyright (c) 2001-2004 The IEEE and The Open Group, All Rights reserved.

NAME

    stat - get file status

SYNOPSIS

    #include <sys/stat.h>

    int stat(const char *restrict path, struct stat *restrict buf);

DESCRIPTION

    The stat() function shall obtain information about the named file and write
    it to the area pointed to by the buf argument. The path argument points to
    a pathname naming a file. Read, write, or execute permission of the named
    file is not required. An implementation that provides additional or
    alternate file access control mechanisms may, under implementation-defined
    conditions, cause stat() to fail. In particular, the system may deny the
    existence of the file specified by path.

    If the named file is a symbolic link, the stat() function shall continue
    pathname resolution using the contents of the symbolic link, and shall
    return information pertaining to the resulting file if the file exists.

    The buf argument is a pointer to a stat structure, as defined in the
    <sys/stat.h> header, into which information is placed concerning the file.

    The stat() function shall update any time-related fields (as described in
    the Base Definitions volume of IEEE Std 1003.1-2001, Section 4.7, File
    Times Update), before writing into the stat structure.

    Unless otherwise specified, the structure members st_mode, st_ino, st_dev,
    st_uid, st_gid, st_atime, st_ctime, and st_mtime shall have meaningful
    values for all file types defined in this volume of IEEE Std 1003.1-2001.
    The value of the member st_nlink shall be set to the number of links to the
    file.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall be
    returned and errno set to indicate the error.

ERRORS

    The stat() function shall fail if:

    [EACCES]

        Search permission is denied for a component of the path prefix.

    [EIO]

        An error occurred while reading from the file system.

    [ELOOP]

        A loop exists in symbolic links encountered during resolution of the
        path argument.

    [ENAMETOOLONG]

        The length of the path argument exceeds {PATH_MAX} or a pathname
        component is longer than {NAME_MAX}.

    [ENOENT]

        A component of path does not name an existing file or path is an empty
        string.

    [ENOTDIR]

        A component of the path prefix is not a directory.

    [EOVERFLOW]

        The file size in bytes or the number of blocks allocated to the file or
        the file serial number cannot be represented correctly in the structure
        pointed to by buf.


    The stat() function may fail if:

    [ELOOP]

        More than {SYMLOOP_MAX} symbolic links were encountered during
        resolution of the path argument.

    [ENAMETOOLONG]

        As a result of encountering a symbolic link in resolution of the path
        argument, the length of the substituted pathname string exceeded
        {PATH_MAX}.

    [EOVERFLOW]

        A value to be stored would overflow one of the members of the stat
        structure.
*/

specification
IntT __xstat_spec( CallContext context, IntT ver, CString * path, FileStatus * buff, ErrorCode * errno )
{
    pre
    {
        REQ("", "Implicit precondition", path!=NULL && buff!=NULL);

        /*
         * The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
         * POSIX (2003) functions stat(), lstat(), and fstat() respectively.ver shall be 3
         * or the behavior of these functions is undefined.
         */
        REQ( "app.__xstat.30", "ver shall be 3 or the behavior is undefined", ver == 3 );

        return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* resolved;
        File* search_result;

        /*
         * If the named file is a symbolic link, the stat() function shall
         * continue pathname resolution using the contents of the symbolic
         * link, and shall return information pertaining to the resulting file
         * if the file exists.
         */
        IMPLEMENT_REQ("__xstat.stat.01");
        resolved=resolvePath_Ext(context, fs, path, &eloop);

        VERBOSE("ELOOP==%s\n", (eloop==True_Bool3? "True_Bool3":
                    (eloop==False_Bool3? "False_Bool3": "Unknown_Bool3")));

        VERBOSE("Before error, path==%s\n", *resolved);

        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_STAT, "__xstat.stat.04", __xstat_spec==-1,  *errno )
        /*
         * The stat() function shall fail if:
         *
         * [EACCES]
         *
         * Search permission is denied for a component of the path prefix.
         *
         */
            ERROR_SHALL3(POSIX_STAT, EACCES,"__xstat.stat.09.01",
                                shall_isEACCES_xstat(context, fs, resolved))

        /*
         * The stat() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of
         * the path argument.
         *
         */
            ERROR_SHALL3(POSIX_STAT, ELOOP,"__xstat.stat.09.03", eloop)

        /*
         * The stat() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * The length of the path argument exceeds {PATH_MAX} or a pathname
         * component is longer than {NAME_MAX}.
         *
         */
            ERROR_SHALL3(POSIX_STAT, ENAMETOOLONG,"__xstat.stat.09.04",
                                shall_isENAMETOOLONG_xstat(context, path))

        /*
         * The stat() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         *
         */
            ERROR_SHALL3(POSIX_STAT, ENOENT,"__xstat.stat.09.05",
                                shall_isENOENT_xstat(context, fs, resolved))

        /*
         * The stat() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         *
         */
            ERROR_SHALL3(POSIX_STAT, ENOTDIR,"__xstat.stat.09.06",
                                shall_isENOTDIR_xstat(context, fs,
                                                getParentDir_Path(resolved)))

        /*
         * The stat() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the
         * file or the file serial number cannot be represented correctly
         * in the structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_STAT, EOVERFLOW,"__xstat.stat.09.07",
                            shall_isEOVERFLOW_xstat(context, fs, resolved))

        /*
         * The stat() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         *
         */
            ERROR_MAY3(POSIX_STAT, ELOOP,"__xstat.stat.10.01", eloop)

        /*
         * The stat() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * As a result of encountering a symbolic link in resolution of the
         * path argument, the length of the substituted pathname
         * string exceeded {PATH_MAX}.
         */
            ERROR_MAY3(POSIX_STAT, ENAMETOOLONG,"__xstat.stat.10.02",
                            may_isENAMETOOLONG_xstat(context, resolved))

        /*
         * The stat() function may fail if:
         *
         * [EOVERFLOW]
         *
         * A value to be stored would overflow one of the members of the stat
         * structure.
         */
            ERROR_MAY3(POSIX_STAT, EOVERFLOW,"__xstat.stat.10.01",
                            may_isEOVERFLOW_xstat(context, fs, resolved))
        /*
         * The stat() function shall fail if:
         *
         * [EIO]
         *
         * An error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_STAT, EIO,"__xstat.stat.09.02", "")

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__xstat.stat.03", "No errors", __xstat_spec==0 && *errno==SUT_EOK);

        if(resolved==NULL)
        {
            VERBOSE("Unable to resolve path...%s\n", path);
            return true;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result==NULL)
        {
            VERBOSE("File isn't registered...\n");
            return true;
        }

        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                        create_FileStatus_FromFile(context, search_result));

        DUMP("$(obj) is a ", path);
        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * The stat() function shall obtain information about the named file
         * and write it to the area pointed to by the buf argument.
         */

        if(!SKIP_LXSTAT_CHECK)
        {
            REQ("__xstat.stat.05", "Stat structure filled properly",
                    checkFileStatusEquality(context, buff, search_result));
        }

        /*
         * __xstat(3, path, stat_buf) shall implement stat(path, stat_buf) as specified by
         * ISO POSIX (2003).
         */
        REQ( "__xstat.30", "__xstat(3, path, stat_buf) implement stat(path, stat_buf)", GENERAL_REQ( "__xstat.stat.*" ) );

        return true;
    }
}

/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

NAME

    __xstat64 -- get File Status

SYNOPSIS

    #define _LARGEFILE_SOURCE 1
    #include <sys/stat.h>
    #include <unistd.h>

    int __xstat64(int ver, const char * path, struct stat64 * stat_buf);

    int __lxstat64(int ver, const char * path, struct stat64 * stat_buf);

    int __fxstat64(int ver, int fildes, struct stat64 * stat_buf);

DESCRIPTION

    The functions __xstat64(), __lxstat64(), and __fxstat64() shall implement the Large File Support functions stat64(),
    lstat64(), and fstat64() respectively.

    ver shall be 3 or the behavior of these functions is undefined.

    __xstat64(3, path, stat_buf) shall behave as stat(path, stat_buf) as specified by Large File Support.

    __lxstat64(3, path, stat_buf) shall behave as lstat(path, stat_buf) as specified by Large File Support.

    __fxstat64(3, fildes, stat_buf) shall behave as fstat(fildes, stat_buf) as specified by Large File Support.

    __xstat64(), __lxstat64(), and __fxstat64() are not in the source standard; they are only in the binary standard.

    stat64(), lstat64(), and fstat64() are not in the binary standard; they are only in the source standard.
*/

specification
IntT __xstat64_spec( CallContext context, IntT ver, CString * path, FileStatus * buff, ErrorCode * errno )
{
    pre
    {
        /*
         * ver shall be 3 or the behavior of these functions is undefined.
         */
        REQ( "app.__xstat64.12", "ver shall be 3 or the behavior is undefined", ver == 3 );

       return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* resolved=resolvePath_Ext(context, fs, path, &eloop);
        File* search_result;

        /*
         * If the named file is a symbolic link, the stat() function shall
         * continue pathname resolution using the contents of the symbolic
         * link, and shall return information pertaining to the resulting file
         * if the file exists.
         */
        IMPLEMENT_REQ("__xstat64.stat.01");

        VERBOSE("ELOOP==%s\n", (eloop==True_Bool3? "True_Bool3":
                    (eloop==False_Bool3? "False_Bool3": "Unknown_Bool3")));

        VERBOSE("Before error, path==%s\n", *path);
        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_STAT64, "__xstat64.stat.04", __xstat64_spec==-1,  *errno )
        /*
         * The stat64() function shall fail if:
         *
         * [EACCES]
         *
         * Search permission is denied for a component of the path prefix.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, EACCES,"__xstat64.stat.09.01",
                                shall_isEACCES_xstat64(context, fs, resolved))

        /*
         * The stat64() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of
         * the path argument.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, ELOOP,"__xstat64.stat.09.03", eloop)

        /*
         * The stat64() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * The length of the path argument exceeds {PATH_MAX} or a pathname
         * component is longer than {NAME_MAX}.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, ENAMETOOLONG,"__xstat64.stat.09.04",
                                shall_isENAMETOOLONG_xstat64(context, path))

        /*
         * The stat64() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, ENOENT,"__xstat64.stat.09.05",
                                shall_isENOENT_xstat64(context, fs, resolved))

        /*
         * The stat64() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, ENOTDIR,"__xstat64.stat.09.06",
                                shall_isENOTDIR_xstat64(context, fs,
                                                getParentDir_Path(resolved)))

        /*
         * The stat64() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the
         * file or the file serial number cannot be represented correctly
         * in the structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_STAT64, EOVERFLOW,"__xstat64.stat.09.07",
                            shall_isEOVERFLOW_xstat64(context, fs, resolved))

        /*
         * The stat64() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         *
         */
            ERROR_MAY3(POSIX_STAT64, ELOOP,"__xstat64.stat.10.01", eloop)

        /*
         * The stat64() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * As a result of encountering a symbolic link in resolution of the
         * path argument, the length of the substituted pathname
         * string exceeded {PATH_MAX}.
         */
            ERROR_MAY3(POSIX_STAT64, ENAMETOOLONG,"__xstat64.stat.10.02",
                            may_isENAMETOOLONG_xstat64(context, resolved))

        /*
         * The stat64() function may fail if:
         *
         * [EOVERFLOW]
         *
         * A value to be stored would overflow one of the members of the stat64
         * structure.
         */
            ERROR_MAY3(POSIX_STAT64, EOVERFLOW,"__xstat64.stat.10.01",
                            may_isEOVERFLOW_xstat64(context, fs, resolved))
        /*
         * The stat64() function shall fail if:
         *
         * [EIO]
         *
         * An error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_STAT64, EIO,"__xstat64.stat.09.02", "")

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__xstat64.stat.03", "No errors", __xstat64_spec==0 && *errno==SUT_EOK);

        if(resolved==NULL)
        {
            VERBOSE("Unable to resolve path...%s\n", path);
            return true;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result==NULL)
        {
            VERBOSE("File isn't registered...\n");
            return true;
        }

        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                        create_FileStatus_FromFile(context, search_result));

        DUMP("$(obj) is a ", path);
        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * The stat() function shall obtain information about the named file
         * and write it to the area pointed to by the buf argument.
         */
        REQ("__xstat64.stat.05", "Stat structure filled properly",
                checkFileStatusEquality(context, buff, search_result));



        return true;
    }
}

specification
IntT __lxstat64_spec( CallContext context, IntT ver, CString * path, FileStatus * buff, ErrorCode * errno )
{
    pre
    {

        /*
         * ver shall be 3 or the behavior of these functions is undefined.
         */
        REQ( "app.__lxstat64.08", "ver shall be 3 or the behavior is undefined", ver == 3 );

       return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* parent=getParentDir_Path(path);
        CString* basename=getBaseName_Path(path);
        CString* resolved=resolvePath_Ext(context, fs, parent, &eloop);
        CString* concated=NULL;
        File* search_result;

        if(resolved!=NULL && basename!=NULL)
            concated=concat_Path(resolved, basename);
        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_LSTAT64, "__lxstat64.lstat.06", __lxstat64_spec==-1, *errno)
        /*
         * The lstat64() function shall fail if:
         *
         * [EACCES]
         *
         * A component of the path prefix denies search permission.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, EACCES,"__lxstat64.lstat.03.01",
                                shall_isEACCES_lxstat(context, fs, concated))

        /*
         * The lstat64() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of
         * the path argument.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, ELOOP,"__lxstat64.lstat.03.03", eloop)

        /*
         * The lstat64() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * The length of a pathname exceeds {PATH_MAX} or a pathname component
         * is longer than {NAME_MAX}.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, ENAMETOOLONG,"__lxstat64.lstat.03.04",
                            shall_isENAMETOOLONG_lxstat(context, path))

        /*
         * The lstat64() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, ENOTDIR,"__lxstat64.lstat.03.05",
                                shall_isENOTDIR_lxstat(context, fs, concated))

        /*
         * The lstat64() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, ENOENT,"__lxstat64.lstat.03.06",
                                shall_isENOENT_lxstat(context, fs, concated))
        /*
         * The lstat64() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the
         * file or the file serial number cannot be represented correctly
         * in the structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT64, EOVERFLOW,"__lxstat64.lstat.03.07",
                            shall_isEOVERFLOW_lxstat(context, fs, concated))

        /*
         * The lstat64() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         *
         */
            ERROR_MAY3(POSIX_LSTAT64, ELOOP,"__lxstat64.lstat.04.01", eloop)
        /*
         * The lstat64() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * As a result of encountering a symbolic link in resolution of the
         * path argument, the length of the substituted pathname
         * string exceeded {PATH_MAX}.
         *
         */
            ERROR_MAY3(POSIX_LSTAT64, ENAMETOOLONG,"__lxstat64.lstat.04.02",
                            may_isENAMETOOLONG_lxstat(context, concated))

        /*
         * The lstat64() function may fail if:
         *
         * [EOVERFLOW]
         *
         * One of the members is too large to store into the structure pointed
         * to by the buf argument.
         *
         */
            ERROR_MAY3(POSIX_LSTAT64, EOVERFLOW,"__lxstat64.lstat.04.03",
                           may_isEOVERFLOW_lxstat(context, fs, concated))
        /*
         * The lstat64() function shall fail if:
         *
         * [EIO]
         *
         * An error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_LSTAT64, EIO,"__lxstat64.lstat.03.02", "")

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__lxstat64.lstat.05", "No errors", __lxstat64_spec==0 && *errno==SUT_EOK);


        search_result=getFile_FileSystem(fs, concated);


        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                        create_FileStatus_FromFile(context, search_result));

        DUMP("$(obj) is a ", path);
        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * For symbolic links, the st_mode member shall contain meaningful
         * information when used with the file type macros, and the st_size
         * member shall contain the length of the pathname contained in the
         * symbolic link.
         */
        /*
         * The lstat() function shall be equivalent to stat(), except when path
         * refers to a symbolic link. In that case lstat() shall return
         * information about the link, while stat() shall return information
         * about the file the link references.
         */
        REQ("__lxstat64.lstat.01;__lxstat64.lstat.02", "Stat structure filled properly",
                checkFileStatusEquality(context, buff, search_result));



        return true;
    }
}


Bool3 shall_isEOVERFLOW_fxstat64(CallContext context, FileDescId fildes)
{
    CString* path=getPath_FileDescId(fildes);
    FileSystem* fs=getFileSystem(context);

    return shall_isEOVERFLOW_xstat64(context, fs, path);
}
Bool3 may_isEOVERFLOW_fxstat64(CallContext context, FileDescId fildes)
{
    CString* path=getPath_FileDescId(fildes);
    FileSystem* fs=getFileSystem(context);

    return may_isEOVERFLOW_xstat64(context, fs, path);
}

specification
IntT __fxstat64_spec( CallContext context, IntT ver, FileDescId fildes, FileStatus * buff, ErrorCode * errno )
{
    pre
    {
        /*
         * ver shall be 3 or the behavior of these functions is undefined.
         */
        REQ( "app.__fxstat64.09", "ver shall be 3 or the behavior is undefined", ver == 3 );

        return true;
    }
    post
    {
        FileSystem *file_system;
        File *search_result;
        Bool3  isELOOP;

        VERBOSE("system==%d, file==%d\n", fildes.system, fildes.filedesc);

        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_FSTAT64, "__fxstat64.fstat.05", __fxstat64_spec==-1,  *errno)
        /*
         * The fstat64() function shall fail if:
         *
         * [EBADF]
         *
         * The fildes argument is not a valid file descriptor.
         *
         */
            ERROR_SHALL3(POSIX_FSTAT64, EBADF,"?__fxstat64.fstat.06.01",
                                shall_isEBADF_fxstat(context, fildes, errno))

        /*
         * The fstat64() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the file
         * or the file serial number cannot be represented correctly in the
         * structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_FSTAT64, EOVERFLOW,"__fxstat64.fstat.06.03",
                            shall_isEOVERFLOW_fxstat(context, fildes))
        /*
         * The fstat64() function may fail if:
         *
         * [EOVERFLOW]
         *
         * One of the values is too large to store into the structure pointed
         * to by the buf argument.
         *
         */
            ERROR_MAY3(POSIX_FSTAT64, EOVERFLOW,"__fxstat64.fstat.07.01",
                                may_isEOVERFLOW_fxstat(context, fildes))
        /*
         * The fstat64() function shall fail if:
         *
         * [EIO]
         *
         * An I/O error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_FSTAT64, EIO,"__fxstat64.fstat.06.02", "")

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__fxstat64.fstat.04", "Errors mustn't reach here:)",
                                __fxstat64_spec==0 && *errno==SUT_EOK);

        file_system = getFileSystem(context);
        search_result = getFile_FileSystem(file_system,
resolvePath_Ext(context, file_system, getPath_FileDescId(fildes), &isELOOP));

        if(search_result==NULL)
        {
            VERBOSE("Unable to get file for fildes==%d: possibly working with"
                    " unresolved symlink\n", fildes.filedesc);
            return true;
        }

        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                        create_FileStatus_FromFile(context, search_result));

        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * The fstat() function shall obtain information about an open file
         * associated with the file descriptor fildes, and shall write it to
         * the area pointed to by buf.
         */
        /*
         * [SHM] If fildes references a shared memory object, the
         * implementation shall update in the stat structure pointed to by the
         * buf argument only the st_uid, st_gid, st_size, and st_mode fields,
         * and only the S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and
         * S_IWOTH file permission bits need be valid. The implementation may
         * update other fields and flags.
         */
        /*
         * [TYM] If fildes references a typed memory object, the implementation
         * shall update in the stat structure pointed to by the buf argument
         * only the st_uid, st_gid, st_size, and st_mode fields, and only the
         * S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH file
         * permission bits need be valid. The implementation may update other
         * fields and flags.
         */
        REQ("__fxstat64.fstat.01;__fxstat64.fstat.02;__fxstat64.fstat.03",
            "Stat structure filled properly",
            checkFileStatusEqualityFXStat(context, buff, search_result));



        return true;
    }
}

/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

NAME

    __xstat -- get File Status

SYNOPSIS

    #include <sys/stat.h> #include <unistd.h>

    int __xstat(int ver, const char * path, struct stat * stat_buf);
    int __lxstat(int ver, const char * path, struct stat * stat_buf);
    int __fxstat(int ver, int fildes, struct stat * stat_buf);

DESCRIPTION

    The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
    POSIX (2003) functions stat(), lstat(), and fstat() respectively.

    ver shall be 3 or the behavior of these functions is undefined.

    __xstat(3, path, stat_buf) shall implement stat(path, stat_buf) as specified
    by ISO POSIX (2003).

    __lxstat(3, path, stat_buf) shall implement lstat(path, stat_buf) as
    specified by ISO POSIX (2003).

    __fxstat(3, fildes, stat_buf) shall implement fstat(fildes, stat_buf) as
    specified by ISO POSIX (2003).

    __xstat(), __lxstat(), and __fxstat() are not in the source standard; they
    are only in the binary standard.

    stat(), lstat(), and fstat() are not in the binary standard; they are only
    in the source standard.
*/
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

  refers

The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Copyright (c) 2001-2004 The IEEE and The Open Group, All Rights reserved.

NAME

    lstat - get file status

SYNOPSIS

    #include <sys/stat.h>

    int lstat(const char *restrict path, struct stat *restrict buf);

DESCRIPTION

    The lstat() function shall be equivalent to stat(), except when path refers
    to a symbolic link. In that case lstat() shall return information about the
    link, while stat() shall return information about the file the link
    references.

    For symbolic links, the st_mode member shall contain meaningful information
    when used with the file type macros, and the st_size member shall contain
    the length of the pathname contained in the symbolic link. File mode bits
    and the contents of the remaining members of the stat structure are
    unspecified. The value returned in the st_size member is the length of the
    contents of the symbolic link, and does not count any trailing null.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall be
    returned and errno set to indicate the error.

ERRORS

    The lstat() function shall fail if:

    [EACCES]

        Search permission is denied for a component of the path prefix.

    [EIO]

        An error occurred while reading from the file system.

    [ELOOP]

        A loop exists in symbolic links encountered during resolution of the
        path argument.

    [ENAMETOOLONG]

        The length of the path argument exceeds {PATH_MAX} or a pathname
        component is longer than {NAME_MAX}.

    [ENOENT]

        A component of path does not name an existing file or path is an empty
        string.

    [ENOTDIR]

        A component of the path prefix is not a directory.

    [EOVERFLOW]

        The file size in bytes or the number of blocks allocated to the file or
        the file serial number cannot be represented correctly in the structure
        pointed to by buf.


    The lstat() function may fail if:

    [ELOOP]

        More than {SYMLOOP_MAX} symbolic links were encountered during
        resolution of the path argument.

    [ENAMETOOLONG]

        As a result of encountering a symbolic link in resolution of the path
        argument, the length of the substituted pathname string exceeded
        {PATH_MAX}.

    [EOVERFLOW]

        A value to be stored would overflow one of the members of the stat
        structure.
*/

specification
IntT __lxstat_spec( CallContext context, IntT ver, CString * path, FileStatus * buff, ErrorCode * errno )
{
    pre
    {
        /*
         * The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
         * POSIX (2003) functions stat(), lstat(), and fstat() respectively.ver shall be 3
         * or the behavior of these functions is undefined.
         */
        REQ( "app.__lxstat.30", "ver shall be 3 or the behavior is undefined", ver == 3 );

       return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* parent=getParentDir_Path(path);
        CString* basename=getBaseName_Path(path);
        CString* resolved=resolvePath_Ext(context, fs, parent, &eloop);
        CString* concated=NULL;
        File* search_result;

        if(resolved!=NULL && basename!=NULL)
            concated=concat_Path(resolved, basename);
        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_LSTAT, "__lxstat.lstat.06", __lxstat_spec==-1, *errno)
        /*
         * The lstat() function shall fail if:
         *
         * [EACCES]
         *
         * A component of the path prefix denies search permission.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, EACCES,"__lxstat.lstat.03.01",
                                shall_isEACCES_lxstat(context, fs, concated))

        /*
         * The lstat() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of
         * the path argument.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, ELOOP,"__lxstat.lstat.03.03", eloop)

        /*
         * The lstat() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * The length of a pathname exceeds {PATH_MAX} or a pathname component
         * is longer than {NAME_MAX}.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, ENAMETOOLONG,"__lxstat.lstat.03.04",
                            shall_isENAMETOOLONG_lxstat(context, path))

        /*
         * The lstat() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, ENOTDIR,"__lxstat.lstat.03.05",
                                shall_isENOTDIR_lxstat(context, fs, concated))

        /*
         * The lstat() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, ENOENT,"__lxstat.lstat.03.06",
                                shall_isENOENT_lxstat(context, fs, concated))
        /*
         * The lstat() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the
         * file or the file serial number cannot be represented correctly
         * in the structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_LSTAT, EOVERFLOW,"__lxstat.lstat.03.07",
                            shall_isEOVERFLOW_lxstat(context, fs, concated))

        /*
         * The lstat() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         *
         */
            ERROR_MAY3(POSIX_LSTAT, ELOOP,"__lxstat.lstat.04.01", eloop)
        /*
         * The lstat() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * As a result of encountering a symbolic link in resolution of the
         * path argument, the length of the substituted pathname
         * string exceeded {PATH_MAX}.
         *
         */
            ERROR_MAY3(POSIX_LSTAT, ENAMETOOLONG,"__lxstat.lstat.04.02",
                            may_isENAMETOOLONG_lxstat(context, concated))

        /*
         * The lstat() function may fail if:
         *
         * [EOVERFLOW]
         *
         * One of the members is too large to store into the structure pointed
         * to by the buf argument.
         *
         */
            ERROR_MAY3(POSIX_LSTAT, EOVERFLOW,"__lxstat.lstat.04.03",
                           may_isEOVERFLOW_lxstat(context, fs, concated))
        /*
         * The lstat() function shall fail if:
         *
         * [EIO]
         *
         * An error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_LSTAT, EIO,"__lxstat.lstat.03.02", "")

        ERROR_END()

        VERBOSE("__lxstat==%d, errno==%d\n", __lxstat_spec, *errno);

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__lxstat.lstat.05", "No errors", __lxstat_spec==0 && *errno==SUT_EOK);

        search_result=getFile_FileSystem(fs, concated);


        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                            create_FileStatus_FromFile(context, search_result));

        DUMP("$(obj) is a ", path);
        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * For symbolic links, the st_mode member shall contain meaningful
         * information when used with the file type macros, and the st_size
         * member shall contain the length of the pathname contained in the
         * symbolic link.
         */
        /*
         * The lstat() function shall be equivalent to stat(), except when path
         * refers to a symbolic link. In that case lstat() shall return
         * information about the link, while stat() shall return information
         * about the file the link references.
         */

        if(!SKIP_LXSTAT_CHECK)
        {
            REQ("__lxstat.lstat.01;__lxstat.lstat.02", "Stat structure filled properly",
                    checkFileStatusEquality(context, buff, search_result));
        }


        parent=resolvePath_Ext(context, getFileSystem(context), path, &eloop);
        DUMP("resolve_all==$(obj), filestat==$(obj)",
            parent,
            create_FileStatus_FromFile(context, getFile_FileSystem(fs, parent))
            );

        /*
         * __lxstat(3, path, stat_buf) shall implement lstat(path, stat_buf) as specified
         * by ISO POSIX (2003).
         */
        REQ( "__lxstat.30", "__lxstat(3, path, stat_buf) shall implement lstat(path, stat_buf)",
                            GENERAL_REQ( "__lxstat.lstat.*" )
           );

        return true;
    }
}

void on__LXStat( CallContext context, CString* path,
                            FileStatus* buff, IntT ret)
{
    if(ret!=-1)
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* parent=getParentDir_Path(path);
        CString* basename=getBaseName_Path(path);
        CString* concated, *resolved;
        File* search_result;

        if(parent==NULL || basename==NULL)
            return;

        resolved=resolvePath_Ext(context, fs, parent, &eloop);
        if(resolved==NULL)
        {
            resetTimeFlags_FileSystem(fs);
            return;
        }

        concated=concat_Path(resolved, basename);

        search_result=getFile_FileSystem(fs, concated);

        if(search_result!=NULL)
        {
            VERBOSE("\nUpdating...%s\n\n", *concated);
        }
        else
        {
            VERBOSE("\nRegistering...%s\n\n", *concated);

            registerFile_Kind(fs, concated, buff->kind);

            fs = getFileSystem(context);
            search_result = getFile_FileSystem(fs, concated);
        }

        updateFile_FromFileStatus(context, search_result, buff);
    }

}

/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

NAME

    __xstat -- get File Status

SYNOPSIS

    #include <sys/stat.h> #include <unistd.h>

    int __xstat(int ver, const char * path, struct stat * stat_buf);
    int __lxstat(int ver, const char * path, struct stat * stat_buf);
    int __fxstat(int ver, int fildes, struct stat * stat_buf);

DESCRIPTION

    The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
    POSIX (2003) functions stat(), lstat(), and fstat() respectively.

    ver shall be 3 or the behavior of these functions is undefined.

    __xstat(3, path, stat_buf) shall implement stat(path, stat_buf) as specified
    by ISO POSIX (2003).

    __lxstat(3, path, stat_buf) shall implement lstat(path, stat_buf) as
    specified by ISO POSIX (2003).

    __fxstat(3, fildes, stat_buf) shall implement fstat(fildes, stat_buf) as
    specified by ISO POSIX (2003).

    __xstat(), __lxstat(), and __fxstat() are not in the source standard; they
    are only in the binary standard.

    stat(), lstat(), and fstat() are not in the binary standard; they are only
    in the source standard.
*/
/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

  refers

The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Copyright (c) 2001-2004 The IEEE and The Open Group, All Rights reserved.


NAME

    fstat - get file status

SYNOPSIS

    #include <sys/stat.h>

    int fstat(int fildes, struct stat *buf);

DESCRIPTION

    The fstat() function shall obtain information about an open file associated
    with the file descriptor fildes, and shall write it to the area pointed to
    by buf.

    [SHM]  If fildes references a shared memory object, the implementation
    shall update in the stat structure pointed to by the buf argument only the
    st_uid, st_gid, st_size, and st_mode fields, and only the S_IRUSR, S_IWUSR,
    S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH file permission bits need be valid.
    The implementation may update other fields and flags.

    [TYM]  If fildes references a typed memory object, the implementation shall
    update in the stat structure pointed to by the buf argument only the
    st_uid, st_gid, st_size, and st_mode fields, and only the S_IRUSR, S_IWUSR,
    S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH file permission bits need be valid.
    The implementation may update other fields and flags.

    The buf argument is a pointer to a stat structure, as defined in
    <sys/stat.h>, into which information is placed concerning the file.

    The structure members st_mode, st_ino, st_dev, st_uid, st_gid, st_atime,
    st_ctime, and st_mtime shall have meaningful values for all other file
    types defined in this volume of IEEE Std 1003.1-2001. The value of the
    member st_nlink shall be set to the number of links to the file.

    An implementation that provides additional or alternative file access
    control mechanisms may, under implementation-defined conditions, cause
    fstat() to fail.

    The fstat() function shall update any time-related fields as described in
    the Base Definitions volume of IEEE Std 1003.1-2001, Section 4.7, File
    Times Update, before writing into the stat structure.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall be
    returned and errno set to indicate the error.

ERRORS

    The fstat() function shall fail if:

    [EBADF]

        The fildes argument is not a valid file descriptor.

    [EIO]

        An I/O error occurred while reading from the file system.

    [EOVERFLOW]

        The file size in bytes or the number of blocks allocated to the file or
        the file serial number cannot be represented correctly in the structure
        pointed to by buf.

    The fstat() function may fail if:

    [EOVERFLOW]

        One of the values is too large to store into the structure pointed to
        by the buf argument.
*/

bool equalsFilePermission(FilePermission* first, FilePermission* second)
{
    if(first==NULL && second==NULL)
        return true;

    if(first!=NULL && second!=NULL)
        return first->read==second->read && first->write==second->write
            && first->execute==second->execute;

    return false;
}

void updateFile_FromFileStatusFXStat(CallContext context, File* file,
                                                        FileStatus* status)
{
    if(   POSIX_OPTION(context, SHM) && status->kind==SharedMemoryObject
      ||  POSIX_OPTION(context, TYM) && status->kind==TypedMemoryObject )
    {
        if(file->permissions==NULL)
        {
            if(status->permissions!=NULL)
                file->permissions=clone(status->permissions);
        }
        if(file->uid==NULL)
            file->uid=create_UidTObj(status->uid);
        if(file->gid==NULL)
            file->gid=create_GidTObj(status->gid);
        if(file->size==NULL)
            file->size=create_OffTObj(status->size);
    }
    else
        updateFile_FromFileStatus(context, file, status);
}

bool checkFileStatusEqualityFXStat(CallContext context, FileStatus* first,
                                                        File* file)
{
    FileStatus* second=create_FileStatus_FromFile(context, file);


    if( POSIX_OPTION(context, SHM) &&
            first->kind==SharedMemoryObject != second->kind==SharedMemoryObject
    ||
        POSIX_OPTION(context, TYM) &&
            first->kind==TypedMemoryObject != second->kind==TypedMemoryObject)

            return false;

    if(   POSIX_OPTION(context, SHM) &&
        (first->kind==SharedMemoryObject && second->kind==SharedMemoryObject)
      ||  POSIX_OPTION(context, TYM) &&
        (first->kind==TypedMemoryObject && second->kind==TypedMemoryObject))
    {
        if(first->kind==SharedMemoryObject && second->kind==SharedMemoryObject)

        if((first->permissions==NULL) != (second->permissions==NULL))
        {
            VERBOSE("permission 1 failed...\n");
            return false;
        }
        if(     !equalsFilePermission(first->permissions->owner,
                                                second->permissions->owner)
            ||  !equalsFilePermission(first->permissions->group,
                                                second->permissions->group)
            ||  !equalsFilePermission(first->permissions->other,
                                                second->permissions->other)
          )
        {
            VERBOSE("permissions 2 failed...\n");
            return false;
        }
        if(first->uid!=second->uid)
        {
            VERBOSE("uid failed...\n");
            return false;
        }
        if(first->gid!=second->gid)
        {
            VERBOSE("gid failed...\n");
            return false;
        }
        if( first->size!=second->size &&
            (first->kind==SymbolicLinkFile || first->kind==RegularFile
                ||
             (
                POSIX_OPTION(context, SHM) && first->kind==SharedMemoryObject
             || POSIX_OPTION(context, TYM) && first->kind==TypedMemoryObject
             )
            )
          )
        {
            VERBOSE("size failed...\n");
            return false;
        }

        return true;
    }

    return checkFileStatusEquality(context, first, file);
}

Bool3 shall_isEBADF_fxstat(CallContext context, FileDescId fildes,
                                                            ErrorCode* errno)
{
    if(*errno==SUT_EBADF)
    {
        CString* path=getPath_FileDescId(fildes);

        return path==NULL? Unknown_Bool3: True_Bool3;
    }
    return Unknown_Bool3;
}
Bool3 shall_isEOVERFLOW_fxstat(CallContext context, FileDescId fildes)
{
    CString* path=getPath_FileDescId(fildes);
    FileSystem* fs=getFileSystem(context);

    return shall_isEOVERFLOW_xstat(context, fs, path);
}
Bool3 may_isEOVERFLOW_fxstat(CallContext context, FileDescId fildes)
{
    CString* path=getPath_FileDescId(fildes);
    FileSystem* fs=getFileSystem(context);

    return may_isEOVERFLOW_xstat(context, fs, path);
}

specification
IntT __fxstat_spec( CallContext context, IntT ver, FileDescId fildes, FileStatus * buff, ErrorCode * errno )
{
    pre
    {
        /*
         * The functions __xstat(), __lxstat(), and __fxstat() shall implement the ISO
         * POSIX (2003) functions stat(), lstat(), and fstat() respectively.ver shall be 3
         * or the behavior of these functions is undefined.
         */
        REQ( "app.__fxstat.30", "ver shall be 3 or the behavior is undefined", ver == 3 );

        return true;
    }
    post
    {
        FileSystem *file_system;
        File *search_result;
        Bool3 isELOOP;

        VERBOSE("system==%d, file==%d\n", fildes.system, fildes.filedesc);
        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_FSTAT, "__fxstat.fstat.05", __fxstat_spec==-1,  *errno )
        /*
         * The fstat() function shall fail if:
         *
         * [EBADF]
         *
         * The fildes argument is not a valid file descriptor.
         *
         */
            ERROR_SHALL3(POSIX_FSTAT, EBADF,"?__fxstat.fstat.06.01",
                                shall_isEBADF_fxstat(context, fildes, errno))

        /*
         * The fstat() function shall fail if:
         *
         * [EOVERFLOW]
         *
         * The file size in bytes or the number of blocks allocated to the file
         * or the file serial number cannot be represented correctly in the
         * structure pointed to by buf.
         *
         */
            ERROR_SHALL3(POSIX_FSTAT, EOVERFLOW,"__fxstat.fstat.06.03",
                            shall_isEOVERFLOW_fxstat(context, fildes))
        /*
         * The fstat() function may fail if:
         *
         * [EOVERFLOW]
         *
         * One of the values is too large to store into the structure pointed
         * to by the buf argument.
         *
         */
            ERROR_MAY3(POSIX_FSTAT, EOVERFLOW,"__fxstat.fstat.07.01",
                                may_isEOVERFLOW_fxstat(context, fildes))
        /*
         * The fstat() function shall fail if:
         *
         * [EIO]
         *
         * An I/O error occurred while reading from the file system.
         *
         */
            ERROR_UNCHECKABLE(POSIX_FSTAT, EIO,"__fxstat.fstat.06.02", "")

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("__fxstat.fstat.04", "Errors mustn't reach here:)",
                                __fxstat_spec==0 && *errno==SUT_EOK);

        file_system = getFileSystem(context);
        search_result = getFile_FileSystem(file_system,
resolvePath_Ext(context, file_system, getPath_FileDescId(fildes), &isELOOP));

        if(search_result==NULL)
        {
            VERBOSE("Unable to get file for fildes==%d: possibly working with"
                    " unresolved symlink\n", fildes.filedesc);
            return true;
        }

        DUMP("Buffer==$(obj)\n", buff);
        DUMP("Created from file==$(obj)\n",
                        create_FileStatus_FromFile(context, search_result));

        printKind(buff->kind);
        VERBOSE("\n");

        /*
         * The fstat() function shall obtain information about an open file
         * associated with the file descriptor fildes, and shall write it to
         * the area pointed to by buf.
         */
        /*
         * [SHM] If fildes references a shared memory object, the
         * implementation shall update in the stat structure pointed to by the
         * buf argument only the st_uid, st_gid, st_size, and st_mode fields,
         * and only the S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and
         * S_IWOTH file permission bits need be valid. The implementation may
         * update other fields and flags.
         */
        /*
         * [TYM] If fildes references a typed memory object, the implementation
         * shall update in the stat structure pointed to by the buf argument
         * only the st_uid, st_gid, st_size, and st_mode fields, and only the
         * S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, and S_IWOTH file
         * permission bits need be valid. The implementation may update other
         * fields and flags.
         */
        REQ("__fxstat.fstat.01;__fxstat.fstat.02;__fxstat.fstat.03", "Stat structure filled properly",
                checkFileStatusEqualityFXStat(context, buff, search_result));

        /*
         * __fxstat(3, fildes, stat_buf) shall implement fstat(fildes, stat_buf) as
         * specified by ISO POSIX (2003).
         */
        REQ( "__fxstat.30", "__fxstat(3, fildes, stat_buf) shall implement fstat(fildes, stat_buf)",
                            GENERAL_REQ( "__fxstat.fstat.*" )
           );

        return true;
    }
}

void on__FXStat( CallContext context, FileDescId fildes,
                            FileStatus* buff, IntT ret)
{
    if(ret!=-1)
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* path=getPath_FileDescId(fildes);
        CString* resolved=NULL;
        File* search_result;

        if(path==NULL)
            return;

        resolved=resolvePath_Ext(context, fs, path, &eloop);

        if(resolved==NULL)
            return;

        DUMP("fxstat resolved==$(obj)\n", resolved);

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result!=NULL)
        {
            VERBOSE("\nUpdating...%s\n\n", *resolved);
        }

        updateFile_FromFileStatusFXStat(context, search_result, buff);
    }
}

/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

  refers

The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2004 Edition
Copyright (c) 2001-2004 The IEEE and The Open Group, All Rights reserved.

NAME

    utime - set file access and modification times

SYNOPSIS

    #include <utime.h>

    int utime(const char *path, const struct utimbuf *times);

DESCRIPTION

    The utime() function shall set the access and modification times of the
    file named by the path argument.

    If times is a null pointer, the access and modification times of the file
    shall be set to the current time. The effective user ID of the process
    shall match the owner of the file, or the process has write permission to
    the file or has appropriate privileges, to use utime() in this manner.

    If times is not a null pointer, times shall be interpreted as a pointer to
    a utimbuf structure and the access and modification times shall be set to
    the values contained in the designated structure. Only a process with the
    effective user ID equal to the user ID of the file or a process with
    appropriate privileges may use utime() this way.

    The utimbuf structure is defined in the <utime.h> header. The times in the
    structure utimbuf are measured in seconds since the Epoch.

    Upon successful completion, utime() shall mark the time of the last file
    status change, st_ctime, to be updated; see <sys/stat.h>.

RETURN VALUE

    Upon successful completion, 0 shall be returned.
    Otherwise, -1 shall be returned and errno shall be set to indicate the
    error, and the file times shall not be affected.

ERRORS

    The utime() function shall fail if:

        [EACCES]

        Search permission is denied by a component of the path prefix; or the
        times argument is a null pointer and the effective user ID of the
        process does not match the owner of the file, the process does not
        have write permission for the file, and the process does not have
        appropriate privileges.

        [ELOOP]

        A loop exists in symbolic links encountered during resolution of the
        path argument.

        [ENAMETOOLONG]

        The length of the path argument exceeds {PATH_MAX} or a pathname
        component is longer than {NAME_MAX}.

        [ENOENT]

        A component of path does not name an existing file or path is an empty
        string.

        [ENOTDIR]

        A component of the path prefix is not a directory.

        [EPERM]

        The times argument is not a null pointer and the calling process'
        effective user ID does not match the owner of the file and the calling
        process does not have the appropriate privileges.

        [EROFS]

        The file system containing the file is read-only.

    The utime() function may fail if:

        [ELOOP]

        More than {SYMLOOP_MAX} symbolic links were encountered during
        resolution of the path argument.

        [ENAMETOOLONG]

        As a result of encountering a symbolic link in resolution of the path
        argument, the length of the substituted pathname string exceeded
        {PATH_MAX}.
*/

specification typedef struct UTimBuf UTimBuf = {};

UTimBuf* create_UTimBuf(TimeT atime, TimeT mtime)
{
    return create(&type_UTimBuf, atime, mtime);
}

Bool3 shall_isEACCES_utime(CallContext context, FileSystem* fs, CString* path,
                                        bool isNULL)
{
    Bool3 res = False_Bool3, nl=False_Bool3;
    CString* parent;
    ProcessState* ps;
    File* fl;
    FileStatus* file_status;

    if(!isAbsolute_Path(path))
        return Unknown_Bool3;

    parent = clone(getParentDir_Path(path));

    if(NULL==parent)  // is child of root
        return Unknown_Bool3;

    res = or_Bool3(res, isNoPermOnPathComponents(context, fs, parent,
                                        true, false, false)); // check search

    if(isNULL)
    {
        nl=True_Bool3;
        ps=getProcessState_CallContext(context);
        fl=getFile_FileSystem(fs, path);
        file_status=create_FileStatus_FromFile(context, fl);

        if(fl==NULL)
            return res;

        if(fl->uid!=NULL)
        {
            if(ps->meta.effective_userid==*(fl->uid))
                nl = False_Bool3;
        }
        else
            nl = and_Bool3(nl, Unknown_Bool3);

        nl = and_Bool3(nl, isNoPermOnPath(context, fs, path,
                                        false, true, false)); // write_access
        nl = and_Bool3(nl, not_Bool3(hasAppropriatePrivileges(context, utime_AccessPrivileges, fl->fileid)));

        res= or_Bool3 (res, nl);
    }

    return res;
}

Bool3 shall_isEPERM_utime(CallContext context, FileSystem* fs, CString* path,
                                        bool isNULL)
{
    Bool3 nl=False_Bool3;
    ProcessState* ps=getProcessState_CallContext(context);
    File* fl;
    FileStatus* file_status;

    if(!isNULL)
    {
        nl=True_Bool3;
        ps=getProcessState_CallContext(context);
        fl=getFile_FileSystem(fs, path);
        file_status=create_FileStatus_FromFile(context, fl);

        if(fl==NULL)
            return Unknown_Bool3;

        if(fl->uid!=NULL)
        {
            if(ps->meta.effective_userid==*(fl->uid))
                nl = False_Bool3;
        }
        else
            nl = and_Bool3(nl, Unknown_Bool3);

        nl = and_Bool3(nl, not_Bool3(hasAppropriatePrivileges(context, utime_AccessPrivileges, fl->fileid)));
    }

    return nl;
}
Bool3 shall_isEROFS_xstat()
{
    return Unknown_Bool3;
}

UTimBuf* create_UTimBuf_FromFile(CallContext context, File* file)
{
    TimeT actime=-1, modtime=-1;

    if(file==NULL)
        return NULL;

    if(file->atime!=NULL)
        actime=*(file->atime);

    if(file->mtime!=NULL)
        modtime=*(file->mtime);

    return create_UTimBuf(actime, modtime);
}
bool checkUTimBufEquality(CallContext context, UTimBuf* first, File* file)
{
    UTimBuf* second=create_UTimBuf_FromFile(context, file);

    if(second==NULL)
        return true;

    if(first!=NULL)//actime is not checked because it is false in anyway
    {
        VERBOSE("file->ctime_update==%s\n", file->ctime_updated?
                                                        "true": "false");

        VERBOSE("file->atime_update==%s\n", file->atime_updated?
                                                        "true": "false");

        DUMP("First==$(obj)\n", first);

        return (file->atime_updated==true? second->actime==first->actime: true)
            && (file->mtime_updated==true?second->modtime==first->modtime:true)
            && file->ctime_updated == false;
    }
    else
    {
        return file->atime_updated==false
            && file->mtime_updated==false && file->ctime_updated==false;
    }
}

specification
IntT utime_spec( CallContext context, CString* path, UTimBuf* times,
                                                            ErrorCode* errno)
{
    pre
    {
        return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* resolved=resolvePath_Ext(context, fs, path, &eloop);
        File* search_result;

        DUMP("resolved==$(obj)\n", resolved);

        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_UTIME, "utime.05", utime_spec==-1, *errno)
        /*
         * The utime() function shall fail if:
         *
         * [EACCES]
         *
         * Search permission is denied by a component of the path prefix; or
         * the times argument is a null pointer and the effective
         * user ID of the process does not match the owner of the file, the
         * process does not have write permission for the file, and the
         * process does not have appropriate privileges.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, EACCES, "utime.06.01",
                            shall_isEACCES_utime(context, fs, resolved, times==NULL))

        /*
         * The utime() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of the
         * path argument.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, ELOOP, "utime.06.02", eloop)

        /*
         * The utime() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * The length of the path argument exceeds {PATH_MAX} or a pathname
         * component is longer than {NAME_MAX}.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, ENAMETOOLONG, "utime.06.03",
                                shall_isENAMETOOLONG_utime(context, path))

        /*
         * The utime() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, ENOENT, "utime.06.04",
                                shall_isENOENT_utime(context, fs, resolved))

        /*
         * The utime() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, ENOTDIR, "utime.06.05",
                                        shall_isENOTDIR_utime(context, fs,
                                                getParentDir_Path(resolved)))

        /*
         * The utime() function shall fail if:
         *
         * [EPERM]
         *
         * The times argument is not a null pointer and the calling process'
         * effective user ID does not match the owner of the file
         * and the calling process does not have the appropriate privileges.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, EPERM, "utime.06.06",
                shall_isEPERM_utime(context, fs, resolved, times==NULL))

        /*
         * The utime() function shall fail if:
         *
         * [EROFS]
         *
         * The file system containing the file is read-only.
         *
         */
            ERROR_SHALL3(POSIX_UTIME, EROFS, "utime.06.07", Unknown_Bool3)

        /*
         * The utime() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         *
         */
            ERROR_MAY3(POSIX_UTIME, ELOOP, "utime.07.01", eloop)

        /*
         * The utime() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         *
         * As a result of encountering a symbolic link in resolution of the
         * path argument, the length of the substituted pathname
         * string exceeded {PATH_MAX}.
         *
         */
            ERROR_MAY3(POSIX_UTIME, ENAMETOOLONG, "utime.07.02",
                                may_isENAMETOOLONG_utime(context, resolved))
        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("utime.04", "Successful completion",
                                utime_spec==0 && *errno==SUT_EOK);
        if(resolved==NULL)
        {
            DUMP("Unable to resolve path...$(obj)\n", path);
            return true;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result==NULL)
        {
            VERBOSE("File isn't registered...\n");
            return true;
        }

        DUMP("Times==$(obj)\n", times);
        DUMP("Created from file==$(obj)\n",
                        create_UTimBuf_FromFile(context, search_result));

        /*
         * The utime() function shall set the access and modification times of
         * the file named by the path argument.
         */
        /*
         * If times is a null pointer, the access and modification times of the
         * file shall be set to the current time. The effective user ID of the
         * process shall match the owner of the file, or the process has write
         * permission to the file or has appropriate privileges, to use utime()
         * in this manner.
         */
        /*
         * If times is not a null pointer, times shall be interpreted as a
         * pointer to a utimbuf structure and the access and modification times
         * shall be set to the values contained in the designated structure.
         * Only a process with the effective user ID equal to the user ID of
         * the file or a process with appropriate privileges may use utime()
         * this way.
         */
        REQ("utime.01;utime.02;utime.03", "Stat structure filled properly",
                checkUTimBufEquality(context, times, search_result));

        return true;
    }
}

void onUtime( CallContext context, CString* path,
                            UTimBuf* times, IntT ret)
{
    if(ret!=-1)
    {
        Bool3 eloop;
        CString* resolved;
        FileSystem* fs=getFileSystem(context);
        File* search_result;

        resolved=resolvePath_Ext(context, fs, path, &eloop);

        if(resolved==NULL)
        {
            resetTimeFlags_FileSystem(fs);
            return;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result!=NULL)
            VERBOSE("\nUpdating...%s\n\n", *resolved);

        updateFile_FromUtimBuf(context, search_result, times);

        if(FEDORA==1)
        {
            updateAtimePath(context, fs, resolved);
            resolved = getParentDir_Path(resolved);
            updateAtimePath(context, fs, resolved);
            ts_sleep_msec(2000);
        }
    }
}

void updateFile_FromUtimBuf( CallContext context, File* file,
                                                            UTimBuf* times)
{
    if(file==NULL)
        return;

    if(times!=NULL)
    {
        file->atime=create_TimeTObj(times->actime);
        file->mtime=create_TimeTObj(times->modtime);

        file->ctime_updated=false;
    }
    else
    {
        file->atime_updated=false;//false if we need updating, otherwise true
        file->mtime_updated=false;
        file->ctime_updated=false;
    }
}


/*
Linux Standard Base Core Specification 3.1
Copyright (c) 2004, 2005 Free Standards Group

    refers

The Open Group Base Specifications Issue 6

IEEE Std 1003.1, 2004 Edition

Copyright (c) 2001-2004 The IEEE and The Open Group, All Rights reserved.

NAME

    utimes - set file access and modification times (LEGACY)

SYNOPSIS

    [XSI] #include <sys/time.h>

    int utimes(const char *path, const struct timeval times[2]);

DESCRIPTION

    The utimes() function shall set the access and modification times of the
    file pointed to by the path argument to the value of the times argument.
    The utimes() function allows time specifications accurate to the
    microsecond.

    For utimes(), the times argument is an array of timeval structures. The
    first array member represents the date and time of last access, and the
    second member represents the date and time of last modification. The times
    in the timeval structure are measured in seconds and microseconds since the
    Epoch, although rounding toward the nearest second may occur.

    If the times argument is a null pointer, the access and modification times
    of the file shall be set to the current time.The effective user ID of the
    process shall match the owner of the file, or has write access to the file
    or appropriate privileges to use this call in this manner. Upon completion,
    utimes() shall mark the time of the last file status change, st_ctime, for
    update.

RETURN VALUE

    Upon successful completion, 0 shall be returned. Otherwise, -1 shall be
    returned and errno shall be set to indicate the error, and the file times
    shall not be affected.

ERRORS

    The utimes() function shall fail if:

        [EACCES]

        Search permission is denied by a component of the path prefix; or the
        times argument is a null pointer and the effective user ID of the
        process does not match the owner of the file and write access is
        denied.

        [ELOOP]

        A loop exists in symbolic links encountered during resolution of the
        path argument.

        [ENAMETOOLONG]

        The length of the path argument exceeds {PATH_MAX} or a pathname
        component is longer than {NAME_MAX}.

        [ENOENT]

        A component of path does not name an existing file or path is an empty
        string.

        [ENOTDIR]

        A component of the path prefix is not a directory.

        [EPERM]

        The times argument is not a null pointer and the calling process'
        effective user ID has write access to the file but does not match the
        owner of the file and the calling process does not have the appropriate
        privileges.

        [EROFS]

        The file system containing the file is read-only.

    The utimes() function may fail if:

        [ELOOP]

        More than {SYMLOOP_MAX} symbolic links were encountered during
        resolution of the path argument.

        [ENAMETOOLONG]

        Pathname resolution of a symbolic link produced an intermediate result
        whose length exceeds {PATH_MAX}.
*/

List* create_TimeValList_FromFile(CallContext context, File* file)
{
    TimeVal* atime=NULL, *mtime=NULL;
    List* ret;

    if(file==NULL)
        return NULL;

    if(file->atime!=NULL)
        atime=create_TimeVal(*file->atime, 0);

    if(file->mtime!=NULL)
        mtime=create_TimeVal(*file->mtime, 0);

    ret=create_List(&type_TimeVal);
    append_List(ret, atime);
    append_List(ret, mtime);
    return ret;
}
bool checkTimeValEquality(TimeVal* first, TimeVal* second)
{
/*
 * The times in the timeval structure are measured in seconds and microseconds
 * since the Epoch, although rounding toward the nearest second may occur.
 */
IMPLEMENT_REQ("utimes.02");
    return first->tv_sec==second->tv_sec
        || first->tv_sec==second->tv_sec-1 && second->tv_usec>=500000
        || first->tv_sec==second->tv_sec+1 && first->tv_usec>=500000;
}
bool checkTimeValListEquality(CallContext context, List* first, File* file)
{
    List* second=create_TimeValList_FromFile(context, file);

    if(second==NULL)
        return true;

    if(first!=NULL)//actime is not checked because it is equal to false in anyway
    {
        VERBOSE("file->ctime_update==%s\n", file->ctime_updated?
                                                        "true": "false");

        VERBOSE("file->atime_update==%s\n", file->atime_updated?
                                                        "true": "false");

        DUMP("First==$(obj)\n", first);

        return (file->atime_updated==true? checkTimeValEquality(get_List(first,0), get_List(second, 0)): true)
            && (file->mtime_updated==true? checkTimeValEquality(get_List(first,1), get_List(second, 1)): true)
            && file->ctime_updated == false;
    }
    else
    {
        return file->atime_updated==false
            && file->mtime_updated==false && file->ctime_updated==false;
    }
}

specification
IntT utimes_spec( CallContext context, CString* path, List* times,
                                                            ErrorCode* errno)
{
    pre
    {
        return true;
    }
    post
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* resolved=resolvePath_Ext(context, fs, path, &eloop);
        File* search_result;

        DUMP("resolved==$(obj)\n", resolved);

        /*
         * Otherwise, -1 shall be returned and errno shall be set to indicate
         * the error, and the file times shall not be affected.
         */
        ERROR_BEGIN(POSIX_UTIMES, "utimes.08", utimes_spec==-1, *errno )
        /*
         * The utimes() function shall fail if:
         *
         * [EACCES]
         *
         * Search permission is denied by a component of the path prefix; or
         * the times argument is a null pointer and the effective user ID of
         * the process does not match the owner of the file and write access
         * is denied.
         */
            ERROR_SHALL3(POSIX_UTIMES, EACCES, "utimes.05.01",
                            shall_isEACCES_utimes(context, fs, resolved, times==NULL))

        /*
         * The utimes() function shall fail if:
         *
         * [ELOOP]
         *
         * A loop exists in symbolic links encountered during resolution of the
         * path argument.
         */
            ERROR_SHALL3(POSIX_UTIMES, ELOOP, "utimes.05.02", eloop)

        /*
         * The utimes() function shall fail if:
         *
         * [ENAMETOOLONG]
         *
         * The length of the path argument exceeds {PATH_MAX} or a pathname
         * component is longer than {NAME_MAX}.
         */
            ERROR_SHALL3(POSIX_UTIMES, ENAMETOOLONG, "utimes.05.03",
                                    shall_isENAMETOOLONG_utimes(context, path))

        /*
         * The utimes() function shall fail if:
         *
         * [ENOENT]
         *
         * A component of path does not name an existing file or path is an
         * empty string.
         */
            ERROR_SHALL3(POSIX_UTIMES, ENOENT, "utimes.05.04",
                                shall_isENOENT_utimes(context, fs, resolved))

        /*
         * The utimes() function shall fail if:
         *
         * [ENOTDIR]
         *
         * A component of the path prefix is not a directory.
         */
            ERROR_SHALL3(POSIX_UTIMES, ENOTDIR, "utimes.05.05",
                                            shall_isENOTDIR_utime(context, fs,
                                                getParentDir_Path(resolved)))

        /*
         * The utimes() function shall fail if:
         *
         * [EPERM]
         *
         * The times argument is not a null pointer and the calling process'
         * effective user ID has write access to the file but does not match
         * the owner of the file and the calling process does not have the
         * appropriate privileges.
         */
            ERROR_SHALL3(POSIX_UTIMES, EPERM, "utimes.05.06",
            shall_isEPERM_utimes(context, fs, resolved, times==NULL))

        /*
         * The utimes() function shall fail if:
         *
         * [EROFS]
         *
         * The file system containing the file is read-only.
         */
            ERROR_SHALL3(POSIX_UTIMES, EROFS, "utimes.05.07", TODO_ERR(EROFS))

        /*
         * The utimes() function may fail if:
         *
         * [ELOOP]
         *
         * More than {SYMLOOP_MAX} symbolic links were encountered during
         * resolution of the path argument.
         */
            ERROR_MAY3(POSIX_UTIMES, ELOOP, "utimes.06.01", eloop)

        /*
         * The utimes() function may fail if:
         *
         * [ENAMETOOLONG]
         *
         * Pathname resolution of a symbolic link produced an intermediate
         * result whose length exceeds {PATH_MAX}.
         */
            ERROR_MAY3(POSIX_UTIMES, ENAMETOOLONG, "utimes.06.02",
                                may_isENAMETOOLONG_utime(context, resolved))

        ERROR_END()

        /*
         * Upon successful completion, 0 shall be returned.
         */
        REQ("utimes.07", "Successful completion",
                                utimes_spec==0 && *errno==SUT_EOK);
        if(resolved==NULL)
        {
            DUMP("Unable to resolve path...$(obj)\n", path);
            return true;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result==NULL)
        {
            VERBOSE("File isn't registered...\n");
            return true;
        }

        DUMP("Times==$(obj)\n", times);
        DUMP("Created from file==$(obj)\n",
                        create_TimeValList_FromFile(context, search_result));

        /*
         * The utimes() function shall set the access and modification times of
         * the file pointed to by the path argument to the value of the times
         * argument. The utimes() function allows time specifications accurate
         * to the microsecond.
         */
        /*
         * If the times argument is a null pointer, the access and modification
         * times of the file shall be set to the current time.The effective
         * user ID of the process shall match the owner of the file, or has
         * write access to the file or appropriate privileges to use this call
         * in this manner.
         */
        /*
         * Upon completion, utimes() shall mark the time of the last file
         * status change, st_ctime, for update.
         */
        REQ("utimes.01;utimes.03;utimes.04", "Stat structure filled properly",
                checkTimeValListEquality(context, times, search_result));

        return true;
    }
}
void onUtimes( CallContext context, CString* path,
                            List* times, IntT ret)
{
    if(ret!=-1)
    {
        Bool3 eloop;
        CString* resolved;
        FileSystem* fs=getFileSystem(context);
        File* search_result;

        resolved=resolvePath_Ext(context, fs, path, &eloop);

        if(resolved==NULL)
        {
            resetTimeFlags_FileSystem(fs);
            return;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result!=NULL)
        {
            VERBOSE("\nUpdating...%s\n\n", *resolved);
        }
        updateFile_FromTimeValList(context, search_result, times);

        if(FEDORA==1)
        {
            updateAtimePath(context, fs, resolved);
            resolved = getParentDir_Path(resolved);
            updateAtimePath(context, fs, resolved);
            ts_sleep_msec(2000);
        }
    }
}

void updateFile_FromTimeValList( CallContext context, File* file,
                                                            List* times)
{
    if(file==NULL)
        return;

    if(times!=NULL)
    {
        file->atime=create_TimeTObj(((TimeVal*)get_List(times, 0))->tv_sec);
        file->mtime=create_TimeTObj(((TimeVal*)get_List(times, 1))->tv_sec);

        file->ctime_updated=false;
    }
    else
    {
        file->atime_updated=false;//false if we need updating, otherwise true
        file->mtime_updated=false;
        file->ctime_updated=false;
    }
}


/********************************************************************/
/**                       Helper Functions                         **/
/********************************************************************/

__XStatReturnType* create___XStatReturnType(CallContext context, IntT val)
{
    return create(&type___XStatReturnType, context, val);
}

void printKind(FileKind sw)
{
    switch(sw)
    {
        case BlockFile:
            VERBOSE("BlockFile\n");
        break;

        case CharacterFile:
            VERBOSE("CharacterFile\n");
        break;

        case FIFOFile:
            VERBOSE("FIFOFile\n");
        break;

        case RegularFile:
            VERBOSE("RegularFile\n");
        break;

        case DirectoryFile:
            VERBOSE("DirectoryFile\n");
        break;

        case SymbolicLinkFile:
            VERBOSE("SymbolicLinkFile\n");
        break;

        case Socket:
            VERBOSE("Socket\n");
        break;

        default:
            VERBOSE("UnknownFileKind\n");
    }
}

FileStatus* create_FileStatus(DevT dev,
                              InoT ino,
                              FileKind kind,
                              FilePermissions* permissions,
                              NLinkT nlink,
                              UidT uid,
                              GidT gid,
                              DevT rdev,
                              OffT size,
                              TimeT atime,
                              TimeT mtime,
                              TimeT ctime,
                              BlksizeT blksize,
                              BlkcntT blocks)
{
    return create(&type_FileStatus,
                    dev,
                    ino,
                    kind,
                    permissions,
                    nlink,
                    uid,
                    gid,
                    rdev,
                    size,
                    atime,
                    mtime,
                    ctime,
                    blksize,
                    blocks
                );
}

FileStatus* create_emptyFileStatus()
{
    FilePermissions* permissions= create_FilePermissions(NULL, NULL, NULL,
                                Unknown_Bool3, Unknown_Bool3, Unknown_Bool3);
    return create_FileStatus(
                    (DevT)-1,
                    (InoT)-1,
                    UnknownFileKind,
                    permissions,
                    (NLinkT)-1,
                    (UidT)-1,
                    (GidT)-1,
                    (DevT)-1,
                    (OffT)-1,
                    (TimeT)-1,
                    (TimeT)-1,
                    (TimeT)-1,
                    (BlksizeT)-1,
                    (BlkcntT)-1
                );
}
FileStatus* create_FileStatus_FromFile(CallContext context, File* file)
{
    FileStatus* res=create_emptyFileStatus();

    if(file==NULL)
        return NULL;

    if(file->dev!=NULL)
        res->dev=*(file->dev);
    if(file->ino!=NULL)
        res->ino=*(file->ino);
    if(file->kind!=UnknownFileKind)
        res->kind=file->kind;
    if(file->permissions!=NULL)
        res->permissions=clone(file->permissions);



    if(file->parents!=NULL)
        //number of elements in "parent" is not equal to nlink(<=)
        res->nlink=size_Set(file->parents);

    if(file->uid!=NULL)
        res->uid=*(file->uid);
    if(file->gid!=NULL)
        res->gid=*(file->gid);



    if(file->size!=NULL)
        res->size=*(file->size);
    if(file->atime!=NULL && file->atime_updated==true)
        res->atime=*(file->atime);
    if(file->ctime!=NULL && file->ctime_updated==true)
        res->ctime=*(file->ctime);
    if(file->mtime!=NULL && file->mtime_updated==true)
        res->mtime=*(file->mtime);

    if(POSIX_OPTION(context, XSI))
    {
        if(file->rdev!=NULL)
            res->rdev=*(file->rdev);
        if(file->blksize!=NULL)
            res->blksize=*(file->blksize);
        if(file->blocks!=NULL)
            res->blocks=*(file->blocks);
    }

    return res;
}

void updateFile_FromFileStatus(CallContext context, File* file,
                                                        FileStatus* status)
{
    if(file==NULL)
        return;

    if(file->kind==SymbolicLinkFile)
    {
        file->size=create_OffTObj(status->size);
        return;
    }

    if(file->dev==NULL)
        file->dev=create_DevTObj(status->dev);
    if(file->ino==NULL)
        file->ino=create_InoTObj(status->ino);
    if(file->kind==UnknownFileKind)
        file->kind=status->kind;
    if(file->permissions==NULL)
        file->permissions=clone(status->permissions);
    else
    {
        if(file->permissions->group==NULL && status->permissions->group!=NULL)
            file->permissions->group=clone(status->permissions->group);
        if(file->permissions->owner==NULL && status->permissions->owner!=NULL)
            file->permissions->owner=clone(status->permissions->owner);
        if(file->permissions->other==NULL && status->permissions->other!=NULL)
            file->permissions->other=clone(status->permissions->other);

        if(file->permissions->set_uid==Unknown_Bool3)
            file->permissions->set_uid=status->permissions->set_uid;
        if(file->permissions->set_gid==Unknown_Bool3)
            file->permissions->set_gid=status->permissions->set_gid;
        if(POSIX_OPTION(context, XSI))
            if(file->permissions->set_vtx==Unknown_Bool3)
                file->permissions->set_vtx=status->permissions->set_vtx;
    }
    if(file->uid==NULL)
        file->uid=create_UidTObj(status->uid);
    if(file->gid==NULL)
        file->gid=create_GidTObj(status->gid);
    if(file->nlink==NULL)
        file->nlink=create_NLinkTObj(status->nlink);

    if(file->size==NULL)
        file->size=create_OffTObj(status->size);


    //atime_updated== false means that file->atime needs updating...
    if(file->atime_updated==false)
    {
        file->atime=create_TimeTObj(status->atime);
        file->atime_updated=true;
    }
    if(file->ctime_updated==false)
    {
        file->ctime=create_TimeTObj(status->ctime);
        file->ctime_updated=true;
    }
    if(file->mtime_updated==false)
    {
        file->mtime=create_TimeTObj(status->mtime);
        file->mtime_updated=true;
    }

    if(POSIX_OPTION(context, XSI))
    {
        if(file->rdev==NULL)
            file->rdev=create_DevTObj(status->rdev);
        if(file->blksize==NULL)
            file->blksize=create_BlksizeTObj(status->blksize);
        if(file->blocks==NULL)
            file->blocks=create_BlkcntTObj(status->blocks);
    }
}
bool equals_Perms(CallContext context, FilePermissions* first, FilePermissions* second)
{
    if(!equals(first->group, second->group))
    {
        DUMP("Perm->group failed...$(obj)!=$(obj)\n", first->group, second->group);
        return false;
    }
    if(!equals(first->owner, second->owner))
    {
        DUMP("Perm->owner failed...$(obj)!=$(obj)\n", first->owner, second->owner);
        return false;
    }
    if(!equals(first->other, second->other))
    {
        DUMP("Perm->other failed...$(obj)!=$(obj)\n", first->other, second->other);
        return false;
    }
    if(first->set_gid!=second->set_gid)
    {
        return false;
    }
    if(first->set_uid!=second->set_uid)
    {
        return false;
    }

    if(POSIX_OPTION(context, XSI))
        if(first->set_vtx!=second->set_vtx)
        {
            return false;
        }
    return true;
}
bool checkFileStatusEquality(CallContext context, FileStatus* first,
                                                                File* file)
{
    FileStatus* second=create_FileStatus_FromFile(context, file);

    if(second==NULL)
        return true;

    if(file->kind==SymbolicLinkFile)
        return first->size==second->size;

    if(POSIX_OPTION(context, XSI))
    {
        if(first->rdev!=second->rdev)
        {
            VERBOSE("rdev failed...\n");
            return false;
        }
        if(first->blksize!=second->blksize)
        {
            VERBOSE("blksize failed...\n");
            return false;
        }
        if(first->blocks!=second->blocks)
        {
            VERBOSE("blocks failed...\n");
            return false;
        }
    }
    if(first->dev!=second->dev)
    {
        VERBOSE("dev failed...\n");
        return false;
    }
    if(first->ino!=second->ino)
    {
        VERBOSE("ino failed...\n");
        return false;
    }
    if(first->kind!=second->kind)
    {
        VERBOSE("kind failed...\n");
        return false;
    }
    if(!equals_Perms(context,  first->permissions, second->permissions))
    {
        VERBOSE("permissions failed...\n");
        return false;
    }
    if(first->uid!=second->uid)
    {
        VERBOSE("uid failed...\n");
        return false;
    }
    if(first->gid!=second->gid)
    {
        VERBOSE("gid failed...\n");
        return false;
    }
    //Must have stat.nlink>=size_Set(file->parent)
    if(first->nlink<second->nlink)
    {
        VERBOSE("nlink failed...\n");
        return false;
    }
    if( first->size!=second->size &&
        (first->kind==SymbolicLinkFile || first->kind==RegularFile
            ||
         (
            POSIX_OPTION(context, SHM) && first->kind==SharedMemoryObject
         || POSIX_OPTION(context, TYM) && first->kind==TypedMemoryObject
         )
        )
      )
    {
        VERBOSE("size failed...\n");
        return false;
    }

    if(first->atime!=*(file->atime) && file->atime_updated==true)
    {
        VERBOSE("atime failed...%d!=%d\n", first->atime, *(file->atime));
        return false;
    }
    if(first->ctime!=*(file->ctime) && file->ctime_updated==true)
    {
        VERBOSE("ctime failed...%d!=%d\n", first->ctime, *(file->ctime));
        return false;
    }
    if(first->mtime!=*(file->mtime) && file->mtime_updated==true)
    {
        VERBOSE("mtime failed...%d!=%d\n", first->mtime, *(file->mtime));
        return false;
    }

    return true;
}


Bool3 shall_isEACCES_xstat(CallContext context, FileSystem* fs, CString* path)
{
    Bool3 res = False_Bool3;

    if(!isAbsolute_Path(path))
        return Unknown_Bool3;

    path = getParentDir_Path(path);

    if(NULL==path)  // is child of root
        return Unknown_Bool3;

    res = or_Bool3(res, isNoPermOnPathComponents(context, fs, path,
                                        false, false, true)); // check search

    return res;
}
Bool3 shall_isEIO_xstat(CallContext context, CString* path, ErrorCode *errno)
{
    return *errno==SUT_EIO? Unknown_Bool3: False_Bool3;
}
Bool3 shall_isELOOP_xstat(CallContext context, FileSystem* fs, CString* path)
{
    Bool3 eloop;
    CString* resolved;
    File* search_result;

    resolved=resolvePath_Ext(context, fs, path, &eloop);
    VERBOSE("ELOOP==%s\n", (eloop==True_Bool3? "True_Bool3":
                    (eloop==False_Bool3? "False_Bool3": "Unknown_Bool3")));
    return eloop;
}
Bool3 shall_isENAMETOOLONG_xstat(CallContext context, CString* path)
{
    LongT path_max;
    LongT name_max;
    int i;
    List *path_components;

    path_max = getPathSystemConfigurationValue(context, path, SUT_PC_PATH_MAX);

    if(SC_VALUE_UNKNOWN==path_max)
        return Unknown_Bool3;

    if(length_CString(path)>path_max)
        return True_Bool3;

    name_max = getPathSystemConfigurationValue(context, path, SUT_PC_NAME_MAX);

    if(SC_VALUE_UNKNOWN==name_max)
        return Unknown_Bool3;

    path_components = split_Path(path);
    for(i=0; i<size_List(path_components); i++)
    {
        CString *path_comp = get_List(path_components, i);
        if(length_CString(path_comp) > name_max)
            return True_Bool3;
    }
    return False_Bool3;
}
Bool3 shall_isENOTDIR_xstat(CallContext context, FileSystem* fs, CString* path)
{
    FileSearchResult *res = getFile_FileSystem_Ext(fs, path);

    if(res->file==NULL)
    {
        if(res->last!=NULL && res->last->kind!=DirectoryFile)
            return True_Bool3;
        return Unknown_Bool3;
    }
    return False_Bool3;
}
Bool3 shall_isENOENT_xstat(CallContext context, FileSystem* fs, CString* path)
{
    if(NULL==path)
        return Unknown_Bool3;

    if(length_CString(path)==0)
        return True_Bool3;
    while(NULL!=path)
    {
        if(False_Bool3==doesFileExist_FileSystem(fs, path))
            return True_Bool3;
        path = getParentDir_Path(path);
    }
    return Unknown_Bool3;
}
Bool3 shall_isEOVERFLOW_xstat(CallContext context, FileSystem* fs,
                                                                CString* path)
{
    File* file;

    if(path==NULL)
        return Unknown_Bool3;

    file=getFile_FileSystem(fs, path);

    if(file==NULL)
        return Unknown_Bool3;

    if(     (file->ino!=NULL) && *(file->ino)>=(InoT)(4294967296l)
        ||  (file->size!=NULL) && *(file->size)>=(OffT)(2147483648l))
        return True_Bool3;

    if(POSIX_OPTION(context, XSI))
    if((file->blocks!=NULL) &&  *(file->blocks)>=(BlkcntT)(2147483648l))
        return True_Bool3;

    return Unknown_Bool3;
}


CString* updateAtimeInLinksInPath3(CallContext context, FileSystem* fs,
                                                                CString* path)
{
    Bool3 eloop;
    CString* parent;
    CString* basename;
    CString* slash=create_CString("/");
    CString* concated;
    File* search_result;

    if(path==NULL)
    {
        resetTimeFlags_FileSystem(fs);
        return NULL;
    }

    if(equals(path, slash))
        return NULL;

    parent=getParentDir_Path(path);
    basename=getBaseName_Path(path);

    if(parent==NULL || basename==NULL)
    {
        resetTimeFlags_FileSystem(fs);
        return NULL;
    }

    VERBOSE("In update...\n");

    if(!equals(parent, slash))
    {
        parent=updateAtimeInLinksInPath3(context, fs, parent);
        if(parent!=NULL)
            parent=clone(parent);
        else
        {
            resetTimeFlags_FileSystem(fs);
            return NULL;
        }
    }

    concated=concat_Path(parent, basename);
    search_result=getFile_FileSystem(fs, concated);

    if(search_result==NULL)
    {
        VERBOSE("Something strange: path component doesn't exist, but path is resolvable???\n");
    }
    else
    if(search_result->kind==SymbolicLinkFile)
    {
        DUMP("SymLink updated for path==$(obj)\n", concated);
        search_result->atime_updated=false;

        if(isAbsolute_Path(search_result->descriptor))
            concated=clone(search_result->descriptor);
        else
        {
            basename=clone(search_result->descriptor);

            if(basename==NULL)
            {
                //resetTimeFlags_FileSystem(getFileSystem(context));
                //Symlink isn't initialized yet
                resetTimeFlags_FileSystem(getFileSystem(context));
                return NULL;
            }

            concated=concat_Path(parent, basename);
        }

        if(!equals(concated, slash))
        {
            concated=updateAtimeInLinksInPath3(context, fs, concated);
            if(concated!=NULL)
                concated=clone(concated);
            else
            {
                resetTimeFlags_FileSystem(getFileSystem(context));
                return NULL;
            }
        }
        DUMP("Concated==$(obj)\n", concated);
    }

    return concated;
}
void on__XStat( CallContext context, CString* path,
                            FileStatus* buff, IntT ret)
{
    if(ret!=-1)
    {
        Bool3 eloop;
        FileSystem* fs=getFileSystem(context);
        CString* resolved=resolvePath_Ext(context, fs, path, &eloop);
        File* search_result;

        if(resolved==NULL)
        {
            resetTimeFlags_FileSystem(fs);
            return;
        }

        search_result=getFile_FileSystem(fs, resolved);

        if(search_result!=NULL)
        {
            VERBOSE("\nUpdating...%s\n\n", *resolved);
        }
        /*
         * The stat() function shall update any time-related fields (as
         * described in the Base Definitions volume of IEEE Std 1003.1-2001,
         * Section 4.7, File Times Update), before writing into the stat
         * structure.
         */
        IMPLEMENT_REQ("__xstat.stat.02");
        updateFile_FromFileStatus(context, search_result, buff);
    }
}

specification typedef struct __XStatReturnType
                        __XStatReturnType = {};

reaction __XStatReturnType* __xstat_return(void)
{
    post
    {
        return true;
    }
}


void on__XStatReturn(CallContext context, IntT arg)
{

}

Bool3 shall_isEOVERFLOW_xstat64(CallContext context, FileSystem* fs,
                                                                CString* path)
{
    return Unknown_Bool3;
}