Setting File Permissions When Opening a File with Ofstream

Setting file permissions when opening a file with ofstream

You cannot. The standard library must be platform agnostic, and permissions like 0600 are meaningless on Windows for example. If you want to use platform-specific features, you'll need to use platform-specific APIs. Of course, you can always call umask() before you open the file, but that's not part of the C++ standard library, it's part of the platform API.

Note: open() isn't part of the C standard library either. It's a platform API. The C standard library function to open a file is fopen().

How do I set file permissions when opening a file in C++?

There is not O_RDONLY mode for fstream. You should use one of:

  1. ios::app
  2. ios::binary
  3. ios::ate
  4. ios::in
  5. ios::out
  6. ios::trunc

Or their combinations (say ios::app | ios::binary). For your case you should use ios::in (maybe with ios::binary). Look at this for more details.

How to share file delete privilege when I opening a file by ifstream

Visual Studio's version of std::ifstream has a non-standard constructor and a non-standard open() overload that both have an extra optional _Prot parameter for specifying "file protection/sharing flags" (see _fsopen() for the list of available flags). However, delete sharing is not one of supported flags.

There is an alternative, though. Visual Studio's version of both std::ifstream and std::ofstream have non-standard constructors that accept a FILE* for the file access. You can wrap a HANDLE from CreateFile() into a FILE* using Microsoft's _open_osfhandle() and _fdopen() functions, for example (error handling removed for brevity):

Can I use CreateFile, but force the handle into a std::ofstream?

HANDLE file_handle = CreateFile(...,FILE_SHARE_DELETE,...);
int file_descriptor = _open_osfhandle((intptr_t)file_handle, _O_RDONLY);
FILE* file = _fdopen(file_descriptor, "r");
std::ifstream stream(file);
...
// Closes stream, file, file_descriptor, and file_handle.
stream.close();

If you need something more portable to non-Microsoft compilers, you will likely have to resort to writing a custom std::basic_streambuf class (or maybe derived from std::filebuf) to wrap your HANDLE, and then pass an object of that class to the std::basic_istream constructor directly.

What permissions does a file written with fstream have?

It depends on the umask.

ofstream (C++) does not create file (permission denied)

There is nothing wrong with the directory permissions nor the compiler issues. The problem is that Chrome has several renderer processes and these processes are sand-boxed (as opposed to the browser process). So, they do not have permission to write a file.

To overcome this problem use --no-sandbox flag to give the file access permission to the renderer processes. Build chrome and then run it from console using the following code (for win):

chrome.exe --no-sandbox

c++ ofstream doesn't modify files. Even the tutorial examples

@timebender

I tried following code using g++.exe(cygwin windows)

    #include <string.h>
#include <sys/errno.h>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
// Create and open a text file
ofstream MyFile("filename.txt", ios::app|ios::out);
if ( MyFile.is_open() )
{
cout << "is_open pass\n";
// Write to the file
MyFile << "Files can be tricky, but it is fun enough!\n";
// Close the file
MyFile.close();
cout << "closed file\n";
}
else
{
cout << "ofstream filename.txt failed\n";
cout << strerror(errno) << "\n";
}
return 0;
}
$ g++ 73174678.cpp -o ./a.out;a.out
$ ./a.out
is_open pass
closed file
$ cat "filename.txt"
Files can be tricky, but it is fun enough!
$ g++.exe 73174678.cpp -o ./a.exe;./a.exe
$ ./a.exe
is_open pass
closed file
I tried your updated program.<BR>
#include <string.h>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ofstream ofs;
system( "echo Before;cat filename.txt");
ofs.open("filename.txt", std::ofstream::out | std::ofstream::trunc);
ofs<<"Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with Ofstream";
ofs.close();
system( "echo After;cat filename.txt");
return 0;
}
Sample output:
$ a.exe
Before
Files can be tricky, but it is fun enough!
After
Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with Ofstream$ ./a.exe
Before
Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with OfstreamAfter
Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with Ofstream$ a.exe
Before
Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with OfstreamAfter
Setting File Permissions When Opening a File with OfstreamSetting File Permissions When Opening a File with Ofstream
Hence need your expected output here ?
I tried compiling your program using g++.exe at my local host.

std::ofstream does not show error when permission denied C++

I'd say your code works and the write operation is actually done, but for the sake of it, add a check after the write too:

outfile << err_line << endl;
if(outfile.fail()) cout << "Error3\n";
else cout<<"OK";

On my system, I'll get your Error 1 ... can't open file if the file isn't opened for writing successfully.

Edit: Or are you running Windows with Compatibility Files virtualization still active? If so, the file will probably be in the Virtual Store, not in the real C:\err.txt path.

Example: C:\Users\username\AppData\Local\VirtualStore

If you find it there, you may find a lot of other stuff in there too. At least I did years ago when I had a similar problem. I decided to manually move (with admin rights) the few important files that some of my older programs had put there and then turn Virtual Store off. I can't find a good and simple official Microsoft link for how to turn off file and registry virtualization right now so perhaps this will do:

RegEdit:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\
Create a DWORD Key with the name EnableVirtualization and give it the value 0. If the key is already there, but set to something else than zero, change it.

There's more here:
UAC Group Policy Settings and Registry Key Settings

How to set file permissions (cross platform) in C++?

Ironically, I have just run into this very same need earlier today.

In my case, the answer came down to what level of permission granularity I need on Windows, versus Linux. In my case, I only care about User, Group, and Other permission on Linux. On Windows, the basic Read/Write All permission leftover from DOS is good enough for me, i.e. I don't need to deal with ACL on Windows.

Generally speaking, Windows has two privilege models: the basic DOS model and the newer access control model. Under the DOS model there is one type of privilege: write privilege. All files can be read, so there is no way to turn off read permission (because it doesn't exist). There is also no concept of execute permission. If a file can be read (answer is yes) and it is binary, then it can be executed; otherwise it can't.

The basic DOS model is sufficient for most Windows environments, i.e. environments where the system is used by a single user in a physical location that can be considered relatively secure. The access control model is more complex by several orders of magnitude.

The access control model uses access control lists (ACL) to grant privileges. Privileges can only be granted by a process with the necessary privileges. This model not only allows the control of User, Group, and Other with Read, Write, and Execute permission, but it also allows control of files over the network and between Windows domains. (You can also get this level of insanity on Unix systems with PAM.)

Note: The Access Control model is only available on NTFS partitions, if you are using FAT partitions you are SOL.

Using ACL is a big pain in the ass. It is not a trivial undertaking and it will require you to learn not just ACL but also all about Security Descriptors, Access Tokens, and a whole lot of other advanced Windows security concepts.

Fortunately for me, for my current needs, I don't need the true security that the access control model provides. I can get by with basically pretending to set permissions on Windows, as long as I really set permissions on Linux.

Windows supports what they call an "ISO C++ conformant" version of chmod(2). This API is called _chmod, and it is similar to chmod(2), but more limited and not type or name compatible (of course). Windows also has a deprecated chmod, so you can't simply add chmod to Windows and use the straight chmod(2) on Linux.

I wrote the following:

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

#ifdef _WIN32
# include <io.h>

typedef int mode_t;

/// @Note If STRICT_UGO_PERMISSIONS is not defined, then setting Read for any
/// of User, Group, or Other will set Read for User and setting Write
/// will set Write for User. Otherwise, Read and Write for Group and
/// Other are ignored.
///
/// @Note For the POSIX modes that do not have a Windows equivalent, the modes
/// defined here use the POSIX values left shifted 16 bits.

static const mode_t S_ISUID = 0x08000000; ///< does nothing
static const mode_t S_ISGID = 0x04000000; ///< does nothing
static const mode_t S_ISVTX = 0x02000000; ///< does nothing
static const mode_t S_IRUSR = mode_t(_S_IREAD); ///< read by user
static const mode_t S_IWUSR = mode_t(_S_IWRITE); ///< write by user
static const mode_t S_IXUSR = 0x00400000; ///< does nothing
# ifndef STRICT_UGO_PERMISSIONS
static const mode_t S_IRGRP = mode_t(_S_IREAD); ///< read by *USER*
static const mode_t S_IWGRP = mode_t(_S_IWRITE); ///< write by *USER*
static const mode_t S_IXGRP = 0x00080000; ///< does nothing
static const mode_t S_IROTH = mode_t(_S_IREAD); ///< read by *USER*
static const mode_t S_IWOTH = mode_t(_S_IWRITE); ///< write by *USER*
static const mode_t S_IXOTH = 0x00010000; ///< does nothing
# else
static const mode_t S_IRGRP = 0x00200000; ///< does nothing
static const mode_t S_IWGRP = 0x00100000; ///< does nothing
static const mode_t S_IXGRP = 0x00080000; ///< does nothing
static const mode_t S_IROTH = 0x00040000; ///< does nothing
static const mode_t S_IWOTH = 0x00020000; ///< does nothing
static const mode_t S_IXOTH = 0x00010000; ///< does nothing
# endif
static const mode_t MS_MODE_MASK = 0x0000ffff; ///< low word

static inline int my_chmod(const char * path, mode_t mode)
{
int result = _chmod(path, (mode & MS_MODE_MASK));

if (result != 0)
{
result = errno;
}

return (result);
}
#else
static inline int my_chmod(const char * path, mode_t mode)
{
int result = chmod(path, mode);

if (result != 0)
{
result = errno;
}

return (result);
}
#endif

It's important to remember that my solution only provides DOS type security. This is also known as no security, but it is the amount of security that most apps give you on Windows.

Also, under my solution, if you don't define STRICT_UGO_PERMISSIONS, when you give a permission to group or other (or remove it for that matter), you are really changing the owner. If you didn't want to do that, but you still didn't need full Windows ACL permissions, just define STRICT_UGO_PERMISSIONS.



Related Topics



Leave a reply



Submit