* cmake/ConfigureChecks.cmake,cmake/config.h.cmake: added check for HAVE_ERRNO_H
[platform/upstream/dbus.git] / dbus / dbus-sysdeps-util-win.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-sysdeps-util.c Would be in dbus-sysdeps.c, but not used in libdbus
3  * 
4  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat, Inc.
5  * Copyright (C) 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 /* #define ENABLE_DBUSGROUPINFO */
26
27 #ifdef ENABLE_DBUSGROUPINFO
28 typedef struct {
29     int gid;
30     char *groupname;
31 } DBusGroupInfo;
32 #endif
33
34 #undef open
35
36 #define STRSAFE_NO_DEPRECATE
37
38 #include "dbus-sysdeps.h"
39 #include "dbus-internals.h"
40 #include "dbus-protocol.h"
41 #include "dbus-string.h"
42 #include "dbus-sysdeps.h"
43 #include "dbus-sysdeps-win.h"
44 #include "dbus-memory.h"
45
46 #include <io.h>
47 #include <sys/stat.h>
48 #include <aclapi.h>
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <fcntl.h>
53 #include <errno.h>
54
55 #ifdef __MINGW32__
56 /* save string functions version
57    using DBusString needs to much time because of uncommon api 
58 */ 
59 #define errno_t int
60
61 errno_t strcat_s(char *dest, int size, char *src) 
62 {
63   _dbus_assert(strlen(dest) + strlen(src) +1 <= size);
64   strcat(dest,src);
65   return 0;
66 }
67
68 errno_t strcpy_s(char *dest, int size, char *src)
69 {
70   _dbus_assert(strlen(src) +1 <= size);
71   strcpy(dest,src);  
72   return 0;
73 }
74 #endif
75
76 /**
77  * Does the chdir, fork, setsid, etc. to become a daemon process.
78  *
79  * @param pidfile #NULL, or pidfile to create
80  * @param print_pid_fd file descriptor to print daemon's pid to, or -1 for none
81  * @param error return location for errors
82  * @returns #FALSE on failure
83  */
84 dbus_bool_t
85 _dbus_become_daemon (const DBusString *pidfile,
86                      DBusPipe         *print_pid_pipe,
87                      DBusError        *error)
88 {
89   return TRUE;
90 }
91
92 /**
93  * Creates a file containing the process ID.
94  *
95  * @param filename the filename to write to
96  * @param pid our process ID
97  * @param error return location for errors
98  * @returns #FALSE on failure
99  */
100 dbus_bool_t
101 _dbus_write_pid_file (const DBusString *filename,
102                       unsigned long     pid,
103                       DBusError        *error)
104 {
105   const char *cfilename;
106   DBusFile file;
107   FILE *f;
108
109   cfilename = _dbus_string_get_const_data (filename);
110
111   if (!_dbus_file_open(&file, cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644))
112     {
113       dbus_set_error (error, _dbus_error_from_errno (errno),
114                       "Failed to open \"%s\": %s", cfilename,
115                       _dbus_strerror (errno));
116       return FALSE;
117     }
118
119   if ((f = fdopen (file.FDATA, "w")) == NULL)
120     {
121       dbus_set_error (error, _dbus_error_from_errno (errno),
122                       "Failed to fdopen fd %d: %s", file.FDATA, _dbus_strerror (errno));
123       _dbus_file_close (&file, NULL);
124       return FALSE;
125     }
126
127   if (fprintf (f, "%lu\n", pid) < 0)
128     {
129       dbus_set_error (error, _dbus_error_from_errno (errno),
130                       "Failed to write to \"%s\": %s", cfilename,
131                       _dbus_strerror (errno));
132
133       fclose (f);
134       return FALSE;
135     }
136
137   if (fclose (f) == EOF)
138     {
139       dbus_set_error (error, _dbus_error_from_errno (errno),
140                       "Failed to close \"%s\": %s", cfilename,
141                       _dbus_strerror (errno));
142       return FALSE;
143     }
144
145   return TRUE;
146 }
147
148 /**
149  * Verify that after the fork we can successfully change to this user.
150  *
151  * @param user the username given in the daemon configuration
152  * @returns #TRUE if username is valid
153  */
154 dbus_bool_t
155 _dbus_verify_daemon_user (const char *user)
156 {
157   return TRUE;
158 }
159
160 /**
161  * Changes the user and group the bus is running as.
162  *
163  * @param user the user to become
164  * @param error return location for errors
165  * @returns #FALSE on failure
166  */
167 dbus_bool_t
168 _dbus_change_to_daemon_user  (const char    *user,
169                               DBusError     *error)
170 {
171   return TRUE;
172 }
173
174 /**
175  * Changes the user and group the bus is running as.
176  *
177  * @param uid the new user ID
178  * @param gid the new group ID
179  * @param error return location for errors
180  * @returns #FALSE on failure
181  */
182 dbus_bool_t
183 _dbus_change_identity  (dbus_uid_t     uid,
184                         dbus_gid_t     gid,
185                         DBusError     *error)
186 {
187   return TRUE;
188 }
189
190 /** Checks if user is at the console
191 *
192 * @param username user to check
193 * @param error return location for errors
194 * @returns #TRUE is the user is at the consolei and there are no errors
195 */
196 dbus_bool_t
197 _dbus_user_at_console(const char *username,
198                       DBusError  *error)
199 {
200 #ifdef DBUS_WINCE
201         return TRUE;
202 #else
203   dbus_bool_t retval = FALSE;
204   wchar_t *wusername;
205   DWORD sid_length;
206   PSID user_sid, console_user_sid;
207   HWINSTA winsta;
208
209   wusername = _dbus_win_utf8_to_utf16 (username, error);
210   if (!wusername)
211     return FALSE;
212
213   if (!_dbus_win_account_to_sid (wusername, &user_sid, error))
214     goto out0;
215
216   /* Now we have the SID for username. Get the SID of the
217    * user at the "console" (window station WinSta0)
218    */
219   if (!(winsta = OpenWindowStation ("WinSta0", FALSE, READ_CONTROL)))
220     {
221       _dbus_win_set_error_from_win_error (error, GetLastError ());
222       goto out2;
223     }
224
225   sid_length = 0;
226   GetUserObjectInformation (winsta, UOI_USER_SID,
227                             NULL, 0, &sid_length);
228   if (sid_length == 0)
229     {
230       /* Nobody is logged on */
231       goto out2;
232     }
233
234   if (sid_length < 0 || sid_length > 1000)
235     {
236       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID length");
237       goto out3;
238     }
239
240   console_user_sid = dbus_malloc (sid_length);
241   if (!console_user_sid)
242     {
243       _DBUS_SET_OOM (error);
244       goto out3;
245     }
246
247   if (!GetUserObjectInformation (winsta, UOI_USER_SID,
248                                  console_user_sid, sid_length, &sid_length))
249     {
250       _dbus_win_set_error_from_win_error (error, GetLastError ());
251       goto out4;
252     }
253
254   if (!IsValidSid (console_user_sid))
255     {
256       dbus_set_error_const (error, DBUS_ERROR_FAILED, "Invalid SID");
257       goto out4;
258     }
259
260   retval = EqualSid (user_sid, console_user_sid);
261
262 out4:
263   dbus_free (console_user_sid);
264 out3:
265   CloseWindowStation (winsta);
266 out2:
267   dbus_free (user_sid);
268 out0:
269   dbus_free (wusername);
270
271   return retval;
272 #endif //DBUS_WINCE
273 }
274
275 /**
276  * Removes a directory; Directory must be empty
277  * 
278  * @param filename directory filename
279  * @param error initialized error object
280  * @returns #TRUE on success
281  */
282 dbus_bool_t
283 _dbus_delete_directory (const DBusString *filename,
284                         DBusError        *error)
285 {
286   const char *filename_c;
287
288   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
289
290   filename_c = _dbus_string_get_const_data (filename);
291
292   if (rmdir (filename_c) != 0)
293     {
294       dbus_set_error (error, DBUS_ERROR_FAILED,
295                       "Failed to remove directory %s: %s\n",
296                       filename_c, _dbus_strerror (errno));
297       return FALSE;
298     }
299
300   return TRUE;
301 }
302
303 /** Installs a signal handler
304  *
305  * @param sig the signal to handle
306  * @param handler the handler
307  */
308 void
309 _dbus_set_signal_handler (int               sig,
310                           DBusSignalHandler handler)
311 {
312   _dbus_verbose ("_dbus_set_signal_handler() has to be implemented\n");
313 }
314
315 /** Checks if a file exists
316 *
317 * @param file full path to the file
318 * @returns #TRUE if file exists
319 */
320 dbus_bool_t 
321 _dbus_file_exists (const char *file)
322 {
323   HANDLE h = CreateFile(
324           file, /* LPCTSTR lpFileName*/
325           0, /* DWORD dwDesiredAccess */
326           0, /* DWORD dwShareMode*/
327           NULL, /* LPSECURITY_ATTRIBUTES lpSecurityAttributes */
328           OPEN_EXISTING, /* DWORD dwCreationDisposition */
329           FILE_ATTRIBUTE_NORMAL, /* DWORD dwFlagsAndAttributes */
330           NULL /* HANDLE hTemplateFile */
331         );
332
333     /* file not found, use local copy of session.conf  */
334     if (h != INVALID_HANDLE_VALUE && GetLastError() != ERROR_PATH_NOT_FOUND)
335       {
336         CloseHandle(h);
337         return TRUE;
338       }
339     else
340         return FALSE;  
341 }
342
343 /**
344  * stat() wrapper.
345  *
346  * @param filename the filename to stat
347  * @param statbuf the stat info to fill in
348  * @param error return location for error
349  * @returns #FALSE if error was set
350  */
351 dbus_bool_t
352 _dbus_stat(const DBusString *filename,
353            DBusStat         *statbuf,
354            DBusError        *error)
355 {
356 #ifdef DBUS_WINCE
357         return TRUE;
358         //TODO
359 #else
360   const char *filename_c;
361 #if !defined(DBUS_WIN) && !defined(DBUS_WINCE)
362
363   struct stat sb;
364 #else
365
366   WIN32_FILE_ATTRIBUTE_DATA wfad;
367   char *lastdot;
368   DWORD rc;
369   PSID owner_sid, group_sid;
370   PSECURITY_DESCRIPTOR sd;
371 #endif
372
373   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
374
375   filename_c = _dbus_string_get_const_data (filename);
376
377   if (!GetFileAttributesEx (filename_c, GetFileExInfoStandard, &wfad))
378     {
379       _dbus_win_set_error_from_win_error (error, GetLastError ());
380       return FALSE;
381     }
382
383   if (wfad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
384     statbuf->mode = _S_IFDIR;
385   else
386     statbuf->mode = _S_IFREG;
387
388   statbuf->mode |= _S_IREAD;
389   if (wfad.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
390     statbuf->mode |= _S_IWRITE;
391
392   lastdot = strrchr (filename_c, '.');
393   if (lastdot && stricmp (lastdot, ".exe") == 0)
394     statbuf->mode |= _S_IEXEC;
395
396   statbuf->mode |= (statbuf->mode & 0700) >> 3;
397   statbuf->mode |= (statbuf->mode & 0700) >> 6;
398
399   statbuf->nlink = 1;
400
401   sd = NULL;
402   rc = GetNamedSecurityInfo ((char *) filename_c, SE_FILE_OBJECT,
403                              OWNER_SECURITY_INFORMATION |
404                              GROUP_SECURITY_INFORMATION,
405                              &owner_sid, &group_sid,
406                              NULL, NULL,
407                              &sd);
408   if (rc != ERROR_SUCCESS)
409     {
410       _dbus_win_set_error_from_win_error (error, rc);
411       if (sd != NULL)
412         LocalFree (sd);
413       return FALSE;
414     }
415
416   statbuf->uid = _dbus_win_sid_to_uid_t (owner_sid);
417   statbuf->gid = _dbus_win_sid_to_uid_t (group_sid);
418
419   LocalFree (sd);
420
421   statbuf->size = ((dbus_int64_t) wfad.nFileSizeHigh << 32) + wfad.nFileSizeLow;
422
423   statbuf->atime =
424     (((dbus_int64_t) wfad.ftLastAccessTime.dwHighDateTime << 32) +
425      wfad.ftLastAccessTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
426
427   statbuf->mtime =
428     (((dbus_int64_t) wfad.ftLastWriteTime.dwHighDateTime << 32) +
429      wfad.ftLastWriteTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
430
431   statbuf->ctime =
432     (((dbus_int64_t) wfad.ftCreationTime.dwHighDateTime << 32) +
433      wfad.ftCreationTime.dwLowDateTime) / 10000000 - DBUS_INT64_CONSTANT (116444736000000000);
434
435   return TRUE;
436 #endif //DBUS_WINCE
437 }
438
439
440 #ifdef HAVE_DIRENT_H
441
442 // mingw ships with dirent.h
443 #include <dirent.h>
444 #define _dbus_opendir opendir
445 #define _dbus_readdir readdir
446 #define _dbus_closedir closedir
447
448 #else
449
450 #ifdef HAVE_IO_H
451 #include <io.h> // win32 file functions
452 #endif
453
454 #include <sys/types.h>
455 #include <stdlib.h>
456
457 /* This file is part of the KDE project
458 Copyright (C) 2000 Werner Almesberger
459
460 libc/sys/linux/sys/dirent.h - Directory entry as returned by readdir
461
462 This program is free software; you can redistribute it and/or
463 modify it under the terms of the GNU Library General Public
464 License as published by the Free Software Foundation; either
465 version 2 of the License, or (at your option) any later version.
466
467 This program is distributed in the hope that it will be useful,
468 but WITHOUT ANY WARRANTY; without even the implied warranty of
469 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
470 Library General Public License for more details.
471
472 You should have received a copy of the GNU Library General Public License
473 along with this program; see the file COPYING.  If not, write to
474 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
475 Boston, MA 02110-1301, USA.
476 */
477 #define HAVE_NO_D_NAMLEN        /* no struct dirent->d_namlen */
478 #define HAVE_DD_LOCK            /* have locking mechanism */
479
480 #define MAXNAMLEN 255           /* sizeof(struct dirent.d_name)-1 */
481
482 #define __dirfd(dir) (dir)->dd_fd
483
484 /* struct dirent - same as Unix */
485 struct dirent
486   {
487     long d_ino;                    /* inode (always 1 in WIN32) */
488     off_t d_off;                /* offset to this dirent */
489     unsigned short d_reclen;    /* length of d_name */
490     char d_name[_MAX_FNAME+1];    /* filename (null terminated) */
491   };
492
493 /* typedef DIR - not the same as Unix */
494 typedef struct
495   {
496     long handle;                /* _findfirst/_findnext handle */
497     short offset;                /* offset into directory */
498     short finished;             /* 1 if there are not more files */
499     struct _finddata_t fileinfo;  /* from _findfirst/_findnext */
500     char *dir;                  /* the dir we are reading */
501     struct dirent dent;         /* the dirent to return */
502   }
503 DIR;
504
505 /**********************************************************************
506 * Implement dirent-style opendir/readdir/closedir on Window 95/NT
507 *
508 * Functions defined are opendir(), readdir() and closedir() with the
509 * same prototypes as the normal dirent.h implementation.
510 *
511 * Does not implement telldir(), seekdir(), rewinddir() or scandir().
512 * The dirent struct is compatible with Unix, except that d_ino is
513 * always 1 and d_off is made up as we go along.
514 *
515 * The DIR typedef is not compatible with Unix.
516 **********************************************************************/
517
518 DIR * _dbus_opendir(const char *dir)
519 {
520   DIR *dp;
521   char *filespec;
522   long handle;
523   int index;
524
525   filespec = malloc(strlen(dir) + 2 + 1);
526   strcpy(filespec, dir);
527   index = strlen(filespec) - 1;
528   if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
529     filespec[index] = '\0';
530   strcat(filespec, "\\*");
531
532   dp = (DIR *)malloc(sizeof(DIR));
533   dp->offset = 0;
534   dp->finished = 0;
535   dp->dir = strdup(dir);
536
537   if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0)
538     {
539       if (errno == ENOENT)
540         dp->finished = 1;
541       else
542         return NULL;
543     }
544
545   dp->handle = handle;
546   free(filespec);
547
548   return dp;
549 }
550
551 struct dirent * _dbus_readdir(DIR *dp)
552   {
553     if (!dp || dp->finished)
554       return NULL;
555
556     if (dp->offset != 0)
557       {
558         if (_findnext(dp->handle, &(dp->fileinfo)) < 0)
559           {
560             dp->finished = 1;
561             errno = 0;
562             return NULL;
563           }
564       }
565     dp->offset++;
566
567     strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
568     dp->dent.d_ino = 1;
569     dp->dent.d_reclen = strlen(dp->dent.d_name);
570     dp->dent.d_off = dp->offset;
571
572     return &(dp->dent);
573   }
574
575
576 int _dbus_closedir(DIR *dp)
577 {
578   if (!dp)
579     return 0;
580   _findclose(dp->handle);
581   if (dp->dir)
582     free(dp->dir);
583   if (dp)
584     free(dp);
585
586   return 0;
587 }
588
589 #endif //#ifdef HAVE_DIRENT_H
590
591 /**
592  * Internals of directory iterator
593  */
594 struct DBusDirIter
595   {
596     DIR *d; /**< The DIR* from opendir() */
597
598   };
599
600 /**
601  * Open a directory to iterate over.
602  *
603  * @param filename the directory name
604  * @param error exception return object or #NULL
605  * @returns new iterator, or #NULL on error
606  */
607 DBusDirIter*
608 _dbus_directory_open (const DBusString *filename,
609                       DBusError        *error)
610 {
611   DIR *d;
612   DBusDirIter *iter;
613   const char *filename_c;
614
615   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
616
617   filename_c = _dbus_string_get_const_data (filename);
618
619   d = _dbus_opendir (filename_c);
620   if (d == NULL)
621     {
622       dbus_set_error (error, _dbus_error_from_errno (errno),
623                       "Failed to read directory \"%s\": %s",
624                       filename_c,
625                       _dbus_strerror (errno));
626       return NULL;
627     }
628   iter = dbus_new0 (DBusDirIter, 1);
629   if (iter == NULL)
630     {
631       _dbus_closedir (d);
632       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
633                       "Could not allocate memory for directory iterator");
634       return NULL;
635     }
636
637   iter->d = d;
638
639   return iter;
640 }
641
642 /**
643  * Get next file in the directory. Will not return "." or ".."  on
644  * UNIX. If an error occurs, the contents of "filename" are
645  * undefined. The error is never set if the function succeeds.
646  *
647  * @todo for thread safety, I think we have to use
648  * readdir_r(). (GLib has the same issue, should file a bug.)
649  *
650  * @param iter the iterator
651  * @param filename string to be set to the next file in the dir
652  * @param error return location for error
653  * @returns #TRUE if filename was filled in with a new filename
654  */
655 dbus_bool_t
656 _dbus_directory_get_next_file (DBusDirIter      *iter,
657                                DBusString       *filename,
658                                DBusError        *error)
659 {
660   struct dirent *ent;
661
662   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
663
664 again:
665   errno = 0;
666   ent = _dbus_readdir (iter->d);
667   if (ent == NULL)
668     {
669       if (errno != 0)
670         dbus_set_error (error,
671                         _dbus_error_from_errno (errno),
672                         "%s", _dbus_strerror (errno));
673       return FALSE;
674     }
675   else if (ent->d_name[0] == '.' &&
676            (ent->d_name[1] == '\0' ||
677             (ent->d_name[1] == '.' && ent->d_name[2] == '\0')))
678     goto again;
679   else
680     {
681       _dbus_string_set_length (filename, 0);
682       if (!_dbus_string_append (filename, ent->d_name))
683         {
684           dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
685                           "No memory to read directory entry");
686           return FALSE;
687         }
688       else
689         return TRUE;
690     }
691 }
692
693 /**
694  * Closes a directory iteration.
695  */
696 void
697 _dbus_directory_close (DBusDirIter *iter)
698 {
699   _dbus_closedir (iter->d);
700   dbus_free (iter);
701 }
702
703 /**
704  * Checks whether the filename is an absolute path
705  *
706  * @param filename the filename
707  * @returns #TRUE if an absolute path
708  */
709 dbus_bool_t
710 _dbus_path_is_absolute (const DBusString *filename)
711 {
712   if (_dbus_string_get_length (filename) > 0)
713     return _dbus_string_get_byte (filename, 1) == ':'
714            || _dbus_string_get_byte (filename, 0) == '\\'
715            || _dbus_string_get_byte (filename, 0) == '/';
716   else
717     return FALSE;
718 }
719
720 #ifdef ENABLE_DBUSGROPINFO
721 static dbus_bool_t
722 fill_group_info(DBusGroupInfo    *info,
723                 dbus_gid_t        gid,
724                 const DBusString *groupname,
725                 DBusError        *error)
726 {
727   const char *group_c_str;
728
729   _dbus_assert (groupname != NULL || gid != DBUS_GID_UNSET);
730   _dbus_assert (groupname == NULL || gid == DBUS_GID_UNSET);
731
732   if (groupname)
733     group_c_str = _dbus_string_get_const_data (groupname);
734   else
735     group_c_str = NULL;
736
737   if (group_c_str)
738     {
739       PSID group_sid;
740       wchar_t *wgroupname = _dbus_win_utf8_to_utf16 (group_c_str, error);
741
742       if (!wgroupname)
743         return FALSE;
744
745       if (!_dbus_win_account_to_sid (wgroupname, &group_sid, error))
746         {
747           dbus_free (wgroupname);
748           return FALSE;
749         }
750
751       info->gid = _dbus_win_sid_to_uid_t (group_sid);
752       info->groupname = _dbus_strdup (group_c_str);
753
754       dbus_free (group_sid);
755       dbus_free (wgroupname);
756
757       return TRUE;
758     }
759   else
760     {
761       dbus_bool_t retval = FALSE;
762       wchar_t *wname, *wdomain;
763       char *name, *domain;
764
765       info->gid = gid;
766
767       if (!_dbus_win_sid_to_name_and_domain (gid, &wname, &wdomain, error))
768         return FALSE;
769
770       name = _dbus_win_utf16_to_utf8 (wname, error);
771       if (!name)
772         goto out0;
773
774       domain = _dbus_win_utf16_to_utf8 (wdomain, error);
775       if (!domain)
776         goto out1;
777
778       info->groupname = dbus_malloc (strlen (domain) + 1 + strlen (name) + 1);
779
780       strcpy (info->groupname, domain);
781       strcat (info->groupname, "\\");
782       strcat (info->groupname, name);
783
784       retval = TRUE;
785
786       dbus_free (domain);
787 out1:
788       dbus_free (name);
789 out0:
790       dbus_free (wname);
791       dbus_free (wdomain);
792
793       return retval;
794     }
795 }
796
797 /**
798  * Initializes the given DBusGroupInfo struct
799  * with information about the given group ID.
800  *
801  * @param info the group info struct
802  * @param gid group ID
803  * @param error the error return
804  * @returns #FALSE if error is set
805  */
806 dbus_bool_t
807 _dbus_group_info_fill_gid (DBusGroupInfo *info,
808                            dbus_gid_t     gid,
809                            DBusError     *error)
810 {
811   return fill_group_info (info, gid, NULL, error);
812 }
813
814 /**
815  * Initializes the given DBusGroupInfo struct
816  * with information about the given group name.
817  *
818  * @param info the group info struct
819  * @param groupname name of group
820  * @param error the error return
821  * @returns #FALSE if error is set
822  */
823 dbus_bool_t
824 _dbus_group_info_fill (DBusGroupInfo    *info,
825                        const DBusString *groupname,
826                        DBusError        *error)
827 {
828   return fill_group_info (info, DBUS_GID_UNSET,
829                           groupname, error);
830 }
831 #endif
832
833 /** @} */ /* End of DBusInternalsUtils functions */
834
835 /**
836  * @addtogroup DBusString
837  *
838  * @{
839  */
840 /**
841  * Get the directory name from a complete filename
842  * @param filename the filename
843  * @param dirname string to append directory name to
844  * @returns #FALSE if no memory
845  */
846 dbus_bool_t
847 _dbus_string_get_dirname(const DBusString *filename,
848                          DBusString       *dirname)
849 {
850   int sep;
851
852   _dbus_assert (filename != dirname);
853   _dbus_assert (filename != NULL);
854   _dbus_assert (dirname != NULL);
855
856   /* Ignore any separators on the end */
857   sep = _dbus_string_get_length (filename);
858   if (sep == 0)
859     return _dbus_string_append (dirname, "."); /* empty string passed in */
860
861   while (sep > 0 &&
862          (_dbus_string_get_byte (filename, sep - 1) == '/' ||
863           _dbus_string_get_byte (filename, sep - 1) == '\\'))
864     --sep;
865
866   _dbus_assert (sep >= 0);
867
868   if (sep == 0 ||
869       (sep == 2 &&
870        _dbus_string_get_byte (filename, 1) == ':' &&
871        isalpha (_dbus_string_get_byte (filename, 0))))
872     return _dbus_string_copy_len (filename, 0, sep + 1,
873                                   dirname, _dbus_string_get_length (dirname));
874
875   {
876     int sep1, sep2;
877     _dbus_string_find_byte_backward (filename, sep, '/', &sep1);
878     _dbus_string_find_byte_backward (filename, sep, '\\', &sep2);
879
880     sep = MAX (sep1, sep2);
881   }
882   if (sep < 0)
883     return _dbus_string_append (dirname, ".");
884
885   while (sep > 0 &&
886          (_dbus_string_get_byte (filename, sep - 1) == '/' ||
887           _dbus_string_get_byte (filename, sep - 1) == '\\'))
888     --sep;
889
890   _dbus_assert (sep >= 0);
891
892   if ((sep == 0 ||
893        (sep == 2 &&
894         _dbus_string_get_byte (filename, 1) == ':' &&
895         isalpha (_dbus_string_get_byte (filename, 0))))
896       &&
897       (_dbus_string_get_byte (filename, sep) == '/' ||
898        _dbus_string_get_byte (filename, sep) == '\\'))
899     return _dbus_string_copy_len (filename, 0, sep + 1,
900                                   dirname, _dbus_string_get_length (dirname));
901   else
902     return _dbus_string_copy_len (filename, 0, sep - 0,
903                                   dirname, _dbus_string_get_length (dirname));
904 }
905
906
907 /**
908  * Checks to see if the UNIX user ID matches the UID of
909  * the process. Should always return #FALSE on Windows.
910  *
911  * @param uid the UNIX user ID
912  * @returns #TRUE if this uid owns the process.
913  */
914 dbus_bool_t
915 _dbus_unix_user_is_process_owner (dbus_uid_t uid)
916 {
917   return FALSE;
918 }
919
920 /*=====================================================================
921   unix emulation functions - should be removed sometime in the future
922  =====================================================================*/
923
924 /**
925  * Checks to see if the UNIX user ID is at the console.
926  * Should always fail on Windows (set the error to
927  * #DBUS_ERROR_NOT_SUPPORTED).
928  *
929  * @param uid UID of person to check 
930  * @param error return location for errors
931  * @returns #TRUE if the UID is the same as the console user and there are no errors
932  */
933 dbus_bool_t
934 _dbus_unix_user_is_at_console (dbus_uid_t         uid,
935                                DBusError         *error)
936 {
937   return FALSE;
938 }
939
940
941 /**
942  * Parse a UNIX group from the bus config file. On Windows, this should
943  * simply always fail (just return #FALSE).
944  *
945  * @param groupname the groupname text
946  * @param gid_p place to return the gid
947  * @returns #TRUE on success
948  */
949 dbus_bool_t
950 _dbus_parse_unix_group_from_config (const DBusString  *groupname,
951                                     dbus_gid_t        *gid_p)
952 {
953   return FALSE;
954 }
955
956 /**
957  * Parse a UNIX user from the bus config file. On Windows, this should
958  * simply always fail (just return #FALSE).
959  *
960  * @param username the username text
961  * @param uid_p place to return the uid
962  * @returns #TRUE on success
963  */
964 dbus_bool_t
965 _dbus_parse_unix_user_from_config (const DBusString  *username,
966                                    dbus_uid_t        *uid_p)
967 {
968   return FALSE;
969 }
970
971
972 /**
973  * Gets all groups corresponding to the given UNIX user ID. On UNIX,
974  * just calls _dbus_groups_from_uid(). On Windows, should always
975  * fail since we don't know any UNIX groups.
976  *
977  * @param uid the UID
978  * @param group_ids return location for array of group IDs
979  * @param n_group_ids return location for length of returned array
980  * @returns #TRUE if the UID existed and we got some credentials
981  */
982 dbus_bool_t
983 _dbus_unix_groups_from_uid (dbus_uid_t            uid,
984                             dbus_gid_t          **group_ids,
985                             int                  *n_group_ids)
986 {
987   return FALSE;
988 }
989
990
991
992 /** @} */ /* DBusString stuff */
993