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:
ios::app
ios::binary
ios::ate
ios::in
ios::out
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
Using Raii to Manage Resources from a C-Style API
Bring Window to Front -> Raise(),Show(),Activatewindow() Don't Work
How to Wrap Functions with the '--Wrap' Option Correctly
Stopping an Infinite Loop in C++ When Key Is Pressed
How to Turn on Multi-Cpu/Core C++ Compiles in the Visual Studio Ide (2008)
Move the String Out of a Std::Ostringstream
a Few Things About Division by Zero in C
Getting Actual File Name (With Proper Casing) on Windows
How to Convert a Tchar Array to Std::String
Is It Good Practice to Make Member Variables Protected
Non-Type Variadic Function Templates in C++11
Observer Design Pattern in C++
How to Call a Constructor on an Already Allocated Memory
Initializing Map of Maps with Initializer List in VS 2013
What Is the Overhead Cost of an Empty Vector
Extern "C" Linkage Inside C++ Namespace
Can Virtual Functions Be Constexpr
Good C++ Array Class for Dealing with Large Arrays of Data in a Fast and Memory Efficient Way