Diff for /parser3/src/main/pa_common.C between versions 1.156 and 1.169

version 1.156, 2003/09/25 09:15:03 version 1.169, 2003/11/24 12:21:02
Line 5 Line 5
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
   
 static const char* IDENT_COMMON_C="$Date$";   static const char * const IDENT_COMMON_C="$Date$"; 
   
 #include "pa_common.h"  #include "pa_common.h"
 #include "pa_exception.h"  #include "pa_exception.h"
Line 64  int PASCAL closesocket(SOCKET); Line 64  int PASCAL closesocket(SOCKET);
 #       endif  #       endif
 #endif  #endif
   
 // locking constants  
 //#define PA_DEBUG_NO_LOCKING  
   
 #ifdef PA_DEBUG_NO_LOCKING  
   
 #ifdef HAVE_FLOCK  
   
 static int lock_shared_blocking(int fd) { return flock(fd, LOCK_SH); }  
 static int lock_exclusive_blocking(int fd) { return flock(fd, LOCK_EX); }  
 static int lock_exclusive_nonblocking(int fd) { return flock(fd, LOCK_EX || LOCK_NB); }  
 static int unlock(int fd) { return flock(fd, LOCK_UN); }  
   
 #else  
 #ifdef HAVE__LOCKING  
   
 #define FLOCK(operation) lseek(fd, 0, SEEK_SET);  return _locking(fd, operation, 1)  
 static int lock_shared_blocking(int fd) { FLOCK(_LK_LOCK); }  
 static int lock_exclusive_blocking(int fd) { FLOCK(_LK_LOCK); }  
 static int lock_exclusive_nonblocking(int fd) { FLOCK(_LK_NBLCK); }  
 static int unlock(int fd) { FLOCK(_LK_UNLCK); }  
   
 #else  
 #ifdef HAVE_FCNTL  
   
 #define FLOCK(cmd, arg) struct flock ls={arg, SEEK_SET};  return fcntl(fd, cmd, &ls)  
 static int lock_shared_blocking(int fd) { FLOCK(F_SETLKW, F_RDLCK); }  
 static int lock_exclusive_blocking(int fd) { FLOCK(F_SETLKW, F_WRLCK); }  
 static int lock_exclusive_nonblocking(int fd) { FLOCK(F_SETLK, F_RDLCK); }  
 static int unlock(int fd) { FLOCK(F_SETLK, F_UNLCK); }  
   
 #else  
 #ifdef HAVE_LOCKF  
   
 #define FLOCK(fd, operation) lseek(fd, 0, SEEK_SET);  return lockf(fd, operation, 1)  
 static int lock_shared_blocking(int fd) { FLOCK(F_LOCK); } // on intel solaris man doesn't have doc on shared blocking  
 static int lock_exclusive_blocking(int fd) { FLOCK(F_LOCK); }  
 static int lock_exclusive_nonblocking(int fd) { FLOCK(F_TLOCK); }  
 static int unlock(int fd) { FLOCK(F_TLOCK); }  
   
 #else  
   
 #error unable to find file locking func  
   
 #endif  
 #endif  
 #endif  
 #endif  
   
 #else  
 static int lock_shared_blocking(int fd) { return 0; }  
 static int lock_exclusive_blocking(int fd) { return 0; }  
 static int lock_exclusive_nonblocking(int fd) { return 0; }  
 static int unlock(int fd) { return 0; }  
   
 #endif  
   
 // defines for globals  // defines for globals
   
 #define FILE_STATUS_NAME  "status"  #define FILE_STATUS_NAME  "status"
Line 254  static void timeout_handler(int sig){ Line 198  static void timeout_handler(int sig){
 static int http_request(String& response,  static int http_request(String& response,
                         const char* host, int port,                           const char* host, int port, 
                         const char* request,                           const char* request, 
                         int timeout,                          int 
   #ifdef PA_USE_ALARM
                           timeout
   #endif
                           ,
                         bool fail_on_status_ne_200) {                          bool fail_on_status_ne_200) {
         if(!host)          if(!host)
                 throw Exception("http.host",                   throw Exception("http.host", 
Line 382  struct File_read_http_result { Line 330  struct File_read_http_result {
 /// @todo build .cookies field. use ^file.tables.SET-COOKIES.menu{ for now  /// @todo build .cookies field. use ^file.tables.SET-COOKIES.menu{ for now
 static File_read_http_result file_read_http(Request_charsets& charsets,   static File_read_http_result file_read_http(Request_charsets& charsets, 
                                             const String& file_spec,                                               const String& file_spec, 
                                             HashStringValue *options=0) {                                              bool as_text,
                                                   HashStringValue *options=0) {
         File_read_http_result result;          File_read_http_result result;
         char host[MAX_STRING];           char host[MAX_STRING]; 
         const char* uri;           const char* uri; 
Line 403  static File_read_http_result file_read_h Line 352  static File_read_http_result file_read_h
                         valid_options++;                          valid_options++;
                         timeout=vtimeout->as_int();                           timeout=vtimeout->as_int(); 
                 }                  }
                 if(vheaders=options->get(http_headers_name)) {                  if((vheaders=options->get(http_headers_name))) {
                         valid_options++;                          valid_options++;
                 }                  }
                 if(Value* vany_status=options->get(http_any_status_name)) {                  if(Value* vany_status=options->get(http_any_status_name)) {
Line 462  static File_read_http_result file_read_h Line 411  static File_read_http_result file_read_h
                 bool user_agent_specified=false;                  bool user_agent_specified=false;
                 if(vheaders && !vheaders->is_string()) { // allow empty                  if(vheaders && !vheaders->is_string()) { // allow empty
                         if(HashStringValue *headers=vheaders->get_hash()) {                          if(HashStringValue *headers=vheaders->get_hash()) {
                                 Http_pass_header_info info={&charsets, &request};                                  Http_pass_header_info info={&charsets, &request, false};
                                 headers->for_each(http_pass_header, &info);                                   headers->for_each(http_pass_header, &info); 
                                 user_agent_specified=info.user_agent_specified;                                  user_agent_specified=info.user_agent_specified;
                         } else                          } else
Line 554  static File_read_http_result file_read_h Line 503  static File_read_http_result file_read_h
                 real_remote_charset=asked_remote_charset;                  real_remote_charset=asked_remote_charset;
   
         // output response          // output response
         String::C real_body=Charset::transcode(          String::C real_body=String::C(raw_body.cstrm()/*must be modifiable*/, raw_body.length());
                 String::C(raw_body.cstrm()/*must be modifiable*/, raw_body.length()),          if(as_text)
                 *real_remote_charset,                  real_body=Charset::transcode(real_body, *real_remote_charset, charsets.source());
                 charsets.source());  
   
         result.str=const_cast<char *>(real_body.str); // hacking a little          result.str=const_cast<char *>(real_body.str); // hacking a little
         result.length=real_body.length;          result.length=real_body.length;
Line 575  struct File_read_action_info { Line 523  struct File_read_action_info {
 static void file_read_action(  static void file_read_action(
                              struct stat& finfo,                                struct stat& finfo, 
                              int f,                                int f, 
                              const String& file_spec, const char* fname, bool as_text,                                const String& file_spec, const char* /*fname*/, bool as_text, 
                              void *context) {                               void *context) {
         File_read_action_info& info=*static_cast<File_read_action_info *>(context);           File_read_action_info& info=*static_cast<File_read_action_info *>(context); 
         if(size_t to_read_size=(size_t)finfo.st_size) {           if(size_t to_read_size=(size_t)finfo.st_size) { 
Line 585  static void file_read_action( Line 533  static void file_read_action(
                 if(ssize_t(*info.data_size)<0 || *info.data_size>to_read_size)                  if(ssize_t(*info.data_size)<0 || *info.data_size>to_read_size)
                         throw Exception(0,                           throw Exception(0, 
                                 &file_spec,                                   &file_spec, 
                                 "read failed: actually read %lu bytes count not in [0..%lu] valid range",                                   "read failed: actually read %l bytes count not in [0..%lu] valid range", 
                                         *info.data_size, to_read_size);                                           *info.data_size, to_read_size); 
         } else { // empty file          } else { // empty file
                 if(as_text) {                  if(as_text) {
Line 600  static void file_read_action( Line 548  static void file_read_action(
 File_read_result file_read(Request_charsets& charsets, const String& file_spec,   File_read_result file_read(Request_charsets& charsets, const String& file_spec, 
                            bool as_text, HashStringValue *params,                             bool as_text, HashStringValue *params,
                            bool fail_on_read_problem) {                             bool fail_on_read_problem) {
         File_read_result result={false};          File_read_result result={false, 0, 0, 0};
 #ifdef PA_HTTP  #ifdef PA_HTTP
         if(file_spec.starts_with("http://")) {          if(file_spec.starts_with("http://")) {
                 // fail on read problem                  // fail on read problem
                 File_read_http_result http=file_read_http(charsets, file_spec, params);                  File_read_http_result http=file_read_http(charsets, file_spec, as_text, params);
                 result.success=true;                  result.success=true;
                 result.str=http.str;                  result.str=http.str;
                 result.length=http.length;                  result.length=http.length;
                 result.headers=http.headers;                   result.headers=http.headers; 
         } else {          } else {
 #endif  #endif
                   if(params && params->count())
                           throw Exception("parser.runtime",
                                   0,
                                   "invalid option passed");
   
                 File_read_action_info info={&result.str, &result.length};                   File_read_action_info info={&result.str, &result.length}; 
                 result.success=file_read_action_under_lock(file_spec,                   result.success=file_read_action_under_lock(file_spec, 
                         "read", file_read_action, &info,                           "read", file_read_action, &info, 
Line 623  File_read_result file_read(Request_chars Line 576  File_read_result file_read(Request_chars
                 // UTF-8 signature: EF BB BF                  // UTF-8 signature: EF BB BF
                 if(result.length>=3) {                  if(result.length>=3) {
                         char *in=(char *)result.str;                          char *in=(char *)result.str;
                         if(strncmp(in, "\xEB\xBB\xBF", 3)==0) {                          if(strncmp(in, "\xEF\xBB\xBF", 3)==0) {
                                 result.str=in+3; result.length-=3;// skip prefix                                  result.str=in+3; result.length-=3;// skip prefix
                         }                          }
                 }                  }
Line 671  bool file_read_action_under_lock(const S Line 624  bool file_read_action_under_lock(const S
         // later: it seems, even this does not help sometimes          // later: it seems, even this does not help sometimes
     if((f=open(fname, O_RDONLY|(as_text?_O_TEXT:_O_BINARY)))>=0) {      if((f=open(fname, O_RDONLY|(as_text?_O_TEXT:_O_BINARY)))>=0) {
                 try {                  try {
                         if(lock_shared_blocking(f)!=0)                          if(pa_lock_shared_blocking(f)!=0)
                                 throw Exception("file.lock",                                   throw Exception("file.lock", 
                                                 &file_spec,                                                   &file_spec, 
                                                 "shared lock failed: %s (%d), actual filename '%s'",                                                   "shared lock failed: %s (%d), actual filename '%s'", 
Line 690  bool file_read_action_under_lock(const S Line 643  bool file_read_action_under_lock(const S
   
                         action(finfo, f, file_spec, fname, as_text, context);                           action(finfo, f, file_spec, fname, as_text, context); 
                 } catch(...) {                  } catch(...) {
                         unlock(f);close(f);                           pa_unlock(f);close(f); 
                         if(fail_on_read_problem)                          if(fail_on_read_problem)
                                 rethrow;                                  rethrow;
                         return false;                                             return false;                   
                 }                   } 
   
                 unlock(f);close(f);                   pa_unlock(f);close(f); 
                 return true;                  return true;
     } else {      } else {
                 if(fail_on_read_problem)                  if(fail_on_read_problem)
Line 733  bool file_write_action_under_lock( Line 686  bool file_write_action_under_lock(
                 O_CREAT|O_RDWR                  O_CREAT|O_RDWR
                 |(as_text?_O_TEXT:_O_BINARY)                  |(as_text?_O_TEXT:_O_BINARY)
                 |(do_append?O_APPEND:PA_O_TRUNC), 0664))>=0) {                  |(do_append?O_APPEND:PA_O_TRUNC), 0664))>=0) {
                 if((do_block?lock_exclusive_blocking(f):lock_exclusive_nonblocking(f))!=0) {                  if((do_block?pa_lock_exclusive_blocking(f):pa_lock_exclusive_nonblocking(f))!=0) {
                         Exception e("file.lock",                           Exception e("file.lock", 
                                 &file_spec,                                   &file_spec, 
                                 "shared lock failed: %s (%d), actual filename '%s'",                                   "shared lock failed: %s (%d), actual filename '%s'", 
Line 751  bool file_write_action_under_lock( Line 704  bool file_write_action_under_lock(
                         if(!do_append)                          if(!do_append)
                                 ftruncate(f, lseek(f, 0, SEEK_CUR)); // one can not use O_TRUNC, read lower                                  ftruncate(f, lseek(f, 0, SEEK_CUR)); // one can not use O_TRUNC, read lower
 #endif  #endif
                         unlock(f);close(f);                           pa_unlock(f);close(f); 
                         rethrow;                          rethrow;
                 }                  }
                                   
Line 759  bool file_write_action_under_lock( Line 712  bool file_write_action_under_lock(
                 if(!do_append)                  if(!do_append)
                         ftruncate(f, lseek(f, 0, SEEK_CUR)); // O_TRUNC truncates even exclusevely write-locked file [thanks to Igor Milyakov <virtan@rotabanner.com> for discovering]                          ftruncate(f, lseek(f, 0, SEEK_CUR)); // O_TRUNC truncates even exclusevely write-locked file [thanks to Igor Milyakov <virtan@rotabanner.com> for discovering]
 #endif  #endif
                 unlock(f);close(f);                   pa_unlock(f);close(f); 
                 return true;                  return true;
         } else          } else
                 throw Exception(errno==EACCES?"file.access":0,                   throw Exception(errno==EACCES?"file.access":0, 
Line 805  static void rmdir(const String& file_spe Line 758  static void rmdir(const String& file_spe
                   
         rmdir(file_spec.mid(0, pos_after-1/* / */).cstr(String::L_FILE_SPEC));           rmdir(file_spec.mid(0, pos_after-1/* / */).cstr(String::L_FILE_SPEC)); 
 }  }
 bool file_delete(const String& file_spec, bool fail_on_read_problem) {  bool file_delete(const String& file_spec, bool fail_on_problem) {
         const char* fname=file_spec.cstr(String::L_FILE_SPEC);           const char* fname=file_spec.cstr(String::L_FILE_SPEC); 
         if(unlink(fname)!=0)          if(unlink(fname)!=0)
                 if(fail_on_read_problem)                  if(fail_on_problem)
                         throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0,                           throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, 
                                 &file_spec,                                   &file_spec, 
                                 "unlink failed: %s (%d), actual filename '%s'",                                   "unlink failed: %s (%d), actual filename '%s'", 
Line 1124  int __vsnprintf(char* b, size_t s, const Line 1077  int __vsnprintf(char* b, size_t s, const
   
         if(r<0)          if(r<0)
                 r=0;                  r=0;
         else if(r>s)          else if((size_t)r>s)
                 r=s;                  r=s;
 #endif  #endif
         b[r]=0;          b[r]=0;
Line 1138  int __snprintf(char* b, size_t s, const Line 1091  int __snprintf(char* b, size_t s, const
     va_end(l);       va_end(l); 
         return r;          return r;
 }  }
   
 int pa_sleep(unsigned long secs, unsigned long usecs) {  
         for (;  usecs >= 1000000; ++secs, usecs -= 1000000);   
   
 #ifdef WIN32  
         Sleep(secs * 1000 + usecs / 1000);   
         return 0;  
 #else  
         struct timeval t;  
         t.tv_sec = secs;  
         t.tv_usec = usecs;  
         return (select(0, NULL, NULL, NULL, &t) == -1 ? errno : 0);   
 #endif  
 }  
   
   

Removed from v.1.156  
changed lines
  Added in v.1.169


E-mail: