3 MPDM - Minimum Profit Data Manager
4 Copyright (C) 2003/2007 Angel Ortega <angel@triptico.com>
6 mpdm_f.c - File management
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 http://www.triptico.com
33 #ifdef CONFOPT_UNISTD_H
49 #ifdef CONFOPT_SYS_TYPES_H
50 #include <sys/types.h>
53 #ifdef CONFOPT_SYS_WAIT_H
57 #ifdef CONFOPT_SYS_STAT_H
83 #else /* CONFOPT_ICONV */
87 #endif /* CONFOPT_ICONV */
94 #endif /* CONFOPT_WIN32 */
103 ********************/
106 static void store_syserr(void)
107 /* stores the system error inside the global ERRNO */
109 mpdm_hset_s(mpdm_root(), L
"ERRNO", MPDM_MBS(strerror(errno
)));
113 static int get_char(struct mpdm_file
*f
)
114 /* reads a character from a file structure */
120 if (f
->hin
!= NULL
) {
124 if (ReadFile(f
->hin
, &tmp
, 1, &n
, NULL
) && n
> 0)
128 #endif /* CONFOPT_WIN32 */
131 /* read (converting to positive if needed) */
132 if ((c
= fgetc(f
->in
)) < 0 && !feof(f
->in
))
140 static int put_buf(char *ptr
, int s
, struct mpdm_file
*f
)
141 /* writes s bytes in the buffer in ptr to f */
145 if (f
->hout
!= NULL
) {
148 if (WriteFile(f
->hout
, ptr
, s
, &n
, NULL
) && n
> 0)
152 #endif /* CONFOPT_WIN32 */
155 s
= fwrite(ptr
, s
, 1, f
->out
);
161 static int put_char(int c
, struct mpdm_file
*f
)
162 /* writes a character in a file structure */
166 if (put_buf(&tmp
, 1, f
) != 1)
173 static wchar_t *read_mbs(struct mpdm_file
*f
, int *s
)
174 /* reads a multibyte string from a mpdm_file into a dynamic string */
181 while ((c
= get_char(f
)) != EOF
) {
187 if (i
== sizeof(tmp
) - 1) {
188 /* out of space; start allocating */
189 if ((auxptr
= mpdm_poke(auxptr
, &n
, tmp
, i
, sizeof(char))) == NULL
)
196 /* is there something to return? */
202 /* auxiliary space used; concat all */
203 if ((auxptr
= mpdm_poke(auxptr
, &n
, tmp
, i
, sizeof(char))) == NULL
)
206 /* do the conversion */
207 ptr
= mpdm_mbstowcs(auxptr
, s
, -1);
212 ptr
= mpdm_mbstowcs(tmp
, s
, -1);
219 static int write_wcs(struct mpdm_file
*f
, wchar_t * str
)
220 /* writes a wide string to an struct mpdm_file */
225 ptr
= mpdm_wcstombs(str
, &s
);
226 s
= put_buf(ptr
, s
, f
);
235 static wchar_t *read_iconv(struct mpdm_file
*f
, int *s
)
236 /* reads a multibyte string transforming with iconv */
245 /* resets the decoder */
246 iconv(f
->ic_dec
, NULL
, NULL
, NULL
, NULL
);
248 while ((c
= get_char(f
)) != EOF
) {
254 /* too big? shouldn't happen */
255 if (i
== sizeof(tmp
))
260 ol
= sizeof(wchar_t);
264 if (iconv(f
->ic_dec
, &iptr
, &il
, &optr
, &ol
) == -1) {
265 /* found incomplete multibyte character */
269 /* otherwise, return '?' */
275 if ((ptr
= mpdm_poke(ptr
, s
, &wc
, 1, sizeof(wchar_t))) == NULL
)
278 /* if it's an end of line, finish */
284 ptr
= mpdm_poke(ptr
, s
, L
"", 1, sizeof(wchar_t));
292 static int write_iconv(struct mpdm_file
*f
, wchar_t * str
)
293 /* writes a wide string to a stream using iconv */
298 /* resets the encoder */
299 iconv(f
->ic_enc
, NULL
, NULL
, NULL
, NULL
);
301 /* convert char by char */
302 for (; *str
!= L
'\0'; str
++) {
307 il
= sizeof(wchar_t);
313 if (iconv(f
->ic_enc
, &iptr
, &il
, &optr
, &ol
) == -1) {
314 /* error converting; convert a '?' instead */
317 il
= sizeof(wchar_t);
322 iconv(f
->ic_enc
, &iptr
, &il
, &optr
, &ol
);
325 for (n
= 0; n
< sizeof(tmp
) - ol
; n
++, cnt
++) {
326 if (put_char(tmp
[n
], f
) == EOF
)
335 #else /* CONFOPT_ICONV */
337 #define UTF8_BYTE() if((c = get_char(f)) == EOF) break
339 static wchar_t *read_utf8(struct mpdm_file
*f
, int *s
)
340 /* crappy, ad-hoc utf8 reader */
356 if ((c
& 0xe0) == 0xe0) {
357 wc
= (c
& 0x1f) << 12;
359 wc
|= (c
& 0x3f) << 6;
364 wc
= (c
& 0x3f) << 6;
370 if ((ptr
= mpdm_poke(ptr
, s
, &wc
, 1, sizeof(wchar_t))) == NULL
)
373 /* if it's an end of line, finish */
379 ptr
= mpdm_poke(ptr
, s
, L
"", 1, sizeof(wchar_t));
387 static int write_utf8(struct mpdm_file
*f
, wchar_t * str
)
388 /* crappy, ad-hoc utf8 writer */
393 /* convert char by char */
394 for (; (wc
= *str
) != L
'\0'; str
++) {
396 put_char((int) wc
, f
);
399 put_char((int) (0xc0 | (wc
>> 6)), f
);
400 put_char((int) (0x80 | (wc
& 0x3f)), f
);
404 put_char((int) (0xe0 | (wc
>> 12)), f
);
405 put_char((int) (0x80 | ((wc
>> 6) & 0x3f)), f
);
406 put_char((int) (0x80 | (wc
& 0x3f)), f
);
417 #endif /* CONFOPT_ICONV */
420 static mpdm_t
new_mpdm_file(void)
421 /* creates a new file value */
424 struct mpdm_file
*fs
;
426 if ((fs
= malloc(sizeof(struct mpdm_file
))) == NULL
)
429 memset(fs
, '\0', sizeof(struct mpdm_file
));
433 if ((v
= mpdm_hget_s(mpdm_root(), L
"ENCODING")) != NULL
) {
434 mpdm_t cs
= MPDM_2MBS(v
->data
);
436 fs
->ic_enc
= iconv_open((char *) cs
->data
, "WCHAR_T");
437 fs
->ic_dec
= iconv_open("WCHAR_T", (char *) cs
->data
);
440 fs
->ic_enc
= fs
->ic_dec
= (iconv_t
) - 1;
442 #else /* CONFOPT_ICONV */
444 /* if the encoding is utf8, set the flag */
445 if ((v
= mpdm_hget_s(mpdm_root(), L
"ENCODING")) != NULL
) {
446 wchar_t *enc
= mpdm_string(v
);
448 /* if it's utf-8, set the flag */
449 if (wcscmp(enc
, L
"utf-8") == 0 ||
450 wcscmp(enc
, L
"UTF-8") == 0 ||
451 wcscmp(enc
, L
"utf8") == 0 || wcscmp(enc
, L
"UTF8") == 0)
455 #endif /* CONFOPT_ICONV */
457 if ((v
= mpdm_new(MPDM_FILE
| MPDM_FREE
, fs
, sizeof(struct mpdm_file
))) == NULL
)
464 static void destroy_mpdm_file(mpdm_t v
)
465 /* destroys and file value */
467 struct mpdm_file
*fs
= v
->data
;
472 if (fs
->ic_enc
!= (iconv_t
) - 1) {
473 iconv_close(fs
->ic_enc
);
474 fs
->ic_enc
= (iconv_t
) - 1;
477 if (fs
->ic_dec
!= (iconv_t
) - 1) {
478 iconv_close(fs
->ic_dec
);
479 fs
->ic_dec
= (iconv_t
) - 1;
491 wchar_t *mpdm_read_mbs(FILE * f
, int *s
)
492 /* reads a multibyte string from a stream into a dynamic string */
496 /* reset the structure */
497 memset(&fs
, '\0', sizeof(fs
));
500 return read_mbs(&fs
, s
);
504 int mpdm_write_wcs(FILE * f
, wchar_t * str
)
505 /* writes a wide string to a stream */
509 /* reset the structure */
510 memset(&fs
, '\0', sizeof(fs
));
513 return write_wcs(&fs
, str
);
517 mpdm_t
mpdm_new_f(FILE * f
)
518 /* creates a new file value from a FILE * */
525 if ((v
= new_mpdm_file()) != NULL
) {
526 struct mpdm_file
*fs
= v
->data
;
527 fs
->in
= fs
->out
= f
;
535 * mpdm_open - Opens a file.
536 * @filename: the file name
537 * @mode: an fopen-like mode string
539 * Opens a file. If @filename can be open in the specified @mode, an
540 * mpdm_t value will be returned containing the file descriptor, or NULL
544 mpdm_t
mpdm_open(mpdm_t filename
, mpdm_t mode
)
548 if (filename
== NULL
|| mode
== NULL
)
551 /* convert to mbs,s */
552 filename
= MPDM_2MBS(filename
->data
);
553 mode
= MPDM_2MBS(mode
->data
);
555 if ((f
= fopen((char *) filename
->data
, (char *) mode
->data
)) == NULL
)
558 #if defined(CONFOPT_SYS_STAT_H) && defined(S_ISDIR) && defined(EISDIR)
561 /* test if the open file is a directory */
562 if (fstat(fileno(f
), &s
) != -1 && S_ISDIR(s
.st_mode
)) {
563 /* it's a directory; fail */
577 * mpdm_close - Closes a file descriptor.
578 * @fd: the value containing the file descriptor
580 * Closes the file descriptor.
583 mpdm_t
mpdm_close(mpdm_t fd
)
585 struct mpdm_file
*fs
= fd
->data
;
587 if ((fd
->flags
& MPDM_FILE
) && fs
!= NULL
) {
591 if (fs
->out
!= fs
->in
&& fs
->out
!= NULL
)
594 destroy_mpdm_file(fd
);
602 * mpdm_read - Reads a line from a file descriptor.
603 * @fd: the value containing the file descriptor
605 * Reads a line from @fd. Returns the line, or NULL on EOF.
607 * [Character Set Conversion]
609 mpdm_t
mpdm_read(mpdm_t fd
)
614 struct mpdm_file
*fs
= fd
->data
;
621 if (fs
->ic_dec
!= (iconv_t
) - 1)
622 ptr
= read_iconv(fs
, &s
);
624 #else /* CONFOPT_ICONV */
627 ptr
= read_utf8(fs
, &s
);
629 #endif /* CONFOPT_ICONV */
631 ptr
= read_mbs(fs
, &s
);
634 v
= MPDM_ENS(ptr
, s
);
640 mpdm_t
mpdm_getchar(mpdm_t fd
)
644 struct mpdm_file
*fs
= fd
->data
;
646 if (fs
== NULL
|| (c
= get_char(fs
)) == EOF
)
649 /* get the char as-is */
650 tmp
[0] = (wchar_t) c
;
657 mpdm_t
mpdm_putchar(mpdm_t fd
, mpdm_t c
)
659 struct mpdm_file
*fs
= fd
->data
;
660 wchar_t *ptr
= mpdm_string(c
);
662 if (fs
== NULL
|| put_char(*ptr
, fs
) == -1)
670 * mpdm_write - Writes a value into a file.
671 * @fd: the file descriptor.
672 * @v: the value to be written.
674 * Writes the @v string value into @fd, using the current encoding.
676 * [Character Set Conversion]
678 int mpdm_write(mpdm_t fd
, mpdm_t v
)
680 struct mpdm_file
*fs
= fd
->data
;
688 if (fs
->ic_enc
!= (iconv_t
) - 1)
689 ret
= write_iconv(fs
, mpdm_string(v
));
691 #else /* CONFOPT_ICONV */
694 ret
= write_utf8(fs
, mpdm_string(v
));
696 #endif /* CONFOPT_ICONV */
698 ret
= write_wcs(fs
, mpdm_string(v
));
704 int mpdm_fseek(mpdm_t fd
, long offset
, int whence
)
706 struct mpdm_file
*fs
= fd
->data
;
708 return fseek(fs
->in
, offset
, whence
);
712 long mpdm_ftell(mpdm_t fd
)
714 struct mpdm_file
*fs
= fd
->data
;
716 return ftell(fs
->in
);
720 FILE * mpdm_get_filehandle(mpdm_t fd
)
724 if (fd
->flags
& MPDM_FILE
) {
725 struct mpdm_file
*fs
= fd
->data
;
734 mpdm_t mpdm_bread(mpdm_t fd, int size)
739 int mpdm_bwrite(mpdm_tfd, mpdm_t v, int size)
746 * mpdm_encoding - Sets the current charset encoding for files.
747 * @charset: the charset name.
749 * Sets the current charset encoding for files. Future opened
750 * files will be assumed to be encoded with @charset, which can
751 * be any of the supported charset names (utf-8, iso-8859-1, etc.),
752 * and converted on each read / write. If charset is NULL, it
753 * is reverted to default charset conversion (i.e. the one defined
755 * Returns a negative number if @charset is unsupported, or zero
756 * if no errors were found.
758 * [Character Set Conversion]
760 int mpdm_encoding(mpdm_t charset
)
766 if (charset
!= NULL
) {
768 mpdm_t cs
= MPDM_2MBS(charset
->data
);
770 /* tries to create an encoder and a decoder for this charset */
772 if ((ic
= iconv_open("WCHAR_T", (char *) cs
->data
)) == (iconv_t
) - 1)
777 if ((ic
= iconv_open((char *) cs
->data
, "WCHAR_T")) == (iconv_t
) - 1)
783 /* can create; store and exit */
785 mpdm_hset_s(mpdm_root(), L
"ENCODING", charset
);
789 #else /* CONFOPT_ICONV */
791 wchar_t *enc
= mpdm_string(charset
);
793 /* if it's NULL or utf-8, store */
794 if (charset
== NULL
||
795 wcscmp(enc
, L
"utf-8") == 0 ||
796 wcscmp(enc
, L
"UTF-8") == 0 ||
797 wcscmp(enc
, L
"utf8") == 0 || wcscmp(enc
, L
"UTF8") == 0) {
798 mpdm_hset_s(mpdm_root(), L
"ENCODING", charset
);
802 #endif /* CONFOPT_ICONV */
809 * mpdm_unlink - Deletes a file.
810 * @filename: file name to be deleted
815 int mpdm_unlink(mpdm_t filename
)
820 filename
= MPDM_2MBS(filename
->data
);
822 if ((ret
= unlink((char *) filename
->data
)) == -1)
830 * mpdm_stat - Gives status from a file.
831 * @filename: file name to get the status from
833 * Returns a 13 element array of the status (permissions, onwer, etc.)
834 * from the desired @filename, or NULL if the file cannot be accessed.
838 mpdm_t
mpdm_stat(mpdm_t filename
)
842 #ifdef CONFOPT_SYS_STAT_H
845 filename
= MPDM_2MBS(filename
->data
);
847 if (stat((char *) filename
->data
, &s
) != -1) {
850 mpdm_aset(r
, MPDM_I(s
.st_dev
), 0);
851 mpdm_aset(r
, MPDM_I(s
.st_ino
), 1);
852 mpdm_aset(r
, MPDM_I(s
.st_mode
), 2);
853 mpdm_aset(r
, MPDM_I(s
.st_nlink
), 3);
854 mpdm_aset(r
, MPDM_I(s
.st_uid
), 4);
855 mpdm_aset(r
, MPDM_I(s
.st_gid
), 5);
856 mpdm_aset(r
, MPDM_I(s
.st_rdev
), 6);
857 mpdm_aset(r
, MPDM_I(s
.st_size
), 7);
858 mpdm_aset(r
, MPDM_I(s
.st_atime
), 8);
859 mpdm_aset(r
, MPDM_I(s
.st_mtime
), 9);
860 mpdm_aset(r
, MPDM_I(s
.st_ctime
), 10);
861 mpdm_aset(r
, MPDM_I(0), 11); /* s.st_blksize */
862 mpdm_aset(r
, MPDM_I(0), 12); /* s.st_blocks */
867 #endif /* CONFOPT_SYS_STAT_H */
874 * mpdm_chmod - Changes a file's permissions.
875 * @filename: the file name
876 * @perms: permissions (element 2 from mpdm_stat())
878 * Changes the permissions for a file.
881 int mpdm_chmod(mpdm_t filename
, mpdm_t perms
)
885 filename
= MPDM_2MBS(filename
->data
);
886 if ((r
= chmod((char *) filename
->data
, mpdm_ival(perms
))) == -1)
894 * mpdm_chown - Changes a file's owner.
895 * @filename: the file name
896 * @uid: user id (element 4 from mpdm_stat())
897 * @gid: group id (element 5 from mpdm_stat())
899 * Changes the owner and group id's for a file.
902 int mpdm_chown(mpdm_t filename
, mpdm_t uid
, mpdm_t gid
)
908 filename
= MPDM_2MBS(filename
->data
);
909 if ((r
= chown((char *) filename
->data
, mpdm_ival(uid
), mpdm_ival(gid
))) == -1)
912 #endif /* CONFOPT_CHOWN */
919 * mpdm_glob - Executes a file globbing.
920 * @spec: Globbing spec
922 * Executes a file globbing. @spec is system-dependent, but usually
923 * the * and ? metacharacters work everywhere. @spec can contain a
924 * directory; if that's the case, the output strings will include it.
925 * In any case, each returned value will be suitable for a call to
928 * Returns an array of files that match the globbing (can be an empty
929 * array if no file matches), or NULL if globbing is unsupported.
932 mpdm_t
mpdm_glob(mpdm_t spec
)
948 spec
= MPDM_2MBS(spec
->data
);
950 spec
= MPDM_2MBS(L
"*.*");
952 ptr
= (char *) spec
->data
;
954 /* convert MSDOS dir separators into Unix ones */
955 for (; *ptr
!= '\0'; ptr
++) {
964 if ((h
= FindFirstFile((char *) spec
->data
, &fd
)) != INVALID_HANDLE_VALUE
) {
965 /* if spec includes a directory, store in s */
966 if ((ptr
= strrchr((char *) spec
->data
, '/')) != NULL
) {
968 s
= MPDM_S(spec
->data
);
972 /* ignore . and .. */
973 if (strcmp(fd
.cFileName
, ".") == 0 || strcmp(fd
.cFileName
, "..") == 0)
976 /* concat base directory and file names */
977 w
= mpdm_strcat(s
, MPDM_MBS(fd
.cFileName
));
979 /* if it's a directory, add a / */
980 if (fd
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
981 w
= mpdm_strcat(w
, MPDM_LS(L
"/"));
987 while (FindNextFile(h
, &fd
));
1000 /* convert to mbs */
1002 spec
= MPDM_2MBS(spec
->data
);
1005 if (ptr
== NULL
|| *ptr
== '\0')
1011 globbuf
.gl_offs
= 1;
1017 if (glob(ptr
, GLOB_MARK
, NULL
, &globbuf
) == 0) {
1020 for (n
= 0; globbuf
.gl_pathv
[n
] != NULL
; n
++) {
1021 char *ptr
= globbuf
.gl_pathv
[n
];
1022 mpdm_t t
= MPDM_MBS(ptr
);
1024 /* if last char is /, add to directories */
1025 if (ptr
[strlen(ptr
) - 1] == '/')
1036 /* no win32 nor glob.h; try workaround */
1044 d
= mpdm_sort(d
, 1);
1045 f
= mpdm_sort(f
, 1);
1047 /* transfer all data in d and f */
1048 for (n
= 0; n
< mpdm_size(d
); n
++)
1049 mpdm_push(v
, mpdm_aget(d
, n
));
1050 for (n
= 0; n
< mpdm_size(f
); n
++)
1051 mpdm_push(v
, mpdm_aget(f
, n
));
1058 #ifdef CONFOPT_WIN32
1060 static void win32_pipe(HANDLE
* h
, int n
)
1062 SECURITY_ATTRIBUTES sa
;
1065 memset(&sa
, '\0', sizeof(sa
));
1066 sa
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
1067 sa
.bInheritHandle
= TRUE
;
1068 sa
.lpSecurityDescriptor
= NULL
;
1070 cp
= GetCurrentProcess();
1072 CreatePipe(&h
[0], &h
[1], &sa
, 0);
1073 DuplicateHandle(cp
, h
[n
], cp
, &t
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
1079 static int sysdep_popen(mpdm_t v
, char *prg
, int rw
)
1080 /* win32-style pipe */
1084 PROCESS_INFORMATION pi
;
1087 struct mpdm_file
*fs
= v
->data
;
1090 pr
[0] = pr
[1] = pw
[0] = pw
[1] = NULL
;
1097 /* spawn new process */
1098 memset(&pi
, '\0', sizeof(pi
));
1099 memset(&si
, '\0', sizeof(si
));
1101 si
.cb
= sizeof(STARTUPINFO
);
1102 si
.hStdError
= pr
[1];
1103 si
.hStdOutput
= pr
[1];
1104 si
.hStdInput
= pw
[0];
1105 si
.dwFlags
|= STARTF_USESTDHANDLES
;
1107 ret
= CreateProcess(NULL
, prg
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
);
1121 static int sysdep_pclose(mpdm_t v
)
1123 struct mpdm_file
*fs
= v
->data
;
1125 if (fs
->hin
!= NULL
)
1126 CloseHandle(fs
->hin
);
1128 if (fs
->hout
!= NULL
)
1129 CloseHandle(fs
->hout
);
1131 /* how to know process exit code? */
1136 #else /* CONFOPT_WIN32 */
1138 static int sysdep_popen(mpdm_t v
, char *prg
, int rw
)
1139 /* unix-style pipe open */
1142 struct mpdm_file
*fs
= v
->data
;
1145 pr
[0] = pr
[1] = pw
[0] = pw
[1] = -1;
1165 /* redirect stderr to stdout */
1169 /* run the program */
1170 execlp("/bin/sh", "/bin/sh", "-c", prg
, NULL
);
1171 execlp(prg
, prg
, NULL
);
1173 /* still here? exec failed; close pipes and exit */
1179 /* create the pipes as non-buffered streams */
1181 fs
->in
= fdopen(pr
[0], "r");
1182 setvbuf(fs
->in
, NULL
, _IONBF
, 0);
1187 fs
->out
= fdopen(pw
[1], "w");
1188 setvbuf(fs
->out
, NULL
, _IONBF
, 0);
1196 static int sysdep_pclose(mpdm_t v
)
1197 /* unix-style pipe close */
1200 struct mpdm_file
*fs
= v
->data
;
1205 if (fs
->out
!= fs
->in
&& fs
->out
!= NULL
)
1214 #endif /* CONFOPT_WIN32 */
1218 * mpdm_popen - Opens a pipe.
1219 * @prg: the program to pipe
1220 * @mode: an fopen-like mode string
1222 * Opens a pipe to a program. If @prg can be open in the specified @mode, an
1223 * mpdm_t value will be returned containing the file descriptor, or NULL
1227 mpdm_t
mpdm_popen(mpdm_t prg
, mpdm_t mode
)
1233 if (prg
== NULL
|| mode
== NULL
)
1236 if ((v
= new_mpdm_file()) == NULL
)
1239 /* convert to mbs,s */
1240 prg
= MPDM_2MBS(prg
->data
);
1241 mode
= MPDM_2MBS(mode
->data
);
1244 m
= (char *) mode
->data
;
1252 rw
= 0x03; /* r+ or w+ */
1254 if (!sysdep_popen(v
, (char *) prg
->data
, rw
)) {
1255 destroy_mpdm_file(v
);
1264 * mpdm_pclose - Closes a pipe.
1265 * @fd: the value containing the file descriptor
1270 mpdm_t
mpdm_pclose(mpdm_t fd
)
1274 if ((fd
->flags
& MPDM_FILE
) && fd
->data
!= NULL
) {
1275 r
= MPDM_I(sysdep_pclose(fd
));
1276 destroy_mpdm_file(fd
);
1284 * mpdm_home_dir - Returns the home user directory.
1286 * Returns a system-dependent directory where the user can write
1287 * documents and create subdirectories.
1290 mpdm_t
mpdm_home_dir(void)
1296 #ifdef CONFOPT_WIN32
1300 /* get the 'My Documents' folder */
1301 SHGetSpecialFolderLocation(NULL
, CSIDL_PERSONAL
, &pidl
);
1302 SHGetPathFromIDList(pidl
, tmp
);
1307 #ifdef CONFOPT_PWD_H
1311 /* get home dir from /etc/passwd entry */
1312 if (tmp
[0] == '\0' && (p
= getpwuid(getpid())) != NULL
) {
1313 strcpy(tmp
, p
->pw_dir
);
1319 /* still none? try the ENV variable $HOME */
1320 if (tmp
[0] == '\0' && (ptr
= getenv("HOME")) != NULL
) {
1333 * mpdm_app_dir - Returns the applications directory.
1335 * Returns a system-dependent directory where the applications store
1336 * their private data, as components or resources.
1339 mpdm_t
mpdm_app_dir(void)
1343 #ifdef CONFOPT_WIN32
1349 /* get the 'Program Files' folder (can fail) */
1351 if (SHGetSpecialFolderLocation(NULL
, CSIDL_PROGRAM_FILES
, &pidl
) == S_OK
)
1352 SHGetPathFromIDList(pidl
, tmp
);
1354 /* if it's still empty, get from the registry */
1355 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
1356 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
1357 0, KEY_QUERY_VALUE
, &hkey
) == ERROR_SUCCESS
) {
1358 int n
= sizeof(tmp
);
1360 if (RegQueryValueEx(hkey
, "ProgramFilesDir",
1361 NULL
, NULL
, tmp
, (LPDWORD
) & n
) != ERROR_SUCCESS
)
1365 if (tmp
[0] != '\0') {
1371 /* still none? get the configured directory */
1373 r
= MPDM_MBS(CONFOPT_PREFIX
"/share/");