00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 #define _GNU_SOURCE             
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stdarg.h>
00018 #include <stdint.h>
00019 #include <unistd.h>
00020 #include <string.h>
00021 #include <ctype.h>
00022 #include <errno.h>
00023 #include <pwd.h>
00024 #include <grp.h>
00025 
00026 #include <sys/param.h>
00027 #include <sys/stat.h>
00028 
00029 #include "dhash.h"
00030 #include "util.h"
00031 #include "path_utils.h"
00032 #include "logging.h"
00033 #include "inotify_watch.h"
00034 #include "watch_database.h"
00035 
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 
00064 
00065 
00066 int debug = 0;
00067 
00068 
00069 
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 int key_string_cmp(const void *_a, const void *_b)
00093 {
00094     const hash_key_t *a = _a, *b = _b;
00095     char buf_a[128], buf_b[128];
00096     const char *str_a, *str_b;
00097 
00098     switch(a->type) {
00099     case HASH_KEY_STRING:
00100         str_a = a->str;
00101         break;
00102     case HASH_KEY_ULONG:
00103         snprintf(buf_a, sizeof(buf_a), "%lu", a->ul);
00104         str_a = buf_a;
00105         break;
00106     default:
00107         buf_a[0] = 0;
00108         str_a = buf_a;
00109     }
00110 
00111     switch(b->type) {
00112     case HASH_KEY_STRING:
00113         str_b = b->str;
00114         break;
00115     case HASH_KEY_ULONG:
00116         snprintf(buf_b, sizeof(buf_b), "%lu", b->ul);
00117         str_b = buf_b;
00118         break;
00119     default:
00120         buf_b[0] = 0;
00121         str_b = buf_b;
00122     }
00123 
00124     return strcmp(str_a, str_b);
00125 }
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 int entry_string_cmp(const void *_a, const void *_b)
00136 {
00137     const hash_entry_t *a = _a, *b = _b;
00138     char buf_a[128], buf_b[128];
00139     const char *str_a, *str_b;
00140 
00141     switch(a->key.type) {
00142     case HASH_KEY_STRING:
00143         str_a = a->key.str;
00144         break;
00145     case HASH_KEY_ULONG:
00146         snprintf(buf_a, sizeof(buf_a), "%lu", a->key.ul);
00147         str_a = buf_a;
00148         break;
00149     default:
00150         buf_a[0] = 0;
00151         str_a = buf_a;
00152     }
00153 
00154     switch(b->key.type) {
00155     case HASH_KEY_STRING:
00156         str_b = b->key.str;
00157         break;
00158     case HASH_KEY_ULONG:
00159         snprintf(buf_b, sizeof(buf_b), "%lu", b->key.ul);
00160         str_b = buf_b;
00161         break;
00162     default:
00163         buf_b[0] = 0;
00164         str_b = buf_b;
00165     }
00166 
00167     return strcmp(str_a, str_b);
00168 }
00169 
00170 
00171 
00172 
00173 
00174 
00175 
00176 
00177 
00178 char *keys_string(hash_table_t *table, const char *prefix, const char *suffix)
00179 {
00180     int prefix_len, suffix_len, extra_len;
00181     hash_key_t *keys, *key;
00182     int error;
00183     unsigned long i, count;
00184     int alloc_len;
00185     char tmp_buf[128];
00186     char *buf, *p, *buf_end;
00187 
00188     
00189 
00190 
00191 
00192     prefix_len = prefix ? strlen(prefix) : 0;
00193     suffix_len = suffix ? strlen(suffix) : 0;
00194     extra_len = prefix_len + suffix_len;
00195 
00196     
00197     if ((error = hash_keys(table, &count, &keys)) != HASH_SUCCESS) {
00198         log_msg(LOG_ERROR, _("could not get key array (%s)\n"),  error_string(error));
00199         return NULL;
00200     }
00201 
00202     
00203     if (count == 0) {
00204         return strdup("");
00205     }
00206 
00207     
00208     qsort(keys, count, sizeof(hash_key_t), key_string_cmp);
00209 
00210     
00211     alloc_len = 0;
00212     for (i = 0; i < count; i++) {
00213         key = &keys[i];
00214         switch(key->type) {
00215         case HASH_KEY_STRING:
00216             alloc_len += strlen(key->str) + extra_len;
00217             break;
00218         case HASH_KEY_ULONG:
00219             snprintf(tmp_buf, sizeof(tmp_buf), "%lu", key->ul);
00220             alloc_len += strlen(tmp_buf) + extra_len;
00221             break;
00222         }
00223     }
00224 
00225     
00226     alloc_len += 1;             
00227     if ((buf = malloc(alloc_len)) == NULL) {
00228         free(keys);
00229         return NULL;
00230     }
00231     p = buf;                    
00232     buf_end = &buf[alloc_len];  
00233 
00234     
00235     for (i = 0; i < count; i++) {
00236         key = &keys[i];
00237         switch(key->type) {
00238         case HASH_KEY_STRING:
00239             p += snprintf(p, buf_end - p, "%s%s%s", prefix?prefix:"", key->str, suffix?suffix:"");
00240             if (p >= buf_end) goto fail; 
00241             break;
00242         case HASH_KEY_ULONG:
00243             p += snprintf(p, buf_end - p, "%s%lu%s", prefix?prefix:"", key->ul, suffix?suffix:"");
00244             if (p >= buf_end) goto fail; 
00245             break;
00246         }
00247     }
00248     
00249     if (p > buf) p[-suffix_len] = 0;
00250     free(keys);
00251     return buf;
00252  fail:
00253     
00254     buf_end[-1] = 0;   
00255     free(keys);
00256     return buf;
00257 
00258 }
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 
00268 
00269 
00270 char *watch_path_table_string(hash_table_t *table)
00271 {
00272     int error;
00273     hash_entry_t *entries;
00274     unsigned long i, count;
00275     struct path_watch_t *pw;
00276     char *pw_string;
00277     char *tbl_string;
00278     size_t alloc_len, alloc_increment;
00279     size_t pw_string_len, tbl_string_len, needed_len;
00280 
00281     alloc_increment = 1024;
00282     tbl_string_len = 0;
00283 
00284     if ((tbl_string = malloc(alloc_len = alloc_increment)) == NULL) {
00285         return NULL;
00286     }
00287     *tbl_string = 0;
00288 
00289     
00290     if ((error = hash_entries(table, &count, &entries)) != HASH_SUCCESS) {
00291         log_msg(LOG_ERROR, _("could not get entry array (%s)\n"),  error_string(error));
00292         return NULL;
00293     }
00294 
00295     
00296     qsort(entries, count, sizeof(hash_entry_t), entry_string_cmp);
00297 
00298     
00299     for (i = 0; i < count; i++) {
00300         
00301         pw = (struct path_watch_t *) entries[i].value.ptr;
00302         if ((pw_string = path_watch_string(pw)) == NULL) {
00303             free(entries);
00304             return NULL;
00305         }
00306         
00307         pw_string_len = strlen(pw_string);
00308         needed_len = pw_string_len + 1; 
00309         if (tbl_string_len + needed_len > alloc_len) {
00310             alloc_len = alloc_len + MAX(needed_len,alloc_increment);
00311             if ((tbl_string = realloc(tbl_string, alloc_len)) == NULL) {
00312                 free(tbl_string);
00313                 free(entries);
00314                 return NULL;
00315             }
00316         }
00317         
00318         strncpy(tbl_string + tbl_string_len, pw_string, alloc_len - tbl_string_len);
00319         tbl_string_len += pw_string_len;
00320 
00321         
00322         free(pw_string);
00323 
00324         
00325         strncpy(tbl_string + tbl_string_len, "\n", alloc_len - tbl_string_len);
00326         tbl_string_len += 1;
00327     }
00328     
00329     free(entries);
00330 
00331     
00332     if (tbl_string_len > 0) tbl_string[tbl_string_len - 1] = 0;
00333     return tbl_string;
00334 }
00335 
00336 
00337 
00338 
00339 
00340 int strip_whitespace(char *str)
00341 {
00342     char *p = str;
00343 
00344     
00345     for (p = str; *p && isspace(*p); p++);
00346     if (p != str) memmove(str, p, strlen(p) + 1);
00347 
00348     
00349     for (p = str; *p; p++);
00350     for (p--; p >= str; p--) {
00351         if (isspace(*p))
00352             *p = 0;
00353         else
00354             break;
00355     }
00356     return SUCCESS;
00357 }
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 const char *util_error_string(int error)
00370 {
00371     static __thread char buf[80]; 
00372 
00373     switch(error) {
00374     case SUCCESS:                       return _("Success");
00375     case UTIL_ERROR_NOT_FOUND:          return _("Not found");
00376     default:
00377         snprintf(buf, sizeof(buf), _("unknown(%d)"), error);
00378         return buf;
00379     }
00380 }
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 const char *lwatch_error_string(int error)
00393 {
00394     static __thread char buf[80]; 
00395 
00396     switch(error) {
00397     case LWATCH_ERROR_CANNOT_MONITOR:        return _("cannot monitor target");
00398     case LWATCH_ERROR_CANNOT_FIND_PATH_INFO: return _("cannot find path info");
00399     case LWATCH_ERROR_LOST_RENAME:           return _("one of the paths for a rename event is unknown");
00400     case LWATCH_ERROR_STAT_NOT_VALID:        return _("stat information is not valid");
00401     default:
00402         snprintf(buf, sizeof(buf), _("unknown(%d)"), error);
00403         return buf;
00404     }
00405 }
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414 
00415 
00416 
00417 const char *error_string(int error)
00418 {
00419     static __thread char buf[256];   
00420 
00421     if (IS_HASH_ERROR(error))
00422         return hash_error_string(error);
00423     if (IS_INOTIFY_WATCH_ERROR(error))
00424         return inotify_watch_error_string(error);
00425     if (IS_PATH_UTILS_ERROR(error))
00426         return path_utils_error_string(error);
00427     if (IS_WATCH_DATABASE_ERROR(error))
00428         return watch_database_error_string(error);
00429     if (IS_LWATCH_ERROR(error))
00430         return lwatch_error_string(error);
00431 
00432     strerror_r(error, buf, sizeof(buf));
00433     return buf;
00434 }
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 const char *time_string(time_t t, bool local, const char *fmt)
00452 {
00453     static __thread char buf[128]; 
00454     struct tm tm_time;
00455 
00456     if (local)
00457         localtime_r(&t, &tm_time);
00458     else
00459         gmtime_r(&t, &tm_time);
00460 
00461     if (!fmt) {
00462         if (local) {
00463             fmt = "%FT%T%z";
00464         } else {
00465             fmt = "%FT%TZ";
00466         }
00467     }
00468     strftime(buf, sizeof(buf), fmt, &tm_time);
00469     return buf;
00470 }
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 const char *file_mode_string(mode_t mode)
00481 {
00482     static __thread char buf[11];
00483 
00484   if (S_ISREG (mode))
00485     buf[0] = '-';
00486   else if (S_ISDIR (mode))
00487     buf[0] = 'd';
00488   else if (S_ISBLK (mode))
00489     buf[0] = 'b';
00490   else if (S_ISCHR (mode))
00491     buf[0] = 'c';
00492   else if (S_ISLNK (mode))
00493     buf[0] = 'l';
00494   else if (S_ISFIFO (mode))
00495     buf[0] = 'p';
00496   else if (S_ISSOCK (mode))
00497     buf[0] = 's';
00498   else
00499     buf[0] = '?';
00500 
00501   buf[1] = mode & S_IRUSR ? 'r' : '-';
00502   buf[2] = mode & S_IWUSR ? 'w' : '-';
00503   buf[3] = (mode & S_ISUID
00504             ? (mode & S_IXUSR ? 's' : 'S')
00505             : (mode & S_IXUSR ? 'x' : '-'));
00506   buf[4] = mode & S_IRGRP ? 'r' : '-';
00507   buf[5] = mode & S_IWGRP ? 'w' : '-';
00508   buf[6] = (mode & S_ISGID
00509             ? (mode & S_IXGRP ? 's' : 'S')
00510             : (mode & S_IXGRP ? 'x' : '-'));
00511   buf[7] = mode & S_IROTH ? 'r' : '-';
00512   buf[8] = mode & S_IWOTH ? 'w' : '-';
00513   buf[9] = (mode & S_ISVTX
00514             ? (mode & S_IXOTH ? 't' : 'T')
00515             : (mode & S_IXOTH ? 'x' : '-'));
00516   buf[10] = '\0';
00517 
00518   return buf;
00519 }
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 int get_uid_name(uid_t uid, char **name)
00530 {
00531     struct passwd pw;
00532     struct passwd *result;
00533     char *buf;
00534     size_t bufsize;
00535     int error;
00536 
00537     *name = NULL;
00538     bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
00539     if (bufsize == -1)          
00540         bufsize = 16384;        
00541 
00542     if ((buf = malloc(bufsize)) == NULL) {
00543         error = errno;
00544         log_msg(LOG_ERROR, "Failed getting uid name for %d, could not alloc buffer for getpwuid_r (%s)", uid, strerror(error));
00545         *name = NULL;
00546         return error;
00547     }
00548 
00549     error = getpwuid_r(uid, &pw, buf, bufsize, &result);
00550     if (result == NULL) {
00551         if (error == 0) {
00552             error = UTIL_ERROR_NOT_FOUND;
00553             log_msg(LOG_INFO, "uid name for %d was not found (%s)", uid, strerror(error));
00554         } else {
00555             log_msg(LOG_ERROR, "getpwuid_r() failed, uid = %d: (%s)", uid, strerror(error));
00556         }
00557         *name = strdup(_("unknown"));
00558         free(buf);
00559         return error;
00560     } else {
00561         *name = strdup(pw.pw_name);
00562     }
00563 
00564     free(buf);
00565     return SUCCESS;
00566 }
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 
00575 
00576 int get_gid_name(gid_t gid, char **name)
00577 {
00578     struct group gr;
00579     struct group *result;
00580     char *buf;
00581     size_t bufsize;
00582     int error;
00583 
00584     *name = NULL;
00585     bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
00586     if (bufsize == -1)          
00587         bufsize = 16384;        
00588 
00589     if ((buf = malloc(bufsize)) == NULL) {
00590         error = errno;
00591         log_msg(LOG_ERROR, "Failed getting gid name for %d, could not alloc buffer for getgrgid_r (%s)", gid, strerror(error));
00592         *name = NULL;
00593         return error;
00594     }
00595 
00596     error = getgrgid_r(gid, &gr, buf, bufsize, &result);
00597     if (result == NULL) {
00598         if (error == 0) {
00599             error = UTIL_ERROR_NOT_FOUND;
00600             log_msg(LOG_INFO, "gid name for %d was not found (%s)", gid, strerror(error));
00601         } else {
00602             log_msg(LOG_ERROR, "getgrgid_r() failed, gid = %d: (%s)", gid, strerror(error));
00603         }
00604         *name = strdup(_("unknown"));
00605         free(buf);
00606         return error;
00607     } else {
00608         *name = strdup(gr.gr_name);
00609     }
00610 
00611     free(buf);
00612     return SUCCESS;
00613 }
00614 
00615