3 * This is a reimplementation of the BeOS R5 query-based multi-user system.
4 * (c) 2005, François Revol.
5 * provided under the MIT licence
8 //#ifdef REAL_MULTIUSER
21 #include <TypeConstants.h>
23 #include <errno_private.h>
27 * Users are stored in an fs node (not necessarily a regular file,
28 * that could be a dir, even the user's home dir,
29 * though we should be careful as they are owned by users.
33 #define GR_MAX_NAME 32
35 #define PW_MAX_NAME 32
36 #define PW_MAX_DIR B_PATH_NAME_LENGTH
37 #define PW_MAX_GECOS 128
38 #define PW_MAX_PASSWD 32
39 #define PW_MAX_SHELL B_PATH_NAME_LENGTH
41 /* should be more than enough :) */
42 #define GRBUFFSZ (GR_MAX_NAME + 2)
43 #define PWBUFFSZ (PW_MAX_NAME + PW_MAX_DIR + PW_MAX_GECOS + PW_MAX_PASSWD + PW_MAX_SHELL + 4)
46 /* attribute names we use to store groups & users. */
47 /* pets nm & strings */
49 static const char *B_GR_GID
= "sys:group:gid";
50 static const char *B_GR_NAME
= "sys:group:name";
51 //static const char *B_GR_PASSWD = "sys:group:passwd";
53 static const char *B_PW_DIR
= "sys:user:dir";
54 static const char *B_PW_GECOS
= "sys:user:fullname";
55 static const char *B_PW_GID
= "sys:user:gid";
56 static const char *B_PW_NAME
= "sys:user:name";
57 static const char *B_PW_PASSWD
= "sys:user:passwd";
58 static const char *B_PW_SHELL
= "sys:user:shell";
59 static const char *B_PW_UID
= "sys:user:uid";
62 static const char *Q_GR_ALL
= "sys:group:gid>-1";
63 static const char *QT_GR_GID
= "sys:group:gid==%d";
64 static const char *QT_GR_NAM
= "sys:group:name==\"%s\"";
65 static const char *Q_PW_ALL
= "sys:user:uid>-1";
66 static const char *QT_PW_UID
= "sys:user:uid==%d";
67 static const char *QT_PW_NAM
= "sys:user:name==\"%s\"";
69 extern void __init_pwd_stuff(void);
70 extern void __fini_pwd_stuff(void);
72 static char *default_gr_members
[] = { /*"baron",*/ NULL
};
74 static dev_t boot_device
;
78 static int32 pw_tls_id
;
80 typedef struct pw_tls
{
87 char grfile
[B_PATH_NAME_LENGTH
+1]; /* current group's cached file path */
88 char pwfile
[B_PATH_NAME_LENGTH
+1]; /* current user's cached file path */
91 char grbuff
[GRBUFFSZ
]; /* XXX: merge with pwbuff ? */
94 char pwbuff
[PWBUFFSZ
];
97 struct pw_tls
*get_pw_tls(void)
99 pw_tls_t
*p
= (pw_tls_t
*)tls_get(pw_tls_id
);
100 PRINT(("%s()\n", __FUNCTION__
));
103 p
= (pw_tls_t
*)malloc(sizeof(pw_tls_t
));
106 memset(p
, 0, sizeof(pw_tls_t
));
107 p
->grent_query
= NULL
;
108 p
->pwent_query
= NULL
;
109 tls_set(pw_tls_id
, p
);
114 /* fill the path from the dirent and open() */
115 int dentopen(struct dirent
*dent
, char *path
)
118 PRINT(("%s({%ld, %Ld, %ld, %Ld, %s}, )\n", __FUNCTION__
, dent
->d_pdev
, dent
->d_pino
, dent
->d_dev
, dent
->d_ino
, dent
->d_name
));
119 dent
->d_dev
= boot_device
;
120 err
= get_path_for_dirent(dent
, path
, B_PATH_NAME_LENGTH
);
121 if ((err
< 0) || (path
[0] != '/')) {
125 PRINT(("%s: open(%s)\n", __FUNCTION__
, path
));
126 return open(path
, O_RDONLY
);
131 int fill_grent_default(struct group
*gbuf
)
133 PRINT(("%s()\n", __FUNCTION__
));
135 gbuf
->gr_name
= gbuf
->gr_gid
?"users":"wheel";
136 gbuf
->gr_passwd
= "";
137 gbuf
->gr_mem
= default_gr_members
;
141 int fill_grent_from_fd(int fd
, struct group
*gbuf
, char *buf
, size_t buflen
)
146 len
= fs_read_attr(fd
, B_GR_GID
, B_INT32_TYPE
, 0LL, &gbuf
->gr_gid
, sizeof(gid_t
));
148 return fill_grent_default(gbuf
);
149 PRINT(("%s: got gid\n", __FUNCTION__
));
150 gbuf
->gr_passwd
= "";
151 gbuf
->gr_mem
= default_gr_members
;
153 if (left
< GR_MAX_NAME
+ 1)
155 len
= fs_read_attr(fd
, B_GR_NAME
, B_STRING_TYPE
, 0LL, buf
, GR_MAX_NAME
);
157 return fill_grent_default(gbuf
);
162 PRINT(("%s: got name\n", __FUNCTION__
));
170 PRINT(("%s()\n", __FUNCTION__
));
171 if (p
->grent_query
) /* clumsy apps */
172 fs_close_query(p
->grent_query
);
173 p
->grent_query
= fs_open_query(boot_device
, Q_GR_ALL
, 0);
174 PRINT(("pwq: %p\n", p
->grent_query
));
181 PRINT(("%s()\n", __FUNCTION__
));
185 fs_close_query(p
->grent_query
);
186 p
->grent_query
= NULL
;
191 /* this conforms to the linux getgrent_r (there are several protos for that one... crap) */
192 /* note the FILE * based version is not supported as it makes no sense here */
193 int getgrent_r(struct group
*gbuf
, char *buf
, size_t buflen
, struct group
**gbufp
)
199 PRINT(("%s()\n", __FUNCTION__
));
203 PRINT(("getgrent_r: grq = %p, idx = %d\n", p
->grent_query
, p
->gridx
));
205 setgrent(); /* y0u clumsy app! */
207 return EIO
; /* something happened... */
209 dent
= fs_read_query(p
->grent_query
);
212 /* found nothing on first iteration ? */
214 if (fill_grent_default(gbuf
) < 0)
221 fd
= dentopen(dent
, p
->grfile
);
223 return errno
?errno
:-1;
224 err
= fill_grent_from_fd(fd
, gbuf
, buf
, buflen
);
225 PRINT(("%s: fill_grent_from_fd = %d\n", __FUNCTION__
, err
));
234 struct group
*getgrent(void)
239 PRINT(("%s()\n", __FUNCTION__
));
242 /* we are really bork */
246 err
= getgrent_r(&p
->grent
, p
->grbuff
, GRBUFFSZ
, &ent
);
253 PRINT(("getgrent(); returning entry for %s\n", ent
->gr_name
));
258 struct group
*getgrgid(gid_t gid
)
266 PRINT(("%s()\n", __FUNCTION__
));
269 /* we are really bork */
275 sprintf(p
->grfile
, QT_GR_GID
, gid
);
276 query
= fs_open_query(boot_device
, p
->grfile
, 0);
277 PRINT(("q: %p\n", query
));
281 dent
= fs_read_query(query
);
283 fs_close_query(query
);
286 fd
= dentopen(dent
, p
->grfile
);
287 fs_close_query(query
);
290 err
= fill_grent_from_fd(fd
, &p
->grent
, p
->grbuff
, GRBUFFSZ
);
291 PRINT(("%s: fill_grent_from_fd = %d\n", __FUNCTION__
, err
));
300 struct group
*getgrnam(const char *name
)
308 PRINT(("%s()\n", __FUNCTION__
));
311 /* we are really bork */
316 if (!name
|| strlen(name
) > GR_MAX_NAME
) {
321 sprintf(p
->grfile
, QT_GR_NAM
, name
);
322 query
= fs_open_query(boot_device
, p
->grfile
, 0);
323 PRINT(("q: %p\n", query
));
327 dent
= fs_read_query(query
);
329 fs_close_query(query
);
332 fd
= dentopen(dent
, p
->grfile
);
333 fs_close_query(query
);
336 err
= fill_grent_from_fd(fd
, &p
->grent
, p
->grbuff
, GRBUFFSZ
);
337 PRINT(("%s: fill_grent_from_fd = %d\n", __FUNCTION__
, err
));
348 int fill_pwent_default(struct passwd
*pwbuf
)
350 PRINT(("%s()\n", __FUNCTION__
));
351 return ENOENT
; /* hmm no we don't exist! */
352 pwbuf
->pw_gid
= 1000;
353 pwbuf
->pw_uid
= 1000;
354 pwbuf
->pw_name
= "baron";
355 pwbuf
->pw_passwd
= "*";
356 pwbuf
->pw_dir
= "/var/tmp";
357 pwbuf
->pw_shell
= "/bin/false";
358 pwbuf
->pw_gecos
= "Unknown User";
362 int fill_pwent_from_fd(int fd
, struct passwd
*pwbuf
, char *buf
, size_t buflen
)
366 PRINT(("%s()\n", __FUNCTION__
));
371 len
= fs_read_attr(fd
, B_PW_GID
, B_INT32_TYPE
, 0LL, &pwbuf
->pw_gid
, sizeof(gid_t
));
373 return fill_pwent_default(pwbuf
);
374 PRINT(("%s: got gid\n", __FUNCTION__
));
376 len
= fs_read_attr(fd
, B_PW_UID
, B_INT32_TYPE
, 0LL, &pwbuf
->pw_uid
, sizeof(uid_t
));
378 return fill_pwent_default(pwbuf
);
379 PRINT(("%s: got uid\n", __FUNCTION__
));
381 if (left
< PW_MAX_NAME
+ 1)
383 len
= fs_read_attr(fd
, B_PW_NAME
, B_STRING_TYPE
, 0LL, buf
, PW_MAX_NAME
);
385 return fill_pwent_default(pwbuf
);
386 pwbuf
->pw_name
= buf
;
390 PRINT(("%s: got name\n", __FUNCTION__
));
392 if (left
< PW_MAX_DIR
+ 1)
394 len
= fs_read_attr(fd
, B_PW_DIR
, B_STRING_TYPE
, 0LL, buf
, PW_MAX_DIR
);
396 return fill_pwent_default(pwbuf
);
401 PRINT(("%s: got dir\n", __FUNCTION__
));
403 if (left
< PW_MAX_SHELL
+ 1)
405 len
= fs_read_attr(fd
, B_PW_SHELL
, B_STRING_TYPE
, 0LL, buf
, PW_MAX_SHELL
);
407 return fill_pwent_default(pwbuf
);
408 pwbuf
->pw_shell
= buf
;
412 PRINT(("%s: got shell\n", __FUNCTION__
));
414 if (left
< PW_MAX_GECOS
+ 1)
416 len
= fs_read_attr(fd
, B_PW_GECOS
, B_STRING_TYPE
, 0LL, buf
, PW_MAX_GECOS
);
418 return fill_pwent_default(pwbuf
);
419 pwbuf
->pw_gecos
= buf
;
423 PRINT(("%s: got gecos\n", __FUNCTION__
));
425 if (left
< PW_MAX_PASSWD
+ 1)
427 len
= fs_read_attr(fd
, B_PW_PASSWD
, B_STRING_TYPE
, 0LL, buf
, PW_MAX_PASSWD
);
429 buf
[0] = '*'; /* no pass set */
432 pwbuf
->pw_passwd
= buf
;
436 PRINT(("%s: got passwd\n", __FUNCTION__
));
447 PRINT(("%s()\n", __FUNCTION__
));
448 if (p
->pwent_query
) /* clumsy apps */
449 fs_close_query(p
->pwent_query
);
450 p
->pwent_query
= fs_open_query(boot_device
, Q_PW_ALL
, 0);
451 PRINT(("pwq: %p\n", p
->pwent_query
));
458 PRINT(("%s()\n", __FUNCTION__
));
462 fs_close_query(p
->pwent_query
);
463 p
->pwent_query
= NULL
;
468 /* this conforms to the linux getpwent_r (there are several protos for that one... crap) */
469 /* note the FILE * based version is not supported as it makes no sense here */
470 int getpwent_r(struct passwd
*pwbuf
, char *buf
, size_t buflen
, struct passwd
**pwbufp
)
476 PRINT(("%s()\n", __FUNCTION__
));
480 PRINT(("getpwent_r: pwq = %p, idx = %d\n", p
->pwent_query
, p
->pwidx
));
482 setpwent(); /* y0u clumsy app! */
484 return EIO
; /* something happened... */
486 dent
= fs_read_query(p
->pwent_query
);
489 /* found nothing on first iteration ? */
491 if (fill_pwent_default(pwbuf
) < 0)
498 fd
= dentopen(dent
, p
->pwfile
);
500 return errno
?errno
:-1;
501 err
= fill_pwent_from_fd(fd
, pwbuf
, buf
, buflen
);
502 PRINT(("%s: fill_pwent_from_fd = %d\n", __FUNCTION__
, err
));
511 struct passwd
*getpwent(void)
516 PRINT(("%s()\n", __FUNCTION__
));
519 /* we are really bork */
523 err
= getpwent_r(&p
->pwent
, p
->pwbuff
, PWBUFFSZ
, &ent
);
530 PRINT(("getpwent(); returning entry for %s\n", ent
->pw_name
));
535 struct passwd
*getpwuid(uid_t uid
)
543 PRINT(("%s(%d)\n", __FUNCTION__
, uid
));
546 /* we are really bork */
552 sprintf(p
->pwfile
, QT_PW_UID
, uid
);
553 PRINT(("%s: query(%s)\n", __FUNCTION__
, p
->pwfile
));
554 query
= fs_open_query(boot_device
, p
->pwfile
, 0);
555 PRINT(("q: %p\n", query
));
559 dent
= fs_read_query(query
);
561 fs_close_query(query
);
564 fd
= dentopen(dent
, p
->pwfile
);
565 fs_close_query(query
);
568 err
= fill_pwent_from_fd(fd
, &p
->pwent
, p
->pwbuff
, PWBUFFSZ
);
569 PRINT(("%s: fill_pwent_from_fd = %d\n", __FUNCTION__
, err
));
578 struct passwd
*getpwnam(const char *name
)
586 PRINT(("%s(%s)\n", __FUNCTION__
, name
));
589 /* we are really bork */
594 if (!name
|| strlen(name
) > PW_MAX_NAME
) {
599 sprintf(p
->pwfile
, QT_PW_NAM
, name
);
600 PRINT(("%s: query(%s)\n", __FUNCTION__
, p
->pwfile
));
601 query
= fs_open_query(boot_device
, p
->pwfile
, 0);
602 PRINT(("q: %p\n", query
));
606 dent
= fs_read_query(query
);
608 fs_close_query(query
);
611 PRINT(("%s: dentopen()\n", __FUNCTION__
));
612 fd
= dentopen(dent
, p
->pwfile
);
613 fs_close_query(query
);
616 err
= fill_pwent_from_fd(fd
, &p
->pwent
, p
->pwbuff
, PWBUFFSZ
);
617 PRINT(("%s: fill_pwent_from_fd = %d\n", __FUNCTION__
, err
));
625 void __init_pwd_backend(void)
627 /* dev_t for the boot volume */
628 boot_device
= dev_for_path("/boot");
629 /* get us an id for holding thread-specific data */
630 pw_tls_id
= tls_allocate();
634 void __fini_pwd_backend(void)
640 #endif /* REAL_MULTIUSER */