4

Following my previous question I'm now trying to execute a batch file trough NSIS code in order to successfully setup the postgres installation after it is being unzipped. The batch file contains command for initializing the database but it fails because of permission restrictions. I am on a Win7 x64 PC. My user account is the administrator and I start the Setup.exe with Run as adminitrator option. This is the error I get:

C:\Program Files (x86)\Poker Assistant>cd "pgsql\bin" C:\Program Files (x86)\Poker Assistant\pgsql\bin>initdb -U postgres -A password --pwfile "pwd.txt" -E utf8 -D "..\data" The files belonging to this database system will be owned by user "Mandarinite".

This user must also own the server process.

The database cluster will be initialized with locale "Bulgarian_Bulgaria.1251". initdb: could not find suitable text search configuration for locale "Bulgarian_ Bulgaria.1251" The default text search configuration will be set to "simple".

Data page checksums are disabled.

creating directory ../data ... initdb: could not create directory "../data": Permission denied

EDIT: After tinkering little more with the installer I got to the root of the problem. I cannot in any way execute the following command when the installation is in the Program Files folder:

initdb -U postgres -A password --pwfile "pwd.txt" -E utf8 -D "..\data"

I tried from .bat file. I tried from .cmd file. I tried manually from Command Prompt. I tried start as Administrator. All attempts resulted in the Permission denied error

EDIT2: I did not find any way to fix the problem so I made a workaround. Now I distribute the postgres with its data directory already initialized. Then I only need to create the service and start it.

Community
  • 1
  • 1
mandarin
  • 1,316
  • 1
  • 15
  • 27
  • Are you sure what your current active directory is? Is it possible that the relative folder reference `..\data` points to a wrong place? – MC ND Jun 19 '15 at 11:15
  • Thanks for linking to the prior question for context. Also, it's *hilarious* that I used Poker Tracker as an example in the prior answer, you said that your users were "used to other apps that bundle PostgreSQL" and your app is called *Poker Assistant*. – Craig Ringer Jun 19 '15 at 13:33
  • @CraigRinger Hilarious indeed. btw to both you and the mr mandarin, how bout the log directory? i found out that it cannot use relative path. – Fandi Susanto Jul 22 '15 at 08:33
  • 1
    @FandiSusanto A relative path should be fine. It seems more likely to be a permissions issue as indicated in the error. Personally I recommend creating the datadir in `%PROGRAMDATA%\MyApp\postgres\data` or similar instead, since that's where Microsoft says data shared for all users of an app on a machine should go. `%PROGRAMDATA%` is an environment variable. – Craig Ringer Jul 22 '15 at 10:41

1 Answers1

3

I just realised what the issue here is.

If you run postgres as Administrator, it uses a special Windows API call to drop permissions (acquire a restricted token), so that it runs without full Administrator rights for security. See PostgreSQL utilities and restricted tokens on windows.

I suspect that what's happening here is that initdb isn't creating the target data directory and setting its permissions before doing that, so it drops permissions and then doesn't have the permissions to create the data directory.

To work around it, simply md ..\data to create the empty directory and then use icacls.exe to grant appropriate permissions before you try to initdb. Or, even better, store it in a more appropriate place like %PROGRAMDATA%\MyApp\pgdata or whatever; application data should not go in %PROGRAMFILES%.

Craig Ringer
  • 307,061
  • 76
  • 688
  • 778
  • Thank you for the explanation. I was able to execute initdb successfully by using the icacls.exe. But i also think that you are right about the %PROGRAMDATA% directory. But i since i need to delete the data on uninstall, i can't use %PROGRAMDATA% there. I used $APPDATA instead. It ends up at C:/Users/somebody/AppData/Roaming at Windows 8.1 OS. Somebody also said that their $APPDATA goes to C:/ProgramData. – Fandi Susanto Jul 25 '15 at 08:17
  • 1
    Don't use `%APPDATA%`! If the user has roaming profile redirection enabled that'll be a CIFS volume, and might have delayed writes and/or sync enabled. This will lead to performance problems at best, and can easily create massive data corruption. If you *must* make it per-user, use `%LOCALAPPDATA%`. – Craig Ringer Jul 25 '15 at 08:18
  • No... i really wish to install to ProgramData folder. But i dont know the right NSIS variable for that. There are only $APPDATA and $LOCALAPPDATA in NSIS. There is no variable for the ProgramData folder. Should i literally type C:/ProgramData on the installer script? But i think that would be a problem for users with dual boot system. – Fandi Susanto Aug 04 '15 at 07:24
  • @FandiSusanto http://nsis.sourceforge.net/Get_the_Special_Folders_Directories_(System_plugin), http://stackoverflow.com/q/22470967/398670, – Craig Ringer Aug 04 '15 at 07:38
  • I found that site back then but i failed to found "ProgramData" there. But just now i tried "SetShellVarContext all" in NSIS and it works. I got it from: http://forums.winamp.com/showthread.php?t=345537 – Fandi Susanto Aug 04 '15 at 07:53
  • @FandiSusanto: could you please tell me which syntax did you used? becaise I used this one and getting invalid paramter error String[] icaclsCommandLine = {"icacls", FwPath.root() + FwPath.VAR_POSTGRESQL, "/inheritance:r /grant:r BUILTIN\\Users:(OI)(CI)F"}; – prashantitis Nov 25 '15 at 16:59
  • I havent tried using icacls in NSIS. Last time, I execute initdb to the Program Data folder. No privileges issues there. I'm not successful with `%PROGRAMDATA%` variable in NSIS. So i used `SetShellVarContext all` plus NSIS variable `$APPDATA`. With SetShellVarContext All, $APPDATA points to Program Data. Without it, $APPDATA points to Roaming folder as i said above. Dont forget to also put SetShellVarContext All in the uninstall section. – Fandi Susanto Nov 27 '15 at 04:03