kern_utils.cc

00001 /* 
00002    EyeDB Object Database Management System
00003    Copyright (C) 1994-2008 SYSRA
00004    
00005    EyeDB is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009    
00010    EyeDB is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014    
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with this library; if not, write to the Free Software
00017    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA 
00018 */
00019 
00020 /*
00021   Author: Eric Viara <viara@sysra.com>
00022 */
00023 
00024 #include <eyedbconfig.h>
00025 
00026 #include <eyedblib/filelib.h>
00027 #include <eyedblib/rpc_lib.h>
00028 #include <kern_p.h>
00029 
00030 #define NEW_FILE_ACCESS
00031 
00032 #define ACCESS_FILE_FMT \
00033  "eyedbsm [pid = %d] running under user %s [uid = %d] : "
00034 
00035 namespace eyedbsm {
00036   const char *
00037   fileGet(const char *dbfile, const char ext[])
00038   {
00039 #define NN 4
00040     static char file[NN][512];
00041     static int n;
00042     char *p, *s;
00043 
00044     if (n == NN)
00045       n = 0;
00046     s = file[n++];
00047     strcpy(s, dbfile);
00048     if (p = strrchr(s, '.'))
00049       *p = 0;
00050     strcat(s, ext);
00051 
00052     return s;
00053   }
00054 
00055   const char *
00056   shmfileGet(const char *dbfile)
00057   {
00058     return fileGet(dbfile, shmext);
00059   }
00060 
00061   const char *
00062   dmpfileGet(const char *volfile)
00063   {
00064     return fileGet(volfile, dmpext);
00065   }
00066 
00067   const char *
00068   objmapfileGet(const char *dbfile)
00069   {
00070     return fileGet(dbfile, ompext);
00071   }
00072 
00073   Status
00074   checkVolMaxSize(unsigned int maxsize)
00075   {
00076     /*
00077       if (maxsize <= 0)
00078       return statusMake(INVALID_DATAFILEMAXSIZE,
00079       "negative volume file maximum size: `%d'",
00080       maxsize);
00081 
00082       if ((((unsigned long long)(maxsize)) * ONE_K) >
00083       (unsigned long long)ESM_MAX_DATAFILE_SIZE)
00084       return statusMake(SIZE_TOO_LARGE,
00085       "volume file maximum size is too large: "
00086       "`%llu bytes', maximum allowed size is `%llu'.",
00087       ((unsigned long long)(maxsize)) * ONE_K,
00088       ESM_MAX_DATAFILE_SIZE);
00089     */
00090 
00091     return Success;
00092   }
00093 
00094   Boolean
00095   filelockS(int fd)
00096   {
00097     return ut_file_lock(fd, ut_LOCKS, ut_NOBLOCK) >= 0 ? True : False;
00098   }
00099 
00100   Boolean
00101   filelockX(int fd)
00102   {
00103     return ut_file_lock(fd, ut_LOCKX, ut_NOBLOCK) >= 0 ? True : False;
00104   }
00105 
00106   Boolean
00107   fileunlock(int fd)
00108   {
00109     return ut_file_unlock(fd) == 0 ? True : False;
00110   }
00111 
00112   int
00113   shmfileOpen(const char *dbfile)
00114   {
00115     int fd = open(shmfileGet(dbfile), O_RDWR);
00116     // we defined NO_FILE_LOCK because of a problem (?) of lock+mmap on
00117     // NFS files on solaris 7+
00118 #ifndef NO_FILE_LOCK
00119 #error "NO_FILE_LOCK not defined"
00120     if (ut_file_lock(fd, ut_LOCKS, ut_NOBLOCK) < 0) {
00121       close(fd);
00122       return -1;
00123     }
00124 #endif
00125     return fd;
00126   }
00127     
00128   int
00129   objmapfileOpen(const char *dbfile, int flag)
00130   {
00131     int fd = open(objmapfileGet(dbfile), flag);
00132     return fd;
00133   }
00134     
00135   Status
00136   syserror(const char *fmt, ...)
00137   {
00138     Status status;
00139     char buf[1024];
00140     int const err = errno;
00141     va_list ap;
00142     va_start(ap, fmt);
00143 
00144     if (!fmt)
00145       buf[0] = 0;
00146     else
00147       vsprintf(buf, fmt, ap);
00148 
00149     va_end(ap);
00150 
00151     if (errno)
00152       return statusMake(SYS_ERROR, "%s: %s", buf,
00153                         strerror(err));
00154 
00155     return statusMake(SYS_ERROR, "%s", buf);
00156   }
00157 
00158   Status
00159   syscheck(const char *pre, long long c, const char *fmt, ...)
00160   {
00161     int const err = errno;
00162     va_list ap;
00163     va_start(ap, fmt);
00164 
00165     if (c < 0)
00166       {
00167         Status status;
00168         char buf[256];
00169 
00170         if (!fmt)
00171           buf[0] = 0;
00172         else
00173           vsprintf(buf, fmt, ap);
00174 
00175         va_end(ap);
00176         return statusMake(SYS_ERROR, "%s%s: errno '%s'", pre, buf,
00177                           strerror(err));
00178       }
00179 
00180     va_end(ap);
00181     return Success;
00182   }
00183 
00184   Status
00185   syscheckn(const char *pre, long long c, int n, const char *fmt, ...)
00186   {
00187     int const err = errno;
00188     va_list ap;
00189     va_start(ap, fmt);
00190 
00191     if (c != n)
00192       {
00193         Status status;
00194         char buf[256];
00195 
00196         if (!fmt)
00197           buf[0] = 0;
00198         else
00199           vsprintf(buf, fmt, ap);
00200 
00201         va_end(ap);
00202         if (c < 0)
00203           return statusMake(SYS_ERROR, "%s%s: errno '%s'", pre, buf,
00204                             strerror(err));
00205 
00206         return statusMake(SYS_ERROR, "%s%s: invalid size read: %db "
00207                           "expected, got %db", pre, buf,
00208                           n, c);
00209       }
00210 
00211     va_end(ap);
00212     return Success;
00213   }
00214 
00215   static const char *
00216   user_get_from_uid(int uid)
00217   {
00218     struct passwd *p = getpwuid(uid);
00219 
00220     if (!p)
00221       return "<unknown user>";
00222   
00223     return p->pw_name;
00224   }
00225 
00226   static const char *
00227   getmsgaccess(unsigned int flags)
00228   {
00229     return (flags == R_OK) ? "read" : "read/write";
00230   }
00231 
00232   Status
00233   checkFileAccessFailed(Error err, const char *what, const char *file,
00234                         unsigned int flags)
00235   {
00236     int uid = getuid();
00237     const char *user = user_get_from_uid(uid);
00238 
00239     //if (flags == F_OK)
00240     if (errno == ENOENT)
00241       return statusMake(err,
00242                         ACCESS_FILE_FMT "%s '%s' does not exist",
00243                         rpc_getpid(), user, uid, what, file);
00244 
00245     return statusMake(err,
00246                       ACCESS_FILE_FMT "no %s access on %s '%s'",
00247                       rpc_getpid(), user, uid,
00248                       getmsgaccess(flags), what, file);
00249   }
00250 
00251   Status
00252   checkFileAccess(Error err, const char *what, const char *file,
00253                   unsigned int flags)
00254   {
00255 #ifdef NEW_FILE_ACCESS
00256     flags &= ~F_OK;
00257 
00258     int fd;
00259 
00260     if ((flags & W_OK) != 0) {
00261       fd = open(file, O_RDWR);
00262     }
00263     else {
00264       fd = open(file, O_RDONLY);
00265     }
00266 
00267     if (fd >= 0) {
00268       close(fd);
00269       return Success;
00270     }
00271 
00272     return checkFileAccessFailed(err, what, file, flags);
00273 #else
00274     if (flags != F_OK) {
00275       /* check existence first */
00276       if (access(file, F_OK))
00277         return checkFileAccessFailed(err, what, file, F_OK);
00278     }
00279 
00280     flags &= ~F_OK;
00281     if (access(file, flags)) {
00282       printf("Access failed for %d\n", flags);
00283       if ((flags & W_OK)) {
00284         privilegeInit();
00285         int fd = open(file, O_RDWR);
00286         if (fd >= 0) {
00287           close(fd);
00288           printf("open OK!\n");
00289         }
00290       }
00291       else {
00292         privilegeInit();
00293         int fd = open(file, O_RDONLY);
00294         if (fd >= 0) {
00295           close(fd);
00296           printf("open OK!\n");
00297         }
00298       }
00299       return checkFileAccessFailed(err, what, file, flags);
00300     }
00301     return Success;
00302 #endif
00303   }
00304 
00305   Status
00306   dopen(char const * pre, char const * file, int mode, int * const fdp,
00307         Boolean * const suser)
00308   {
00309 #ifdef NEW_FILE_ACCESS
00310     if ((*fdp = open(file, mode)) >= 0)
00311       return Success;
00312 
00313     if (*fdp < 0) {
00314       return statusMake((errno == EACCES) ? INVALID_DBFILE_ACCESS : INVALID_DBFILE, "%sdatabase file '%s'", pre, file);
00315     }
00316 
00317     if (suser)
00318       *suser = False;
00319 
00320     return Success;
00321 #else
00322     Status s;
00323 
00324     if ((*fdp = open(file, mode)) >= 0)
00325       return Success;
00326 
00327     if ((s = privilegeAcquire()) != Success)
00328       return s;
00329 
00330     *fdp = open(file, mode);
00331 
00332     if ((s = privilegeRelease()) != Success)
00333       return s;
00334 
00335     if (*fdp < 0) {
00336       return statusMake((errno == EACCES) ? INVALID_DBFILE_ACCESS : INVALID_DBFILE, "%sdatabase file '%s'", pre, file);
00337     }
00338     if (suser)
00339       *suser = False;
00340 
00341     return Success;
00342 #endif
00343   }
00344 
00345   Status
00346   fileSizesGet(const char *file, unsigned long long &filesize,
00347                unsigned long long &fileblksize)
00348   {
00349     struct stat st;
00350     if (stat(file, &st) < 0)
00351       return statusMake(ERROR, "cannot stat file `%s'", file);
00352 
00353     filesize = st.st_size;
00354     fileblksize = st.st_blocks * 512;
00355 
00356     return Success;
00357   }
00358 
00359   Status
00360   fcouldnot(char const *pre, char const *what, char const *which)
00361   {
00362     int const err = errno;
00363     return statusMake(SYS_ERROR, "%ssystem error reported '%s' "
00364                       "while performing %s(%s)",
00365                       pre, strerror(err), what, (which ? which : ""));
00366   }
00367 
00368 #define PWDMAX 1024
00369 
00370 #if 0
00371   Status
00372   push_dir(const char *dbfile, char **pwd)
00373   {
00374     const char *dir = get_dir(dbfile);
00375 
00376     if (!*dir) {
00377       *pwd = 0;
00378       return Success;
00379     }
00380 
00381     *pwd = getcwd(0, PWDMAX);
00382     if (chdir(dir)) {
00383       free(*pwd);
00384       return statusMake(ERROR, "cannot change to directory '%s'", dir);
00385     }
00386 
00387     return Success;
00388   }
00389 #endif
00390 
00391   Status
00392   push_dir(const char *dbfile, char *pwd, unsigned int pwd_size)
00393   {
00394     const char *dir = get_dir(dbfile);
00395 
00396     if (!*dir) {
00397       *pwd = 0;
00398       return Success;
00399     }
00400 
00401     getcwd(pwd, pwd_size);
00402     if (chdir(dir)) {
00403       *pwd = 0;
00404       return statusMake(ERROR, "cannot change to directory '%s'", dir);
00405     }
00406 
00407     return Success;
00408   }
00409 
00410   Status
00411   pop_dir(char *pwd)
00412   {
00413     if (!pwd) {
00414       return Success;
00415     }
00416 
00417     if (chdir(pwd)) {
00418       return statusMake(ERROR, "cannot change to directory '%s'", pwd);
00419     }
00420 
00421 #if 0
00422     free(pwd);
00423 #endif
00424     return Success;
00425   }
00426 
00427   const char *
00428   get_dir(const char *dbfile)
00429   {
00430     if (*dbfile == '/' && strrchr(dbfile, '/')) {
00431       static char dirname[4][256];
00432       static int dirname_cnt;
00433       char *q;
00434     
00435       if (dirname_cnt == 4)
00436         dirname_cnt = 0;
00437 
00438       strcpy(dirname[dirname_cnt], dbfile);
00439       q = strrchr(dirname[dirname_cnt], '/');
00440       *q = 0;
00441       return dirname[dirname_cnt++];
00442     }
00443 
00444     return "";
00445   }
00446 
00447   char *
00448   string_version(unsigned int version)
00449   {
00450     static const char version_fmt[] = "%d.%d.%d";
00451     static char s_version[32];
00452 
00453 #define MAJORCOEF 100000
00454 #define MINORCOEF   1000
00455     int major     = version/MAJORCOEF;
00456     int minor     = (version - major*MAJORCOEF)/MINORCOEF;
00457     int bug_fixed = (version - major*MAJORCOEF - minor*MINORCOEF);
00458 
00459     sprintf(s_version, version_fmt, major, minor, bug_fixed);
00460     return s_version;
00461   }
00462 
00463   const char *
00464   get_time()
00465   {
00466     time_t t;
00467     char *c;
00468     time(&t);
00469     c = ctime(&t);
00470     c[strlen(c)-1] = 0;
00471     return c;
00472   }
00473 
00474   Status
00475   backendInterrupt()
00476   {
00477     backend_interrupt = True;
00478     return Success;
00479   }
00480 
00481   Status
00482   backendInterruptReset()
00483   {
00484     backend_interrupt = False;
00485     return Success;
00486   }
00487 
00488   void display_invalid_oid(const Oid *oid, ObjectHeader *xobjh)
00489   {
00490     printf("eyedbsm: invalid oid: %s ", getOidString(oid));
00491     printf(", xobjh: %p", xobjh);
00492     if (xobjh) {
00493       printf(" , unique: %d, size: %u [%u]", x2h_u32(xobjh->unique),
00494              x2h_u32(xobjh->size),
00495              x2h_makeValid(xobjh->size));
00496     }
00497     printf("\n");
00498   }
00499 
00500 #ifdef DICO_ALG
00501   int
00502   oid_cmp(Oid *a, Oid *b)
00503   {
00504     return (nsOidGet(dbh, a) - nsOidGet(dbh, b));
00505   }
00506 #endif
00507 
00508   Boolean
00509   is_number(const char *s)
00510   {
00511     if (!*s)
00512       return False;
00513   
00514     char c;
00515     while (c = *s++)
00516       if (!(c >= '0' && c <= '9'))
00517         return False;
00518 
00519     return True;
00520   }
00521 
00522   size_t
00523   fdSizeGet(int fd)
00524   {
00525     struct stat st;
00526 
00527     if (fstat(fd, &st) < 0)
00528       return ~0;
00529 
00530     return st.st_size;
00531   }
00532 
00533   size_t
00534   fileSizeGet(const char *file)
00535   {
00536     struct stat st;
00537 
00538     if (stat(file, &st) < 0)
00539       return ~0;
00540 
00541     return st.st_size;
00542   }
00543 }

Generated on Mon Dec 22 18:15:57 2008 for eyedb by  doxygen 1.5.3