Spelling fixes
[oweals/cde.git] / cde / programs / dtmail / libDtMail / Common / IO.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *+SNOTICE
25  *
26  *
27  *      $TOG: IO.C /main/33 1999/01/29 14:45:00 mgreess $
28  *
29  *      RESTRICTED CONFIDENTIAL INFORMATION:
30  *      
31  *      The information in this document is subject to special
32  *      restrictions in a confidential disclosure agreement bertween
33  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
34  *      document outside HP, IBM, Sun, USL, SCO, or Univel wihtout
35  *      Sun's specific written approval.  This documment and all copies
36  *      and derivative works thereof must be returned or destroyed at
37  *      Sun's request.
38  *
39  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
40  *
41  *+ENOTICE
42  */
43
44 #define X_INCLUDE_TIME_H
45 #define X_INCLUDE_GRP_H
46 #define X_INCLUDE_PWD_H
47 #define XOS_USE_NO_LOCKING
48 #include <X11/Xos_r.h>
49
50 #include <assert.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <stdio.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdlib.h>
57 //
58 // START Order dependent for AIX
59 //
60 #include <sys/socket.h>
61 #if defined(_aix)
62 #include <sys/socketvar.h>
63 #if defined(BIG_ENDIAN)
64 #undef BIG_ENDIAN
65 #endif
66 #endif
67 #include <netinet/in.h>
68 #include <netdb.h>
69 #include <arpa/inet.h>
70 //
71 // END Order dependent for AIX
72 //
73 #include <sys/stat.h>
74 #if !defined(__linux__)
75 #  include <sys/statvfs.h>
76 #endif
77 #include <sys/types.h>
78 #include <sys/wait.h>
79 #include <sys/uio.h>
80 #include <unistd.h>
81
82 #ifdef _AIX
83 #include <sys/mntctl.h>
84 #include <sys/statfs.h>
85 #include <sys/vfs.h>
86 #define IOVMAX MSG_MAXIOVLEN
87 extern "C"
88 {
89           fchmod(int, mode_t);
90           statfs(const char *, struct statfs *);
91           mntctl(int, int, char *);
92   ssize_t writev(int, const struct iovec *, int);
93 }
94 #if (OSMAJORVERSION==4) && (OSMINORVERSION==2)
95 /* Temporary hack till the /usr/lpp/xlC/include/unistd.h file is fixed. */
96 extern "C" { int lockf(int, int, off_t); }
97 #endif
98 #endif /* _AIX */
99
100 #include <DtMail/DtMail.hh>
101 #include <DtMail/DtMailError.hh>
102 #include <DtMail/IO.hh>
103 #include <DtMail/Threads.hh>
104
105 #if !defined(IOV_MAX)
106   #if !defined(__linux__)
107     #include <sys/stream.h>
108   #endif
109   #if !defined(DEF_IOV_MAX)
110     #define DEF_IOV_MAX 16
111   #endif
112   #define IOV_MAX DEF_IOV_MAX
113 #endif
114
115 #define IOVEC_IOVBASE_INCREMENTOR(iov, bytes) \
116         ((caddr_t)((size_t)iov->iov_base+bytes))
117
118 // The following I/O routines are wrappers for the normal routines,
119 // but they deal with EINTR, and partial read/write situations.
120 //
121 //
122 int
123 SafeOpen(const char * path, int oflag, mode_t mode)
124 {
125     int status;
126     
127     do {
128         status = open(path, oflag, mode);
129     } while (status < 0 && errno == EINTR);
130
131     return(status);
132 }
133
134 int
135 SafeClose(int fd)
136 {
137     int status;
138     do {
139         status = close(fd);
140     } while (status < 0 && errno == EINTR);
141
142     return(status);
143 }
144
145 int
146 SafeLink(const char * existingPath, const char * newPath)
147 {
148   int status;
149   do {
150     status = link(existingPath, newPath);
151   } while (status < 0 && errno == EINTR);
152
153   return(status);
154 }
155
156 int
157 SafeRename(const char * oldPath, const char * newPath)
158 {
159   int status;
160   do {
161     status = rename(oldPath, newPath);
162   } while (status < 0 && errno == EINTR);
163
164   return(status);
165 }
166
167 int
168 SafeRemove(const char *path)
169 {
170     int status;
171     do {
172       status = remove(path);
173     } while (status < 0 && errno == EINTR);
174
175     return(status);
176 }
177
178 int
179 SafeUnlink(const char *path)
180 {
181     int status;
182     do {
183       status = unlink(path);
184     } while (status < 0 && errno == EINTR);
185
186     return(status);
187 }
188
189 ssize_t
190 SafeRead(int fd, void * buf, size_t bytes)
191 {
192     ssize_t status = 0;
193     do {
194         status = read(fd, buf, bytes);
195     } while(status < 0 && errno == EINTR);
196
197     return(status);
198 }
199
200 ssize_t
201 SafeWrite(int fd, const void * buf, size_t bytes)
202 {
203     ssize_t status = 0;
204     do {
205         status = write(fd, buf, bytes);
206     } while(status < 0 && errno == EINTR);
207     
208     return(status);
209 }
210
211 // SafeWritev -- safe multiply vectored write
212 // Description:
213 //   SafeWritev provides an interrupt safe way to call the writev() system
214 //   call. In addition, it removes the IOV_MAX limitation on the size of the
215 //   iovec structure, and it will not return until either all bytes specified
216 //   by the iovec structure are written or writev() returns an error.
217 // Arguments:
218 //   int fd     -- file descriptor to write to
219 //   struct iovec *iov -- iovec structure describing writes to be done
220 //   int iovcnt -- number of elements in passed in iov structure
221 // Outputs:
222 //   Will effectively destroy the contents of the passed in iovec structure.
223 //   The caller must deallocate the storage associated with the structure
224 //   upon regaining control.
225 // Returns:
226 //   == -1 : error returned from writev() - errno set to specific error number
227 //   != -1 : number of bytes actually written to the file
228
229 unsigned long
230 SafeWritev(int fd, struct iovec *iov, int iovcnt)
231 {
232   ssize_t status;
233   unsigned long bytesWritten = 0;
234
235   // outer loop: starting with the first write vector, as long as there is
236   // at least one vector left to feed writev(), do so
237   //
238   for(int curIov = 0; curIov < iovcnt; ) {
239
240     // inner loop: feed writev() allowing for interrupted system call
241     do {
242       status = writev(
243                 fd,
244                 &iov[curIov],
245                 (iovcnt-curIov) > IOV_MAX ? IOV_MAX : (iovcnt-curIov));
246     } while (status < 0 && errno == EINTR);
247
248     if (status == (ssize_t)-1)          // true error from writev??
249       return((unsigned long)-1);        // yes: bail at this point to caller
250     bytesWritten += status;             // bump # bytes written count
251
252     // must now "walk through" the io vector until we are up the to point
253     // indicated by the number of bytes written by writev() - any leftover
254     // in status indicates a partial write of a vector
255     //
256     while ((status > 0) && (curIov < iovcnt) && (iov[curIov].iov_len <= status)) {
257       status -= iov[curIov++].iov_len;
258     }
259
260     // Check to see if we have reached the end of the io vector array; also
261     // check to see if more bytes were written than called for; as crazy as
262     // this sounds, in at least one instance when we finish spinning through
263     // the io vectors we still had bytes left that had been written but not
264     // accounted for in the io vectors (status > 0 && curIov >= iovcnt)
265     //
266     if (curIov >= iovcnt) {             // out of IO vectors?
267       if (status > 0) {                 // yes: all data accounted for?
268         DtMailEnv error;                // NO:: log error condition
269         error.logError(
270                 DTM_TRUE,
271                 "SafeWritev: writev(): too many bytes written (%d/%d)\n",
272                 status, bytesWritten);
273       }
274       continue;                         // continue and let for loop exit
275     }
276     
277     // Check for a partial write: if the current vector contains more data
278     // than what has been written, writev() bailed in the middle of writing
279     // a vector - adjust the vector and and feed it back to writev() again
280     // OTHERWISE writev() ended with the current vector so move on to the next
281     //
282     if (iov[curIov].iov_len == status)  // full write of this vector?
283       curIov++;                         // yes: move on to the next vector
284     else if (status != 0) {             // no: adjust this vector and retry
285       iov[curIov].iov_len -= status;
286       iov[curIov].iov_base = IOVEC_IOVBASE_INCREMENTOR((&iov[curIov]), status);
287     }
288   }
289   return(bytesWritten);
290 }
291
292 #define SWS_BUFFERSIZE 1024
293 ssize_t
294 SafeWriteStrip(int fd, const void * buf, size_t bytes)
295 {
296     ssize_t status = 0;
297     int i, j;
298     char *ptr = (char*)buf, *writebuf; 
299     
300     // bug 5856: don't write out control M
301     // make a finite size buffer for writing
302     writebuf = (char*) malloc(bytes < SWS_BUFFERSIZE ? bytes : SWS_BUFFERSIZE); 
303
304     for (i = 0, j = 0; i < bytes; i++, ptr++) {
305         if (*ptr == '\r' && *(ptr+1) == '\n')
306                 continue;
307         writebuf[j++] = *ptr;
308         if (j == SWS_BUFFERSIZE || i == (bytes-1)) {
309                 do {
310                         status = write(fd, writebuf, j);
311                 } while(status < 0 && errno == EINTR);
312                 j = 0;
313         }
314     }
315     free(writebuf);
316     
317     return(status);
318 }
319
320 int
321 SafeStat(const char * path, struct stat * buf)
322 {
323     int status;
324     do {
325         status = stat(path, buf);
326     } while (status < 0 && errno == EINTR);
327
328     return(status);
329 }
330
331 int
332 SafeFchown(int fd, uid_t owner, gid_t group)
333 {
334   int status;
335   do {
336     status = fchown(fd, owner, group);
337   } while (status < 0 && errno == EINTR);
338
339   return(status);
340 }
341
342 int
343 SafeLStat(const char * path, struct stat * buf)
344 {
345     int status;
346     do {
347         status = lstat(path, buf);
348     } while (status < 0 && errno == EINTR);
349
350     return(status);
351 }
352
353 int
354 SafeFStat(int fd, struct stat * buf)
355 {
356     int status;
357     do {
358         status = fstat(fd, buf);
359     } while (status < 0 && errno == EINTR);
360
361     return(status);
362 }
363
364 // SafeGuaranteedStat - return stat info for object given path name
365 // If NFS attribute caching is enabled (which is the default), a
366 // stat/fstat of a NFS file may not return the correct true size of the
367 // mailbox if it has been appended to since the last time it was read.
368 // To get around this problem, this function will perform a open(),
369 // read() of 1 byte, fstat(), close() which will force the attributes
370 // for the named file to be retrieved directly from the server.
371 // 
372 int
373 SafeGuaranteedStat(const char * path, struct stat * buf)
374 {
375   int saveErrno;
376
377 #ifndef O_RSYNC
378   int tempFd = SafeOpen(path, O_RDONLY|O_SYNC);
379 #else
380   int tempFd = SafeOpen(path, O_RDONLY|O_RSYNC|O_SYNC);
381 #endif /* O_RSYNC */
382
383   if (tempFd == -1) {
384     return(-1);
385   }
386
387   char tempBuf;  
388   if (SafeRead(tempFd, &tempBuf, 1) == -1) {
389     saveErrno = errno;
390     (void) SafeClose(tempFd);
391     errno = saveErrno;
392     return(-1);
393   }
394
395   if (SafeFStat(tempFd, buf) == -1) {
396     saveErrno = errno;
397     (void) SafeClose(tempFd);
398     errno = saveErrno;
399     return(-1);
400   }
401
402   (void) SafeClose(tempFd);
403
404   return(0);
405 }
406
407 int
408 SafeTruncate(const char * path, off_t len)
409 {
410     int status;
411     do {
412         status = truncate((char *)path, len);   // The cast is for AIX
413     } while (status < 0 && errno == EINTR);
414
415     return(status);
416 }
417
418 int
419 SafeFTruncate(int fd, off_t len)
420 {
421     int status;
422     do {
423         status = ftruncate(fd, len);
424     } while (status < 0 && errno == EINTR);
425
426     return(status);
427 }
428
429 int
430 SafeAccess(const char * path, int amode)
431 {
432     int status;
433     do {
434         status = access(path, amode);
435     } while (status < 0 && errno == EINTR);
436
437     return(status);
438 }
439
440 #if defined(sun)
441 #define LOCKF_SIZE_TYPE long
442 #else
443 #define LOCKF_SIZE_TYPE off_t
444 #endif
445
446 int
447 SafeLockf(int fd, int func, long size)
448 {
449     int status;
450     do {
451         status = lockf(fd, func, (LOCKF_SIZE_TYPE) size);
452     } while (status < 0 && errno == EINTR);
453
454     return(status);
455 }
456
457 int
458 SafeFChmod(int fd, mode_t mode)
459 {
460     int status;
461     do {
462         status = fchmod(fd, mode);
463     } while (status < 0 && errno == EINTR);
464
465     return(status);
466 }
467
468 int
469 SafeDup2(int fd1, int fd2)
470 {
471     int status;
472     do {
473         status = dup2(fd1, fd2);
474     } while (status < 0 && errno == EINTR);
475
476     return(status);
477 }
478
479 int
480 SafeExecvp(const char * file, char *const *argv)
481 {
482     int status;
483     do {
484
485         status = execvp(file, (char * const *)argv);
486
487     } while (status < 0 && errno == EINTR);
488
489     return(status);
490 }
491
492 int
493 SafeWaitpid(pid_t proc, int * p_stat, int options)
494 {
495     pid_t status;
496     do {
497         status = waitpid(proc, p_stat, options);
498     } while (status < 0 && errno == EINTR);
499
500     return((int)status);
501 }
502
503 int
504 SafeWait(int * p_stat)
505 {
506     pid_t status;
507     do {
508         status = wait(p_stat);
509     } while (status < 0 && errno == EINTR);
510
511     return((int)status);
512 }
513
514 int
515 SafeUTime(const char * path, utimbuf * ntime)
516 {
517     int status;
518     do {
519         status = utime(path, ntime);
520     } while (status < 0 && errno == EINTR);
521
522     return(status);
523 }
524
525 void
526 SafePathIsAccessible(DtMailEnv &error, const char *path)
527 {
528     int status;
529
530     status = SafeAccess(path, F_OK);
531     if (-1 == status)
532     {
533         if (EACCES == errno)
534           error.vSetError(DTME_PathElementPermissions, DTM_FALSE, NULL, path);
535         else if (ENOTDIR == errno)
536           error.vSetError(DTME_PathElementNotDirectory, DTM_FALSE, NULL, path);
537         else if (ENOENT == errno)
538         {
539             char *s, *t;
540
541             t = strdup(path);
542             s = strrchr(t, '/');
543             if (s && s != t)
544             {
545                 *s = '\0';
546                 status = SafeAccess(t, F_OK);
547                 if (-1 == status)
548                   error.vSetError(
549                                 DTME_PathElementDoesNotExist,
550                                 DTM_FALSE, NULL,
551                                 path);
552             }
553         }
554     }
555 }
556
557 #if defined(POSIX_THREADS)
558 static void * time_mutex = NULL;
559 #endif
560
561 void
562 SafeCtime(const time_t *clock, char * buf, int buflen)
563 {
564   _Xctimeparams ctime_buf;
565   char *result;
566
567   memset((void*) &ctime_buf, 0, sizeof(_Xctimeparams));
568   result = _XCtime(clock, ctime_buf);
569   if (result)
570     strncpy(buf, result, buflen);
571   else
572     *buf = '\0';
573 }
574
575 void
576 SafeLocaltime(const time_t *clock, tm & result)
577 {
578   struct tm     *time_ptr;
579   _Xltimeparams localtime_buf;
580
581   memset((void*) &localtime_buf, 0, sizeof(_Xltimeparams));
582   time_ptr = _XLocaltime(clock, localtime_buf);
583   result = *time_ptr;
584 }
585
586 time_t
587 SafeMktime(tm * timeptr)
588 {
589 #if defined(POSIX_THREADS)
590
591     if (!time_mutex) {
592         time_mutex = MutexInit();
593     }
594
595     MutexLock lock_scope(time_mutex);
596 #endif
597
598     return(mktime(timeptr));
599 }
600
601 size_t
602 SafeStrftime(char * buf, size_t buf_size,
603              const char * format, const tm * timeptr)
604 {
605 #if defined(POSIX_THREADS)
606
607     if (!time_mutex) {
608         time_mutex = MutexInit();
609     }
610
611     MutexLock lock_scope(time_mutex);
612 #endif
613
614     return(strftime(buf, buf_size, format, timeptr));
615 }
616
617 #define  SockINTERNAL_BUFSIZE   2048
618
619 void *SockOpen(char *host, int clientPort, char **errorstring)
620 {
621     int sockfd;
622     unsigned long inaddr;
623     struct sockaddr_in ad;
624     struct hostent *hp;
625     DtMailEnv error;
626     char *errorfmt = NULL;
627
628     memset(&ad, 0, sizeof(ad));
629     ad.sin_family = AF_INET;
630
631     inaddr = inet_addr(host);
632     if (inaddr != -1)
633       memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
634     else
635     {
636         hp = gethostbyname(host);
637         if (hp == NULL)
638         {
639             if (NULL != errorstring)
640             {
641                 errorfmt = DtMailEnv::getMessageText(
642                                                 SockErrorSet, 2,
643                                                 "Unknown host:  %s");
644                 if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
645                 sprintf(*errorstring, errorfmt, host);
646             }
647             return (FILE*) NULL;
648         }
649         memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
650     }
651     ad.sin_port = htons(clientPort);
652     
653     sockfd = socket(AF_INET, SOCK_STREAM, 0);
654     if (sockfd < 0)
655     {
656         if (NULL != errorstring)
657         {
658             errorfmt = DtMailEnv::getMessageText(
659                                                 SockErrorSet, 3,
660                                                 "Error creating socket: %s");
661             if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
662             sprintf(*errorstring, errorfmt, error.errnoMessage());
663         }
664         return (FILE*) NULL;
665     }
666     if (connect(sockfd, (struct sockaddr *) &ad, sizeof(ad)) < 0)
667     {
668         if (NULL != errorstring)
669         {
670             errorfmt = DtMailEnv::getMessageText(
671                                         SockErrorSet, 3,
672                                         "Error connecting to socket:  %s");
673             if (NULL == *errorstring) *errorstring = (char*) malloc(BUFSIZ);
674             sprintf(*errorstring, errorfmt, error.errnoMessage());
675         }
676         close(sockfd);
677         return (FILE*) NULL;
678     }
679
680 #if defined(USE_SOCKSTREAM)
681     FILE *sockfp = fdopen(sockfd, "r+");
682     setvbuf(sockfp, NULL, _IONBF, SockINTERNAL_BUFSIZE);
683     return (void*) sockfp;
684 #else
685     return (void*) sockfd;
686 #endif
687 }
688
689 int SockPrintf(void *sockfp, char* format, ...)
690 {
691     va_list ap;
692     char *buf = new char[8192];
693     int i;
694
695     va_start(ap, format);
696     vsprintf(buf, format, ap);
697     va_end(ap);
698     i = SockWrite(buf, 1, strlen(buf), sockfp);
699     delete [] buf;
700     return i;
701 }
702
703 char *SockGets(char *buf, int len, void *sockfp)
704 {
705 #if defined(USE_SOCKSTREAM)
706     char *in = fgets(buf, len, (FILE*) sockfp);
707     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
708     return in;
709 #else
710     size_t n;
711     char *bufp;
712     
713     n = 0;
714     bufp = buf-1;
715     do
716     {
717         bufp++;
718         read((int) sockfp, (void*) bufp, 1);
719         n++;
720     } while (*bufp != '\n');
721     *(bufp+1) = '\0';
722     return buf;
723 #endif
724 }
725
726 int SockRead(char *buf, int size, int len, void *sockfp)
727 {
728 #if defined(USE_SOCKSTREAM)
729     int n = fread(buf, size, len, (FILE*) sockfp);
730     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
731 #else
732     int n = (int) read((int) sockfp, (void*) buf, (size_t) size * len);
733 #endif
734     return n;
735 }
736
737 int SockWrite(char *buf, int size, int len, void *sockfp)
738 {
739     int n;
740
741 #if defined(USE_SOCKSTREAM)
742     n = fwrite(buf, size, len, (FILE*) sockfp);
743     fseek((FILE*) sockfp, 0L, SEEK_CUR);        /* required by POSIX */
744 #else
745     n = write((int) sockfp, buf, size * len);
746 #endif
747
748     return n;
749 }
750
751 void SockClose(void *sockfp)
752 {
753 #if defined(USE_SOCKSTREAM)
754     fclose((FILE*) sockfp);
755 #else
756     close((int) sockfp);
757 #endif
758 }
759
760 void
761 GetGroupName(char * grp_name)
762 {
763     struct group *grp;
764     _Xgetgrparams grp_buf;
765
766     memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
767     grp = _XGetgrgid(getegid(), grp_buf);
768
769     if (grp) {
770         strcpy(grp_name, grp->gr_name);
771     }
772     else {
773         strcpy(grp_name, "UNKNOWN_GROUP");
774     }
775
776 }
777
778 gid_t
779 GetIdForGroupName(char * grp_name)
780 {
781   assert(grp_name != NULL);
782   struct group *grp;
783   _Xgetgrparams grp_buf;
784   
785   memset((void*) &grp_buf, 0, sizeof(_Xgetgrparams));
786   grp = _XGetgrnam(grp_name, grp_buf);
787     
788   return(grp ? grp->gr_gid : (gid_t)-1);
789 }
790
791 void
792 GetPasswordEntry(passwd & result)
793 {
794   static struct passwd passwordEntry;
795   static int oneTimeFlag = 0;
796
797   if (!oneTimeFlag) {
798     _Xgetpwparams pw_buf;
799     struct passwd *tresult;
800
801     memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
802 #if defined(_AIX)
803     _Xos_processLock;
804     tresult = getpwuid(getuid());
805     _Xos_processUnlock;
806 #else
807     tresult = _XGetpwuid(getuid(), pw_buf);
808 #endif
809
810     assert(tresult != NULL);
811     memcpy(&passwordEntry, tresult, sizeof(struct passwd));
812     passwordEntry.pw_name = strdup(passwordEntry.pw_name);
813     passwordEntry.pw_passwd = strdup(passwordEntry.pw_passwd);
814 #if !defined(_AIX) && !defined(__linux__) && !defined(CSRG_BASED)
815     passwordEntry.pw_age = strdup(passwordEntry.pw_age);
816     passwordEntry.pw_comment = strdup(passwordEntry.pw_comment);
817 #endif
818     passwordEntry.pw_gecos = strdup(passwordEntry.pw_gecos);
819     passwordEntry.pw_dir = strdup(passwordEntry.pw_dir);
820     passwordEntry.pw_shell = strdup(passwordEntry.pw_shell);
821     oneTimeFlag++;
822   }
823
824   memcpy(&result, &passwordEntry, sizeof(struct passwd));
825   return;
826 }
827 #if defined(MAILGROUP_REQUIRED)
828 int isSetMailGidNeeded(const char * mailboxPath)
829 {
830
831   assert(mailboxPath);
832
833     char inbox_path[1024];
834     char mbox_path[1024];
835     struct passwd *pw;
836     struct stat buf;
837     struct stat buf1;
838     _Xgetpwparams pw_buf;
839
840     memset((void*) &pw_buf, 0, sizeof(_Xgetpwparams));
841     pw = _XGetpwuid(getuid(), pw_buf);
842
843     // construct the lockfile name for the user.
844     char *lock_file = (char *)calloc(1,strlen(pw->pw_name) + 6);
845     strcpy(lock_file,pw->pw_name);
846     strcat(lock_file,".lock");
847
848     // parse the mailfolder name from the path
849     char *p = strrchr(mailboxPath,'/');
850     int len = (NULL!=0) ? strlen(mailboxPath)-strlen(p) : strlen(mailboxPath);
851     char *str = (char *) calloc(1, len+1);
852     strncpy(str, mailboxPath, len);
853     str[len] = '\0';
854     
855     stat(str,&buf);
856
857     // Default or system mailbox dir name.
858     strcpy(inbox_path, "/var/spool/mail");
859     stat(inbox_path,&buf1);
860     free(str);
861
862     if( ( (buf.st_dev == buf1.st_dev) && (buf.st_ino == buf1.st_ino) ) )
863     {
864         if( !strcmp((p+1),pw->pw_name) || !strcmp((p+1),lock_file) )
865         {  
866            if( access(mailboxPath,R_OK) == -1 )
867            {
868              free(lock_file);
869              return (1);
870            }
871         }
872         free(lock_file);
873         return ( 0 ); 
874     }
875     else
876     {
877         free(lock_file);
878         return ( 1 ); 
879     }
880 }
881 #endif
882
883 #ifdef _AIX
884 /*
885  * NAME: get_stat
886  *
887  * FUNCTION:
888  *      gather mount status for all virtual mounts for this host.
889  *
890  * EXECUTION ENVIRONMENT: Part of user command.
891  *
892  * ON ENTRY:
893  *      vmountpp        pointer to a buffer in which to put mount info
894  *
895  * NOTES:
896  *      get_stat() was lifted and slightly modified from
897  *      AIX Version 3 df.c.
898  *
899  * RETURNS:
900  *      < 0     error in mntctl()
901  *      > 0     for number of struct vmounts (mount points) in
902  *              buffer which is pointed to by pointer left at
903  *              *vmountpp.
904  */
905 int get_stat(
906 struct vmount   **vmountpp)     /* place to tell where buffer is */
907 {
908   size_t                size;
909   register struct vmount        *vm;
910   int                   nmounts;
911   int                   count;
912
913   size = BUFSIZ;                /* initial default size */
914   count = 10;                   /* don't try forever    */
915
916   while (count--) {             /* don't try it forever */
917         if ((vm = (struct vmount*) malloc(size)) == NULL) {
918                 return(-1);
919         }
920
921 /*
922  * perform the QUERY mntctl - if it returns > 0, that is the
923  * number of vmount structures in the buffer.  If it returns
924  * -1, an error occurred.  If it returned 0, then look in
925  * first word of buffer for needed size.
926  */
927         if ((nmounts = mntctl(MCTL_QUERY, size, (caddr_t)vm)) > 0) {
928                 *vmountpp = vm;         /* OK, got it, now return */
929                 return(nmounts);
930         } else {
931                 if (nmounts == 0) {
932                         size = *(int *)vm; /* the buffer wasn't big enough */
933                         free((void *)vm);   /* get required buffer size     */
934                 } else {
935                         free((void *)vm);/* some other kind of error occurred*/
936                         return(-1);
937                 }
938         }
939   }
940   return(-1);
941 }
942
943 /*
944  * NAME: get_vmount
945  *
946  * FUNCTION:
947  *        Determines, via the filesystems vmount structures,
948  *        the vmount id of the the filesystem id provided as
949  *        an argument (enables ultimate access to the actual
950  *        name of the filesystem).
951  *
952  * EXECUTION ENVIRONMENT: Part of user command.
953  *
954  * RETURNS:
955  *      ptr to structure with vmount id of filesystem or NULL
956  */
957 struct vmount *get_vmount(fsid_t *fsid)
958 {
959     struct vmount *inu_vmount_p=NULL;
960     int inu_vmount_num;
961     register struct vmount *vm;
962     int nmount;
963
964     /* make sure we have all the virtual mount status of this host */
965     if(inu_vmount_p == NULL)
966         inu_vmount_num = get_stat(&inu_vmount_p);
967
968     /* get the number of struct vmount in the vmount buffer */
969     nmount = inu_vmount_num;
970
971     /* go thru all the structures in the vmount buffer */
972     for (vm = inu_vmount_p; nmount; nmount--,
973             vm = (struct vmount *)((char *)vm + vm->vmt_length)) {
974          if(( vm->vmt_fsid.fsid_dev == fsid->fsid_dev ) &&
975             ( vm->vmt_fsid.fsid_type == fsid->fsid_type ))
976              return(vm);
977     }
978     return((struct vmount *)NULL);
979 }
980 #endif /* _AIX */
981
982 int FileSystemSpace(const char *file_path, size_t bytes, char **fsname)
983 {
984     int                 fserror=FALSE;
985     struct stat         stat_buf;
986     size_t              req_space = 0;
987 #if !defined(__linux__)
988     struct statvfs      statvfs_buf;
989 #endif
990
991     if (stat(file_path,&stat_buf) < 0) return 0;
992 #if !defined(__linux__)
993     if (statvfs(file_path,&statvfs_buf) < 0) return 0;
994 #endif
995
996 #ifdef _AIX
997     struct statfs       statfs_buf;
998
999     if (statfs(file_path,&statfs_buf) < 0) return 0;
1000     if (statfs_buf.f_vfstype == MNT_NFS)
1001     {
1002         struct vmount *vm;
1003         vm = get_vmount(&(statfs_buf.f_fsid));
1004         strcpy (statfs_buf.f_fname, vmt2dataptr (vm, VMT_STUB));
1005     }
1006 #endif /* _AIX */
1007
1008     if (bytes != 0)
1009     {
1010
1011         // The following code became redundant as the writeMailBox method now
1012         // checks for No space from the SafeWritev call.
1013 #if 0
1014         // CDExc20314
1015         // This check does not work (HP, IBM, Sun return -1; DEC returns 0)
1016         // Since the calling code has already created the file and is only
1017         // check that there is enough space, we don't need to check that
1018         // there are enough inodes.
1019         //
1020         // special case where the filesystem is out of inodes.
1021         if(statvfs_buf.f_ffree < 10) fserror = TRUE; 
1022 #endif
1023
1024         if (! fserror)
1025         {
1026             req_space = (size_t) ((bytes > stat_buf.st_size) ?
1027                                   (bytes-stat_buf.st_size) :
1028                                   0);
1029 #if !defined(__linux__)
1030             if ( (statvfs_buf.f_bfree*statvfs_buf.f_bsize) >
1031                  (req_space + statvfs_buf.f_bsize) )
1032               return 1;
1033             else
1034               fserror = TRUE;
1035 #endif
1036         }
1037     }
1038     else fserror = TRUE;
1039
1040     if (fserror)
1041     {
1042 #ifdef _AIX
1043         *fsname = (char*) calloc(1, strlen(statfs_buf.f_fname)+1);
1044         strcpy (*fsname, statfs_buf.f_fname);
1045 #else
1046         *fsname = (char*) calloc(1, strlen(file_path)+1);
1047         strcpy (*fsname, file_path);
1048 #endif
1049         return 0;
1050     }
1051     return 1;
1052 }