lib/replace/replace.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    replacement routines for broken systems
00004    Copyright (C) Andrew Tridgell 1992-1998
00005 
00006      ** NOTE! The following LGPL license applies to the replace
00007      ** library. This does NOT imply that all of Samba is released
00008      ** under the LGPL
00009    
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Lesser General Public
00012    License as published by the Free Software Foundation; either
00013    version 2 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Lesser General Public License for more details.
00019 
00020    You should have received a copy of the GNU Lesser General Public
00021    License along with this library; if not, write to the Free Software
00022    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 
00025 #include "replace.h"
00026 
00027 #include "system/filesys.h"
00028 #include "system/time.h"
00029 #include "system/passwd.h"
00030 #include "system/syslog.h"
00031 #include "system/network.h"
00032 #include "system/locale.h"
00033 #include "system/wait.h"
00034 
00035 void replace_dummy(void);
00036 void replace_dummy(void) {}
00037 
00038 #ifndef HAVE_FTRUNCATE
00039  /*******************************************************************
00040 ftruncate for operating systems that don't have it
00041 ********************************************************************/
00042 int rep_ftruncate(int f, off_t l)
00043 {
00044 #ifdef HAVE_CHSIZE
00045       return chsize(f,l);
00046 #elif defined(F_FREESP)
00047       struct  flock   fl;
00048 
00049       fl.l_whence = 0;
00050       fl.l_len = 0;
00051       fl.l_start = l;
00052       fl.l_type = F_WRLCK;
00053       return fcntl(f, F_FREESP, &fl);
00054 #else
00055 #error "you must have a ftruncate function"
00056 #endif
00057 }
00058 #endif /* HAVE_FTRUNCATE */
00059 
00060 
00061 #ifndef HAVE_STRLCPY
00062 /* like strncpy but does not 0 fill the buffer and always null 
00063    terminates. bufsize is the size of the destination buffer */
00064 size_t rep_strlcpy(char *d, const char *s, size_t bufsize)
00065 {
00066         size_t len = strlen(s);
00067         size_t ret = len;
00068         if (bufsize <= 0) return 0;
00069         if (len >= bufsize) len = bufsize-1;
00070         memcpy(d, s, len);
00071         d[len] = 0;
00072         return ret;
00073 }
00074 #endif
00075 
00076 #ifndef HAVE_STRLCAT
00077 /* like strncat but does not 0 fill the buffer and always null 
00078    terminates. bufsize is the length of the buffer, which should
00079    be one more than the maximum resulting string length */
00080 size_t rep_strlcat(char *d, const char *s, size_t bufsize)
00081 {
00082         size_t len1 = strlen(d);
00083         size_t len2 = strlen(s);
00084         size_t ret = len1 + len2;
00085 
00086         if (len1+len2 >= bufsize) {
00087                 if (bufsize < (len1+1)) {
00088                         return ret;
00089                 }
00090                 len2 = bufsize - (len1+1);
00091         }
00092         if (len2 > 0) {
00093                 memcpy(d+len1, s, len2);
00094                 d[len1+len2] = 0;
00095         }
00096         return ret;
00097 }
00098 #endif
00099 
00100 #ifndef HAVE_MKTIME
00101 /*******************************************************************
00102 a mktime() replacement for those who don't have it - contributed by 
00103 C.A. Lademann <cal@zls.com>
00104 Corrections by richard.kettlewell@kewill.com
00105 ********************************************************************/
00106 
00107 #define  MINUTE  60
00108 #define  HOUR    60*MINUTE
00109 #define  DAY             24*HOUR
00110 #define  YEAR    365*DAY
00111 time_t rep_mktime(struct tm *t)
00112 {
00113   struct tm       *u;
00114   time_t  epoch = 0;
00115   int n;
00116   int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
00117   y, m, i;
00118 
00119   if(t->tm_year < 70)
00120     return((time_t)-1);
00121 
00122   n = t->tm_year + 1900 - 1;
00123   epoch = (t->tm_year - 70) * YEAR + 
00124     ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY;
00125 
00126   y = t->tm_year + 1900;
00127   m = 0;
00128 
00129   for(i = 0; i < t->tm_mon; i++) {
00130     epoch += mon [m] * DAY;
00131     if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
00132       epoch += DAY;
00133     
00134     if(++m > 11) {
00135       m = 0;
00136       y++;
00137     }
00138   }
00139 
00140   epoch += (t->tm_mday - 1) * DAY;
00141   epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
00142   
00143   if((u = localtime(&epoch)) != NULL) {
00144     t->tm_sec = u->tm_sec;
00145     t->tm_min = u->tm_min;
00146     t->tm_hour = u->tm_hour;
00147     t->tm_mday = u->tm_mday;
00148     t->tm_mon = u->tm_mon;
00149     t->tm_year = u->tm_year;
00150     t->tm_wday = u->tm_wday;
00151     t->tm_yday = u->tm_yday;
00152     t->tm_isdst = u->tm_isdst;
00153   }
00154 
00155   return(epoch);
00156 }
00157 #endif /* !HAVE_MKTIME */
00158 
00159 
00160 #ifndef HAVE_INITGROUPS
00161 /****************************************************************************
00162  some systems don't have an initgroups call 
00163 ****************************************************************************/
00164 int rep_initgroups(char *name, gid_t id)
00165 {
00166 #ifndef HAVE_SETGROUPS
00167         /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
00168         errno = ENOSYS;
00169         return -1;
00170 #else /* HAVE_SETGROUPS */
00171 
00172 #include <grp.h>
00173 
00174         gid_t *grouplst = NULL;
00175         int max_gr = 32;
00176         int ret;
00177         int    i,j;
00178         struct group *g;
00179         char   *gr;
00180         
00181         if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) {
00182                 errno = ENOMEM;
00183                 return -1;
00184         }
00185 
00186         grouplst[0] = id;
00187         i = 1;
00188         while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) {
00189                 if (g->gr_gid == id)
00190                         continue;
00191                 j = 0;
00192                 gr = g->gr_mem[0];
00193                 while (gr && (*gr != (char)NULL)) {
00194                         if (strcmp(name,gr) == 0) {
00195                                 grouplst[i] = g->gr_gid;
00196                                 i++;
00197                                 gr = (char *)NULL;
00198                                 break;
00199                         }
00200                         gr = g->gr_mem[++j];
00201                 }
00202         }
00203         endgrent();
00204         ret = setgroups(i, grouplst);
00205         free(grouplst);
00206         return ret;
00207 #endif /* HAVE_SETGROUPS */
00208 }
00209 #endif /* HAVE_INITGROUPS */
00210 
00211 
00212 #if (defined(SecureWare) && defined(SCO))
00213 /* This is needed due to needing the nap() function but we don't want
00214    to include the Xenix libraries since that will break other things...
00215    BTW: system call # 0x0c28 is the same as calling nap() */
00216 long nap(long milliseconds) {
00217          return syscall(0x0c28, milliseconds);
00218  }
00219 #endif
00220 
00221 
00222 #ifndef HAVE_MEMMOVE
00223 /*******************************************************************
00224 safely copies memory, ensuring no overlap problems.
00225 this is only used if the machine does not have it's own memmove().
00226 this is not the fastest algorithm in town, but it will do for our
00227 needs.
00228 ********************************************************************/
00229 void *rep_memmove(void *dest,const void *src,int size)
00230 {
00231         unsigned long d,s;
00232         int i;
00233         if (dest==src || !size) return(dest);
00234 
00235         d = (unsigned long)dest;
00236         s = (unsigned long)src;
00237 
00238         if ((d >= (s+size)) || (s >= (d+size))) {
00239                 /* no overlap */
00240                 memcpy(dest,src,size);
00241                 return(dest);
00242         }
00243 
00244         if (d < s) {
00245                 /* we can forward copy */
00246                 if (s-d >= sizeof(int) && 
00247                     !(s%sizeof(int)) && 
00248                     !(d%sizeof(int)) && 
00249                     !(size%sizeof(int))) {
00250                         /* do it all as words */
00251                         int *idest = (int *)dest;
00252                         int *isrc = (int *)src;
00253                         size /= sizeof(int);
00254                         for (i=0;i<size;i++) idest[i] = isrc[i];
00255                 } else {
00256                         /* simplest */
00257                         char *cdest = (char *)dest;
00258                         char *csrc = (char *)src;
00259                         for (i=0;i<size;i++) cdest[i] = csrc[i];
00260                 }
00261         } else {
00262                 /* must backward copy */
00263                 if (d-s >= sizeof(int) && 
00264                     !(s%sizeof(int)) && 
00265                     !(d%sizeof(int)) && 
00266                     !(size%sizeof(int))) {
00267                         /* do it all as words */
00268                         int *idest = (int *)dest;
00269                         int *isrc = (int *)src;
00270                         size /= sizeof(int);
00271                         for (i=size-1;i>=0;i--) idest[i] = isrc[i];
00272                 } else {
00273                         /* simplest */
00274                         char *cdest = (char *)dest;
00275                         char *csrc = (char *)src;
00276                         for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
00277                 }      
00278         }
00279         return(dest);
00280 }
00281 #endif /* HAVE_MEMMOVE */
00282 
00283 #ifndef HAVE_STRDUP
00284 /****************************************************************************
00285 duplicate a string
00286 ****************************************************************************/
00287 char *rep_strdup(const char *s)
00288 {
00289         size_t len;
00290         char *ret;
00291 
00292         if (!s) return(NULL);
00293 
00294         len = strlen(s)+1;
00295         ret = (char *)malloc(len);
00296         if (!ret) return(NULL);
00297         memcpy(ret,s,len);
00298         return(ret);
00299 }
00300 #endif /* HAVE_STRDUP */
00301 
00302 #ifndef WITH_PTHREADS
00303 /* REWRITE: not thread safe */
00304 #ifdef REPLACE_INET_NTOA
00305 char *rep_inet_ntoa(struct in_addr ip)
00306 {
00307         uint8_t *p = (uint8_t *)&ip.s_addr;
00308         static char buf[18];
00309         slprintf(buf, 17, "%d.%d.%d.%d", 
00310                  (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
00311         return buf;
00312 }
00313 #endif /* REPLACE_INET_NTOA */
00314 #endif
00315 
00316 #ifndef HAVE_SETLINEBUF
00317 void rep_setlinebuf(FILE *stream)
00318 {
00319         setvbuf(stream, (char *)NULL, _IOLBF, 0);
00320 }
00321 #endif /* HAVE_SETLINEBUF */
00322 
00323 #ifndef HAVE_VSYSLOG
00324 #ifdef HAVE_SYSLOG
00325 void rep_vsyslog (int facility_priority, const char *format, va_list arglist)
00326 {
00327         char *msg = NULL;
00328         vasprintf(&msg, format, arglist);
00329         if (!msg)
00330                 return;
00331         syslog(facility_priority, "%s", msg);
00332         free(msg);
00333 }
00334 #endif /* HAVE_SYSLOG */
00335 #endif /* HAVE_VSYSLOG */
00336 
00337 #ifndef HAVE_STRNLEN
00338 /**
00339  Some platforms don't have strnlen
00340 **/
00341  size_t rep_strnlen(const char *s, size_t max)
00342 {
00343         size_t len;
00344   
00345         for (len = 0; len < max; len++) {
00346                 if (s[len] == '\0') {
00347                         break;
00348                 }
00349         }
00350         return len;  
00351 }
00352 #endif
00353   
00354 #ifndef HAVE_STRNDUP
00355 /**
00356  Some platforms don't have strndup.
00357 **/
00358 char *rep_strndup(const char *s, size_t n)
00359 {
00360         char *ret;
00361         
00362         n = strnlen(s, n);
00363         ret = malloc(n+1);
00364         if (!ret)
00365                 return NULL;
00366         memcpy(ret, s, n);
00367         ret[n] = 0;
00368 
00369         return ret;
00370 }
00371 #endif
00372 
00373 #ifndef HAVE_WAITPID
00374 int rep_waitpid(pid_t pid,int *status,int options)
00375 {
00376   return wait4(pid, status, options, NULL);
00377 }
00378 #endif
00379 
00380 #ifndef HAVE_SETEUID
00381 int rep_seteuid(uid_t euid)
00382 {
00383 #ifdef HAVE_SETRESUID
00384         return setresuid(-1, euid, -1);
00385 #else
00386 #  error "You need a seteuid function"
00387 #endif
00388 }
00389 #endif
00390 
00391 #ifndef HAVE_SETEGID
00392 int rep_setegid(gid_t egid)
00393 {
00394 #ifdef HAVE_SETRESGID
00395         return setresgid(-1, egid, -1);
00396 #else
00397 #  error "You need a setegid function"
00398 #endif
00399 }
00400 #endif
00401 
00402 /*******************************************************************
00403 os/2 also doesn't have chroot
00404 ********************************************************************/
00405 #ifndef HAVE_CHROOT
00406 int rep_chroot(const char *dname)
00407 {
00408         errno = ENOSYS;
00409         return -1;
00410 }
00411 #endif
00412 
00413 /*****************************************************************
00414  Possibly replace mkstemp if it is broken.
00415 *****************************************************************/  
00416 
00417 #ifndef HAVE_SECURE_MKSTEMP
00418 int rep_mkstemp(char *template)
00419 {
00420         /* have a reasonable go at emulating it. Hope that
00421            the system mktemp() isn't completly hopeless */
00422         char *p = mktemp(template);
00423         if (!p)
00424                 return -1;
00425         return open(p, O_CREAT|O_EXCL|O_RDWR, 0600);
00426 }
00427 #endif
00428 
00429 #ifndef HAVE_MKDTEMP
00430 char *rep_mkdtemp(char *template)
00431 {
00432         char *dname;
00433         
00434         if ((dname = mktemp(template))) {
00435                 if (mkdir(dname, 0700) >= 0) {
00436                         return dname;
00437                 }
00438         }
00439 
00440         return NULL;
00441 }
00442 #endif
00443 
00444 #ifndef HAVE_PREAD
00445 ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
00446 {
00447         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
00448                 return -1;
00449         }
00450         return read(__fd, __buf, __nbytes);
00451 }
00452 #endif
00453 
00454 #ifndef HAVE_PWRITE
00455 ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
00456 {
00457         if (lseek(__fd, __offset, SEEK_SET) != __offset) {
00458                 return -1;
00459         }
00460         return write(__fd, __buf, __nbytes);
00461 }
00462 #endif
00463 
00464 #ifndef HAVE_STRCASESTR
00465 char *rep_strcasestr(const char *haystack, const char *needle)
00466 {
00467         const char *s;
00468         size_t nlen = strlen(needle);
00469         for (s=haystack;*s;s++) {
00470                 if (toupper(*needle) == toupper(*s) &&
00471                     strncasecmp(s, needle, nlen) == 0) {
00472                         return (char *)((intptr_t)s);
00473                 }
00474         }
00475         return NULL;
00476 }
00477 #endif
00478 
00479 #ifndef HAVE_STRTOK_R
00480 /* based on GLIBC version, copyright Free Software Foundation */
00481 char *rep_strtok_r(char *s, const char *delim, char **save_ptr)
00482 {
00483         char *token;
00484 
00485         if (s == NULL) s = *save_ptr;
00486 
00487         s += strspn(s, delim);
00488         if (*s == '\0') {
00489                 *save_ptr = s;
00490                 return NULL;
00491         }
00492 
00493         token = s;
00494         s = strpbrk(token, delim);
00495         if (s == NULL) {
00496                 *save_ptr = token + strlen(token);
00497         } else {
00498                 *s = '\0';
00499                 *save_ptr = s + 1;
00500         }
00501 
00502         return token;
00503 }
00504 #endif
00505 
00506 #ifndef HAVE_STRTOLL
00507 long long int rep_strtoll(const char *str, char **endptr, int base)
00508 {
00509 #ifdef HAVE_STRTOQ
00510         return strtoq(str, endptr, base);
00511 #elif defined(HAVE___STRTOLL) 
00512         return __strtoll(str, endptr, base);
00513 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
00514         return (long long int) strtol(str, endptr, base);
00515 #else
00516 # error "You need a strtoll function"
00517 #endif
00518 }
00519 #endif
00520 
00521 
00522 #ifndef HAVE_STRTOULL
00523 unsigned long long int rep_strtoull(const char *str, char **endptr, int base)
00524 {
00525 #ifdef HAVE_STRTOUQ
00526         return strtouq(str, endptr, base);
00527 #elif defined(HAVE___STRTOULL) 
00528         return __strtoull(str, endptr, base);
00529 #elif SIZEOF_LONG == SIZEOF_LONG_LONG
00530         return (unsigned long long int) strtoul(str, endptr, base);
00531 #else
00532 # error "You need a strtoull function"
00533 #endif
00534 }
00535 #endif
00536 
00537 #ifndef HAVE_SETENV
00538 int rep_setenv(const char *name, const char *value, int overwrite) 
00539 {
00540         char *p;
00541         size_t l1, l2;
00542         int ret;
00543 
00544         if (!overwrite && getenv(name)) {
00545                 return 0;
00546         }
00547 
00548         l1 = strlen(name);
00549         l2 = strlen(value);
00550 
00551         p = malloc(l1+l2+2);
00552         if (p == NULL) {
00553                 return -1;
00554         }
00555         memcpy(p, name, l1);
00556         p[l1] = '=';
00557         memcpy(p+l1+1, value, l2);
00558         p[l1+l2+1] = 0;
00559 
00560         ret = putenv(p);
00561         if (ret != 0) {
00562                 free(p);
00563         }
00564 
00565         return ret;
00566 }
00567 #endif
00568 
00569 #ifndef HAVE_UNSETENV
00570 int rep_unsetenv(const char *name)
00571 {
00572         extern char **environ;
00573         size_t len = strlen(name);
00574         size_t i; 
00575         int found = 0;
00576 
00577         for (i=0; (environ && environ[i]); i++) {
00578                 if (found) {
00579                         environ[i-1] = environ[i];
00580                         continue;
00581                 }
00582 
00583                 if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') {
00584                         free(environ[i]);
00585                         environ[i] = NULL;
00586                         found = 1;
00587                         continue;
00588                 }
00589         }
00590 
00591         return 0;
00592 }
00593 #endif
00594 
00595 #ifndef HAVE_SOCKETPAIR
00596 int rep_socketpair(int d, int type, int protocol, int sv[2])
00597 {
00598         if (d != AF_UNIX) {
00599                 errno = EAFNOSUPPORT;
00600                 return -1;
00601         }
00602 
00603         if (protocol != 0) {
00604                 errno = EPROTONOSUPPORT;
00605                 return -1;
00606         }
00607 
00608         if (type != SOCK_STREAM) {
00609                 errno = EOPNOTSUPP;
00610                 return -1;
00611         }
00612 
00613         return pipe(sv);
00614 }
00615 #endif

Sambaに対してSat Aug 29 21:22:58 2009に生成されました。  doxygen 1.4.7