|
|
| version 1.99, 2002/02/07 17:41:36 | version 1.108.2.1, 2002/06/10 09:24:08 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: commonly functions. | Parser: commonly functions. |
| Copyright(c) 2001 ArtLebedev Group(http://www.artlebedev.com) | Copyright(c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexander Petrosyan <paf@design.ru>(http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| $Id$ | $Id$ |
| */ | */ |
| Line 78 static int unlock(int fd) { FLOCK(F_TLOC | Line 78 static int unlock(int fd) { FLOCK(F_TLOC |
| #endif | #endif |
| static char *strnchr(char *buf, size_t size, char c) { | static char *strnchr(char *buf, size_t size, char c) { |
| // sanity check | |
| if(!buf) | |
| return 0; | |
| for(; size-->0; buf++) { | for(; size-->0; buf++) { |
| if(*buf==c) | if(*buf==c) |
| return buf; | return buf; |
| Line 135 bool file_read(Pool& pool, const String& | Line 139 bool file_read(Pool& pool, const String& |
| 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) { |
| lock_shared_blocking(f); | lock_shared_blocking(f); |
| if(stat(fname, &finfo)!=0) { | if(stat(fname, &finfo)!=0) { |
| Exception e(0, 0, | Exception e("file.missing", |
| &file_spec, | &file_spec, |
| "stat failed: %s (%d), actual filename '%s'", | "stat failed: %s (%d), actual filename '%s'", |
| strerror(errno), errno, fname); | strerror(errno), errno, fname); |
| Line 145 bool file_read(Pool& pool, const String& | Line 149 bool file_read(Pool& pool, const String& |
| throw e; | throw e; |
| return false; | return false; |
| } | } |
| #ifdef NO_FOREIGN_GROUP_FILES | |
| if(finfo.st_gid/*foreign?*/!=getegid()) { | |
| Exception e("parser.runtime", | |
| &file_spec, | |
| "parser reading files of foreign group disabled [recompile parser without --disable-foreign-group-files configure option], actual filename '%s'", | |
| fname); | |
| unlock(f); | |
| close(f); | |
| if(fail_on_read_problem) | |
| throw e; | |
| return false; | |
| } | |
| #endif | |
| size_t max_size=limit?min(offset+limit, (size_t)finfo.st_size)-offset:finfo.st_size; | size_t max_size=limit?min(offset+limit, (size_t)finfo.st_size)-offset:finfo.st_size; |
| if(!max_size) { // eof | if(!max_size) { // eof |
| if(as_text) { | if(as_text) { |
| Line 165 bool file_read(Pool& pool, const String& | Line 182 bool file_read(Pool& pool, const String& |
| return true; | return true; |
| if(int(data_size)<0 || data_size>max_size) | if(int(data_size)<0 || data_size>max_size) |
| throw Exception(0, 0, | throw Exception(0, |
| &file_spec, | &file_spec, |
| "read failed: actually read %d bytes count not in [0..%lu] valid range", | "read failed: actually read %d bytes count not in [0..%lu] valid range", |
| data_size, (unsigned long)max_size); //never | data_size, (unsigned long)max_size); //never |
| Line 178 bool file_read(Pool& pool, const String& | Line 195 bool file_read(Pool& pool, const String& |
| return true; | return true; |
| } | } |
| if(fail_on_read_problem) | if(fail_on_read_problem) |
| throw Exception(0, 0, | throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, |
| &file_spec, | &file_spec, |
| "read failed: %s (%d), actual filename '%s'", | "read failed: %s (%d), actual filename '%s'", |
| strerror(errno), errno, fname); | strerror(errno), errno, fname); |
| Line 208 bool file_write_action_under_lock( | Line 225 bool file_write_action_under_lock( |
| if((f=open(fname, | if((f=open(fname, |
| O_CREAT|O_RDWR | O_CREAT|O_RDWR |
| |(as_text?_O_TEXT:_O_BINARY) | |(as_text?_O_TEXT:_O_BINARY) |
| |(do_append?O_APPEND:0), 0664))>=0) { | |(do_append?O_APPEND:O_TRUNC), 0664))>=0) { |
| if((do_block?lock_exclusive_blocking(f):lock_exclusive_nonblocking(f))!=0) { | if((do_block?lock_exclusive_blocking(f):lock_exclusive_nonblocking(f))!=0) { |
| close(f); | close(f); |
| return false; | return false; |
| Line 218 bool file_write_action_under_lock( | Line 235 bool file_write_action_under_lock( |
| action(f, context); | action(f, context); |
| } catch(...) { | } catch(...) { |
| #if O_TRUNC==0 | #if O_TRUNC==0 |
| ftruncate(f, tell(f)); | if(!do_append) |
| ftruncate(f, tell(f)); | |
| #endif | #endif |
| unlock(f); | unlock(f); |
| close(f); | close(f); |
| Line 226 bool file_write_action_under_lock( | Line 244 bool file_write_action_under_lock( |
| } | } |
| #if O_TRUNC==0 | #if O_TRUNC==0 |
| ftruncate(f, tell(f)); | if(!do_append) |
| ftruncate(f, tell(f)); | |
| #endif | #endif |
| unlock(f); | unlock(f); |
| close(f); | close(f); |
| return true; | return true; |
| } else | } else |
| throw Exception(0, 0, | throw Exception(errno==EACCES?"file.access":0, |
| &file_spec, | &file_spec, |
| "%s failed: %s (%d), actual filename '%s'", | "%s failed: %s (%d), actual filename '%s'", |
| action_name, strerror(errno), errno, fname); | action_name, strerror(errno), errno, fname); |
| Line 274 bool file_delete(const String& file_spec | Line 293 bool file_delete(const String& file_spec |
| const char *fname=file_spec.cstr(String::UL_FILE_SPEC); | const char *fname=file_spec.cstr(String::UL_FILE_SPEC); |
| if(unlink(fname)!=0) | if(unlink(fname)!=0) |
| if(fail_on_read_problem) | if(fail_on_read_problem) |
| throw Exception(0, 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'", |
| strerror(errno), errno, fname); | strerror(errno), errno, fname); |
| Line 291 void file_move(const String& old_spec, c | Line 310 void file_move(const String& old_spec, c |
| create_dir_for_file(new_spec); | create_dir_for_file(new_spec); |
| if(rename(old_spec_cstr, new_spec_cstr)!=0) | if(rename(old_spec_cstr, new_spec_cstr)!=0) |
| throw Exception(0, 0, | throw Exception(errno==EACCES?"file.access":errno==ENOENT?"file.missing":0, |
| &old_spec, | &old_spec, |
| "rename failed: %s (%d), actual filename '%s' to '%s'", | "rename failed: %s (%d), actual filename '%s' to '%s'", |
| strerror(errno), errno, old_spec_cstr, new_spec_cstr); | strerror(errno), errno, old_spec_cstr, new_spec_cstr); |
| Line 304 static bool entry_readable(const String& | Line 323 static bool entry_readable(const String& |
| const char *fname=file_spec.cstr(String::UL_FILE_SPEC); | const char *fname=file_spec.cstr(String::UL_FILE_SPEC); |
| struct stat finfo; | struct stat finfo; |
| if(access(fname, R_OK)==0 && stat(fname, &finfo)==0) { | if(access(fname, R_OK)==0 && stat(fname, &finfo)==0) { |
| bool is_dir=finfo.st_mode&S_IFDIR != 0; | bool is_dir=(finfo.st_mode&S_IFDIR) != 0; |
| return is_dir==need_dir; | return is_dir==need_dir; |
| } | } |
| return false; | return false; |
| Line 336 bool file_stat(const String& file_spec, | Line 355 bool file_stat(const String& file_spec, |
| struct stat finfo; | struct stat finfo; |
| if(stat(fname, &finfo)!=0) | if(stat(fname, &finfo)!=0) |
| if(fail_on_read_problem) | if(fail_on_read_problem) |
| throw Exception(0, 0, | throw Exception("file.missing", |
| &file_spec, | &file_spec, |
| "getting file size failed: %s (%d), real filename '%s'", | "getting file size failed: %s (%d), real filename '%s'", |
| strerror(errno), errno, fname); | strerror(errno), errno, fname); |
| Line 392 char *rsplit(char *string, char delim) { | Line 411 char *rsplit(char *string, char delim) { |
| /// @todo less stupid type detection | /// @todo less stupid type detection |
| char *format(Pool& pool, double value, char *fmt) { | char *format(Pool& pool, double value, char *fmt) { |
| char *result=(char *)pool.malloc(MAX_NUMBER, 4); | char local_buf[MAX_NUMBER]; |
| size_t size; | |
| if(fmt) | if(fmt) |
| if(strpbrk(fmt, "diouxX")) | if(strpbrk(fmt, "diouxX")) |
| if(strpbrk(fmt, "ouxX")) | if(strpbrk(fmt, "ouxX")) |
| snprintf(result, MAX_NUMBER, fmt, (uint)value ); | size=snprintf(local_buf, sizeof(local_buf), fmt, (uint)value); |
| else | else |
| snprintf(result, MAX_NUMBER, fmt, (int)value ); | size=snprintf(local_buf, sizeof(local_buf), fmt, (int)value); |
| else | else |
| snprintf(result, MAX_NUMBER, fmt, value); | size=snprintf(local_buf, sizeof(local_buf), fmt, value); |
| else | else |
| snprintf(result, MAX_NUMBER, "%d", (int)value); | size=snprintf(local_buf, sizeof(local_buf), "%d", (int)value); |
| return result; | char *pool_buf=(char *)pool.malloc(size+1, 4); |
| memcpy(pool_buf, local_buf, size+1); | |
| return pool_buf; | |
| } | } |
| size_t stdout_write(const void *buf, size_t size) { | size_t stdout_write(const void *buf, size_t size) { |