aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/pwdgrp.h
blob: c0466b44692031da3d3802d3535769af99cb95ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
/* pwdgrp.h

   Copyright 2001 Red Hat inc.

   Stuff common to pwd and grp handling.

This file is part of Cygwin.

This software is a copyrighted work licensed under the terms of the
Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
details. */

/* These functions are needed to allow searching and walking through
   the passwd and group lists */
extern struct passwd *internal_getpwsid (cygsid &);
extern struct passwd *internal_getpwnam (const char *, BOOL = FALSE);
extern struct passwd *internal_getpwuid (__uid32_t, BOOL = FALSE);
extern struct __group32 *internal_getgrsid (cygsid &);
extern struct __group32 *internal_getgrgid (__gid32_t gid, BOOL = FALSE);
extern struct __group32 *internal_getgrnam (const char *, BOOL = FALSE);
extern struct __group32 *internal_getgrent (int);
int internal_getgroups (int, __gid32_t *, cygsid * = NULL);

enum pwdgrp_state {
  uninitialized = 0,
  initializing,
  loaded
};

#define MAX_ETC_FILES 2
class etc
{
  static int curr_ix;
  static bool sawchange[MAX_ETC_FILES];
  static const char *fn[MAX_ETC_FILES];
  static FILETIME last_modified[MAX_ETC_FILES];
  static bool dir_changed (int);
  static int init (int, const char *);
  static bool file_changed (int);
  static void set_last_modified (int, FILETIME&);
  friend class pwdgrp;
};

class pwdgrp
{
  pwdgrp_state state;
  int pwd_ix;
  path_conv pc;
  char *buf;
  char *lptr, *eptr;

  char *gets ()
  {
    if (!buf)
      lptr = NULL;
    else if (!eptr)
      lptr = NULL;
    else
      {
	lptr = eptr;
	eptr = strchr (lptr, '\n');
	if (eptr)
	  {
	    if (eptr > lptr && *(eptr - 1) == '\r')
	      *(eptr - 1) = 0;
	    *eptr++ = '\0';
	  }
      }
    return lptr;
  }

public:
  pwdgrp () : state (uninitialized) {}
  BOOL isinitializing ()
    {
      if (state <= initializing)
	state = initializing;
      else if (etc::file_changed (pwd_ix - 1))
	state = initializing;
      return state == initializing;
    }
  void operator = (pwdgrp_state nstate) { state = nstate; }
  BOOL isuninitialized () const { return state == uninitialized; }

  bool load (const char *posix_fname, void (* add_line) (char *))
  {
    if (buf)
      free (buf);
    buf = lptr = eptr = NULL;

    pc.check (posix_fname);
    pwd_ix = etc::init (pwd_ix - 1, pc) + 1;

    paranoid_printf ("%s", posix_fname);

    bool res;
    if (pc.error || !pc.exists () || !pc.isdisk () || pc.isdir ())
      res = false;
    else
      {
	HANDLE fh = CreateFile (pc, GENERIC_READ, wincap.shared (), NULL,
				OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	if (fh == INVALID_HANDLE_VALUE)
	  res = false;
	else
	  {
	    DWORD size = GetFileSize (fh, NULL), read_bytes;
	    buf = (char *) malloc (size + 1);
	    if (!ReadFile (fh, buf, size, &read_bytes, NULL))
	      {
		if (buf)
		  free (buf);
		buf = NULL;
		fh = NULL;
		return false;
	      }
	    buf[read_bytes] = '\0';
	    eptr = buf;
	    CloseHandle (fh);
	    FILETIME ft;
	    if (GetFileTime (fh, NULL, NULL, &ft))
	      etc::set_last_modified (pwd_ix - 1, ft);
	    char *line;
	    while ((line = gets()) != NULL)
	      add_line (line);
	    res = true;
	  }
      }

    state = loaded;
    return res;
  }
};