/*
* 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;
}