[BACK]Return to mandocdb.c CVS log [TXT][DIR] Up to [cvsweb.bsd.lv] / mandoc

Diff for /mandoc/mandocdb.c between version 1.114 and 1.118

version 1.114, 2014/01/22 20:58:39 version 1.118, 2014/03/19 22:33:09
Line 20 
Line 20 
 #endif  #endif
   
 #include <sys/stat.h>  #include <sys/stat.h>
   #include <sys/wait.h>
   
 #include <assert.h>  #include <assert.h>
 #include <ctype.h>  #include <ctype.h>
Line 98  struct inodev {
Line 99  struct inodev {
   
 struct  mpage {  struct  mpage {
         struct inodev    inodev;  /* used for hashing routine */          struct inodev    inodev;  /* used for hashing routine */
           int64_t          recno;   /* id in mpages SQL table */
         enum form        form;    /* format from file content */          enum form        form;    /* format from file content */
         char            *sec;     /* section from file content */          char            *sec;     /* section from file content */
         char            *arch;    /* architecture from file content */          char            *arch;    /* architecture from file content */
Line 115  struct mlink {
Line 117  struct mlink {
         char            *name;    /* name from file name (not empty) */          char            *name;    /* name from file name (not empty) */
         char            *fsec;    /* section from file name suffix */          char            *fsec;    /* section from file name suffix */
         struct mlink    *next;    /* singly linked list */          struct mlink    *next;    /* singly linked list */
           struct mpage    *mpage;   /* parent */
 };  };
   
 enum    stmt {  enum    stmt {
Line 133  struct mdoc_handler {
Line 136  struct mdoc_handler {
 };  };
   
 static  void     dbclose(int);  static  void     dbclose(int);
 static  void     dbadd(const struct mpage *, struct mchars *);  static  void     dbadd(struct mpage *, struct mchars *);
   static  void     dbadd_mlink(const struct mlink *mlink);
 static  int      dbopen(int);  static  int      dbopen(int);
 static  void     dbprune(void);  static  void     dbprune(void);
 static  void     filescan(const char *);  static  void     filescan(const char *);
Line 168  static int  set_basedir(const char *);
Line 172  static int  set_basedir(const char *);
 static  int      treescan(void);  static  int      treescan(void);
 static  size_t   utf8(unsigned int, char [7]);  static  size_t   utf8(unsigned int, char [7]);
   
   static  char             tempfilename[32];
 static  char            *progname;  static  char            *progname;
 static  int              nodb; /* no database changes */  static  int              nodb; /* no database changes */
 static  int              quick; /* abort the parse early */  static  int              mparse_options; /* abort the parse early */
 static  int              use_all; /* use all found files */  static  int              use_all; /* use all found files */
 static  int              verb; /* print what we're doing */  static  int              verb; /* print what we're doing */
 static  int              warnings; /* warn about crap */  static  int              warnings; /* warn about crap */
Line 369  main(int argc, char *argv[])
Line 374  main(int argc, char *argv[])
                         nodb = 1;                          nodb = 1;
                         break;                          break;
                 case ('Q'):                  case ('Q'):
                         quick = 1;                          mparse_options |= MPARSE_QUICK;
                         break;                          break;
                 case ('T'):                  case ('T'):
                         if (strcmp(optarg, "utf8")) {                          if (strcmp(optarg, "utf8")) {
Line 409  main(int argc, char *argv[])
Line 414  main(int argc, char *argv[])
         }          }
   
         exitcode = (int)MANDOCLEVEL_OK;          exitcode = (int)MANDOCLEVEL_OK;
         mp = mparse_alloc(MPARSE_AUTO,          mp = mparse_alloc(mparse_options, MANDOCLEVEL_FATAL, NULL, NULL);
                 MANDOCLEVEL_FATAL, NULL, NULL, quick);  
         mc = mchars_alloc();          mc = mchars_alloc();
   
         ohash_init(&mpages, 6, &mpages_info);          ohash_init(&mpages, 6, &mpages_info);
Line 816  mlink_add(struct mlink *mlink, const struct stat *st)
Line 820  mlink_add(struct mlink *mlink, const struct stat *st)
         } else          } else
                 mlink->next = mpage->mlinks;                  mlink->next = mpage->mlinks;
         mpage->mlinks = mlink;          mpage->mlinks = mlink;
           mlink->mpage = mpage;
 }  }
   
 static void  static void
Line 958  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 963  mpages_merge(struct mchars *mc, struct mparse *mp)
 {  {
         char                     any[] = "any";          char                     any[] = "any";
         struct ohash_info        str_info;          struct ohash_info        str_info;
         struct mpage            *mpage;          struct mpage            *mpage, *mpage_dest;
         struct mlink            *mlink;          struct mlink            *mlink, *mlink_dest;
         struct mdoc             *mdoc;          struct mdoc             *mdoc;
         struct man              *man;          struct man              *man;
           char                    *sodest;
         char                    *cp;          char                    *cp;
         int                      match;          int                      match;
         unsigned int             pslot;          unsigned int             pslot;
Line 997  mpages_merge(struct mchars *mc, struct mparse *mp)
Line 1003  mpages_merge(struct mchars *mc, struct mparse *mp)
                     FORM_CAT != mpage->mlinks->fform) {                      FORM_CAT != mpage->mlinks->fform) {
                         lvl = mparse_readfd(mp, -1, mpage->mlinks->file);                          lvl = mparse_readfd(mp, -1, mpage->mlinks->file);
                         if (lvl < MANDOCLEVEL_FATAL)                          if (lvl < MANDOCLEVEL_FATAL)
                                 mparse_result(mp, &mdoc, &man);                                  mparse_result(mp, &mdoc, &man, &sodest);
                 }                  }
   
                 if (NULL != mdoc) {                  if (NULL != sodest) {
                           mlink_dest = ohash_find(&mlinks,
                               ohash_qlookup(&mlinks, sodest));
                           if (NULL != mlink_dest) {
   
                                   /* The .so target exists. */
   
                                   mpage_dest = mlink_dest->mpage;
                                   mlink = mpage->mlinks;
                                   while (1) {
                                           mlink->mpage = mpage_dest;
   
                                           /*
                                            * If the target was already
                                            * processed, add the links
                                            * to the database now.
                                            * Otherwise, this will
                                            * happen when we come
                                            * to the target.
                                            */
   
                                           if (mpage_dest->recno)
                                                   dbadd_mlink(mlink);
   
                                           if (NULL == mlink->next)
                                                   break;
                                           mlink = mlink->next;
                                   }
   
                                   /* Move all links to the target. */
   
                                   mlink->next = mlink_dest->next;
                                   mlink_dest->next = mpage->mlinks;
                                   mpage->mlinks = NULL;
                           }
                           ohash_delete(&strings);
                           mpage = ohash_next(&mpages, &pslot);
                           continue;
                   } else if (NULL != mdoc) {
                         mpage->form = FORM_SRC;                          mpage->form = FORM_SRC;
                         mpage->sec =                          mpage->sec =
                             mandoc_strdup(mdoc_meta(mdoc)->msec);                              mandoc_strdup(mdoc_meta(mdoc)->msec);
Line 1777  render_key(struct mchars *mc, struct str *key)
Line 1821  render_key(struct mchars *mc, struct str *key)
         key->rendered = buf;          key->rendered = buf;
 }  }
   
   static void
   dbadd_mlink(const struct mlink *mlink)
   {
           size_t           i;
   
           i = 1;
           SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->dsec);
           SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->arch);
           SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->name);
           SQL_BIND_INT64(stmts[STMT_INSERT_LINK], i, mlink->mpage->recno);
           SQL_STEP(stmts[STMT_INSERT_LINK]);
           sqlite3_reset(stmts[STMT_INSERT_LINK]);
   }
   
 /*  /*
  * Flush the current page's terms (and their bits) into the database.   * Flush the current page's terms (and their bits) into the database.
  * Wrap the entire set of additions in a transaction to make sqlite be a   * Wrap the entire set of additions in a transaction to make sqlite be a
Line 1784  render_key(struct mchars *mc, struct str *key)
Line 1842  render_key(struct mchars *mc, struct str *key)
  * Also, handle escape sequences at the last possible moment.   * Also, handle escape sequences at the last possible moment.
  */   */
 static void  static void
 dbadd(const struct mpage *mpage, struct mchars *mc)  dbadd(struct mpage *mpage, struct mchars *mc)
 {  {
         struct mlink    *mlink;          struct mlink    *mlink;
         struct str      *key;          struct str      *key;
         int64_t          recno;  
         size_t           i;          size_t           i;
         unsigned int     slot;          unsigned int     slot;
   
Line 1801  dbadd(const struct mpage *mpage, struct mchars *mc)
Line 1858  dbadd(const struct mpage *mpage, struct mchars *mc)
         i = 1;          i = 1;
         SQL_BIND_INT(stmts[STMT_INSERT_PAGE], i, FORM_SRC == mpage->form);          SQL_BIND_INT(stmts[STMT_INSERT_PAGE], i, FORM_SRC == mpage->form);
         SQL_STEP(stmts[STMT_INSERT_PAGE]);          SQL_STEP(stmts[STMT_INSERT_PAGE]);
         recno = sqlite3_last_insert_rowid(db);          mpage->recno = sqlite3_last_insert_rowid(db);
         sqlite3_reset(stmts[STMT_INSERT_PAGE]);          sqlite3_reset(stmts[STMT_INSERT_PAGE]);
   
         for (mlink = mpage->mlinks; mlink; mlink = mlink->next) {          for (mlink = mpage->mlinks; mlink; mlink = mlink->next)
                 i = 1;                  dbadd_mlink(mlink);
                 SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->dsec);  
                 SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->arch);  
                 SQL_BIND_TEXT(stmts[STMT_INSERT_LINK], i, mlink->name);  
                 SQL_BIND_INT64(stmts[STMT_INSERT_LINK], i, recno);  
                 SQL_STEP(stmts[STMT_INSERT_LINK]);  
                 sqlite3_reset(stmts[STMT_INSERT_LINK]);  
         }  
   
         for (key = ohash_first(&strings, &slot); NULL != key;          for (key = ohash_first(&strings, &slot); NULL != key;
              key = ohash_next(&strings, &slot)) {               key = ohash_next(&strings, &slot)) {
Line 1822  dbadd(const struct mpage *mpage, struct mchars *mc)
Line 1872  dbadd(const struct mpage *mpage, struct mchars *mc)
                 i = 1;                  i = 1;
                 SQL_BIND_INT64(stmts[STMT_INSERT_KEY], i, key->mask);                  SQL_BIND_INT64(stmts[STMT_INSERT_KEY], i, key->mask);
                 SQL_BIND_TEXT(stmts[STMT_INSERT_KEY], i, key->rendered);                  SQL_BIND_TEXT(stmts[STMT_INSERT_KEY], i, key->rendered);
                 SQL_BIND_INT64(stmts[STMT_INSERT_KEY], i, recno);                  SQL_BIND_INT64(stmts[STMT_INSERT_KEY], i, mpage->recno);
                 SQL_STEP(stmts[STMT_INSERT_KEY]);                  SQL_STEP(stmts[STMT_INSERT_KEY]);
                 sqlite3_reset(stmts[STMT_INSERT_KEY]);                  sqlite3_reset(stmts[STMT_INSERT_KEY]);
                 if (key->rendered != key->key)                  if (key->rendered != key->key)
Line 1874  static void
Line 1924  static void
 dbclose(int real)  dbclose(int real)
 {  {
         size_t           i;          size_t           i;
           int              status;
           pid_t            child;
   
         if (nodb)          if (nodb)
                 return;                  return;
Line 1889  dbclose(int real)
Line 1941  dbclose(int real)
         if (real)          if (real)
                 return;                  return;
   
         if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {          if ('\0' == *tempfilename) {
                   if (-1 == rename(MANDOC_DB "~", MANDOC_DB)) {
                           exitcode = (int)MANDOCLEVEL_SYSERR;
                           say(MANDOC_DB, "%s", strerror(errno));
                   }
                   return;
           }
   
           switch (child = fork()) {
           case (-1):
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(MANDOC_DB, NULL);                  say("fork cmp", "%s", strerror(errno));
                   return;
           case (0):
                   execlp("cmp", "cmp", "-s",
                       tempfilename, MANDOC_DB, NULL);
                   say("exec cmp", "%s", strerror(errno));
                   exit(0);
           default:
                   break;
         }          }
           if (-1 == waitpid(child, &status, 0)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say("wait cmp", "%s", strerror(errno));
           } else if (WIFSIGNALED(status)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say("cmp", "Died from a signal");
           } else if (WEXITSTATUS(status)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say(MANDOC_DB,
                       "Data changed, but cannot replace database");
           }
   
           *strrchr(tempfilename, '/') = '\0';
           switch (child = fork()) {
           case (-1):
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say("fork rm", "%s", strerror(errno));
                   return;
           case (0):
                   execlp("rm", "rm", "-rf", tempfilename, NULL);
                   say("exec rm", "%s", strerror(errno));
                   exit((int)MANDOCLEVEL_SYSERR);
           default:
                   break;
           }
           if (-1 == waitpid(child, &status, 0)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say("wait rm", "%s", strerror(errno));
           } else if (WIFSIGNALED(status) || WEXITSTATUS(status)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say(tempfilename,
                       "Cannot remove temporary directory");
           }
 }  }
   
 /*  /*
Line 1906  dbclose(int real)
Line 2008  dbclose(int real)
 static int  static int
 dbopen(int real)  dbopen(int real)
 {  {
         const char      *file, *sql;          const char      *sql;
         int              rc, ofl;          int              rc, ofl;
   
         if (nodb)          if (nodb)
                 return(1);                  return(1);
   
           *tempfilename = '\0';
         ofl = SQLITE_OPEN_READWRITE;          ofl = SQLITE_OPEN_READWRITE;
         if (0 == real) {  
                 file = MANDOC_DB "~";          if (real) {
                 if (-1 == remove(file) && ENOENT != errno) {                  rc = sqlite3_open_v2(MANDOC_DB, &db, ofl, NULL);
                   if (SQLITE_OK != rc) {
                         exitcode = (int)MANDOCLEVEL_SYSERR;                          exitcode = (int)MANDOCLEVEL_SYSERR;
                         say(file, NULL);                          say(MANDOC_DB, "%s", sqlite3_errmsg(db));
                         return(0);                          return(0);
                 }                  }
                 ofl |= SQLITE_OPEN_EXCLUSIVE;                  goto prepare_statements;
         } else          }
                 file = MANDOC_DB;  
   
         rc = sqlite3_open_v2(file, &db, ofl, NULL);          ofl |= SQLITE_OPEN_CREATE | SQLITE_OPEN_EXCLUSIVE;
   
           remove(MANDOC_DB "~");
           rc = sqlite3_open_v2(MANDOC_DB "~", &db, ofl, NULL);
         if (SQLITE_OK == rc)          if (SQLITE_OK == rc)
                 goto prepare_statements;                  goto create_tables;
         if (SQLITE_CANTOPEN != rc) {          if (MPARSE_QUICK & mparse_options) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(file, NULL);                  say(MANDOC_DB "~", "%s", sqlite3_errmsg(db));
                 return(0);                  return(0);
         }          }
   
         sqlite3_close(db);          if (strlcpy(tempfilename, "/tmp/mandocdb.XXXXXX",
         db = NULL;              sizeof(tempfilename)) >= sizeof(tempfilename)) {
   
         if (SQLITE_OK != (rc = sqlite3_open(file, &db))) {  
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(file, NULL);                  say("/tmp/mandocdb.XXXXXX", "Filename too long");
                 return(0);                  return(0);
         }          }
           if (NULL == mkdtemp(tempfilename)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say(tempfilename, "%s", strerror(errno));
                   return(0);
           }
           if (strlcat(tempfilename, "/" MANDOC_DB,
               sizeof(tempfilename)) >= sizeof(tempfilename)) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say(tempfilename, "Filename too long");
                   return(0);
           }
           rc = sqlite3_open_v2(tempfilename, &db, ofl, NULL);
           if (SQLITE_OK != rc) {
                   exitcode = (int)MANDOCLEVEL_SYSERR;
                   say(tempfilename, "%s", sqlite3_errmsg(db));
                   return(0);
           }
   
   create_tables:
         sql = "CREATE TABLE \"mpages\" (\n"          sql = "CREATE TABLE \"mpages\" (\n"
               " \"form\" INTEGER NOT NULL,\n"                " \"form\" INTEGER NOT NULL,\n"
               " \"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL\n"                " \"id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL\n"
Line 1964  dbopen(int real)
Line 2086  dbopen(int real)
   
         if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, NULL)) {          if (SQLITE_OK != sqlite3_exec(db, sql, NULL, NULL, NULL)) {
                 exitcode = (int)MANDOCLEVEL_SYSERR;                  exitcode = (int)MANDOCLEVEL_SYSERR;
                 say(file, "%s", sqlite3_errmsg(db));                  say(MANDOC_DB, "%s", sqlite3_errmsg(db));
                 return(0);                  return(0);
         }          }
   

Legend:
Removed from v.1.114  
changed lines
  Added in v.1.118

CVSweb