00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
#include "dazuko_platform.h"
00036
00037
#include "dazuko_xp.h"
00038
#include "dazukoio.h"
00039
#include "dazuko_call.h"
00040
00041 #define NUM_SLOT_LISTS 5
00042 #define NUM_SLOTS 25
00043
00044 #define SCAN_ON_OPEN (access_mask & DAZUKO_ON_OPEN)
00045 #define SCAN_ON_CLOSE (access_mask & DAZUKO_ON_CLOSE)
00046 #define SCAN_ON_EXEC (access_mask & DAZUKO_ON_EXEC)
00047 #define SCAN_ON_CLOSE_MODIFIED (access_mask & DAZUKO_ON_CLOSE_MODIFIED)
00048
00049 struct path
00050 {
00051
00052
00053
00054 struct path *
next;
00055 int len;
00056 char path[1];
00057 };
00058
00059 struct hash
00060 {
00061
00062
00063
00064
00065 struct hash *
next;
00066 struct xp_file file;
00067 int dirty;
00068 int namelen;
00069 char name[1];
00070 };
00071
00072 struct daemon_id
00073 {
00074 int unique;
00075 struct xp_daemon_id *
xp_id;
00076 };
00077
00078 struct slot
00079 {
00080
00081
00082
00083
00084
00085 int id;
00086 struct daemon_id did;
00087 int write_mode;
00088 int state;
00089 int response;
00090 int event;
00091 int filenamelength;
00092 char *
filename;
00093 struct event_properties event_p;
00094 struct file_properties file_p;
00095 struct xp_mutex mutex;
00096 };
00097
00098 struct slot_list
00099 {
00100 struct xp_atomic use_count;
00101 struct slot slots[
NUM_SLOTS];
00102 char reg_name[1];
00103 };
00104
00105 struct slot_list_container
00106 {
00107 struct slot_list *
slot_list;
00108 struct xp_mutex mutex;
00109 };
00110
00111 struct one_slot_state_not_condition_param
00112 {
00113 struct slot *
slot;
00114 int state;
00115 };
00116
00117 struct two_slot_state_not_condition_param
00118 {
00119 struct slot *
slot1;
00120 int state1;
00121 struct slot *
slot2;
00122 int state2;
00123 };
00124
00125 struct get_ready_slot_condition_param
00126 {
00127 struct slot *
slot;
00128 struct slot_list *
slotlist;
00129 };
00130
00131 static int unique_count = 1;
00132 static char access_mask = 7;
00133 static struct slot_list_container slot_lists[
NUM_SLOT_LISTS];
00134 static struct path *
incl_paths =
NULL;
00135 static struct path *
excl_paths =
NULL;
00136 static struct hash *
hash =
NULL;
00137 static struct xp_rwlock lock_hash;
00138 static struct xp_rwlock lock_lists;
00139 static struct xp_atomic active;
00140 static struct xp_mutex mutex_unique_count;
00141
00142 static struct xp_queue wait_kernel_waiting_for_free_slot;
00143 static struct xp_queue wait_daemon_waiting_for_work;
00144 static struct xp_queue wait_kernel_waiting_while_daemon_works;
00145 static struct xp_queue wait_daemon_waiting_for_free;
00146
00147
00148 int dazuko_vsnprintf(
char *str, size_t size,
const char *format, va_list ap)
00149 {
00150
char *target;
00151
const char *end;
00152
int overflow = 0;
00153
char number_buffer[32];
00154
const char *s;
00155
00156
if (str ==
NULL || size < 1 || format ==
NULL)
00157
return -1;
00158
00159 target = str;
00160 end = (target + size) - 1;
00161
00162
#define DAZUKO_VSNPRINTF_PRINTSTRING \
00163
for ( ; *s ; s++) \
00164
{ \
00165
if (target == end) \
00166
{ \
00167
overflow = 1; \
00168
goto dazuko_vsnprintf_out; \
00169
} \
00170
*target = *s; \
00171
target++; \
00172
}
00173
00174
for ( ; *format ; format++)
00175 {
00176
if (target == end)
00177 {
00178 overflow = 1;
00179
goto dazuko_vsnprintf_out;
00180 }
00181
00182
if (*format ==
'%')
00183 {
00184 format++;
00185
00186
switch (*format)
00187 {
00188
case 's':
00189 s = va_arg(ap,
char *);
00190
if (s ==
NULL)
00191 s =
"(null)";
00192
DAZUKO_VSNPRINTF_PRINTSTRING
00193
break;
00194
00195
case 'd':
00196 sprintf(number_buffer,
"%d", va_arg(ap,
int));
00197 s = number_buffer;
00198
DAZUKO_VSNPRINTF_PRINTSTRING
00199
break;
00200
00201
case 'c':
00202 *target = va_arg(ap,
int);
00203 target++;
00204
break;
00205
00206
case 'l':
00207 format++;
00208
if (*format !=
'u')
00209 {
00210
00211
goto dazuko_vsnprintf_out;
00212 }
00213 sprintf(number_buffer,
"%lu", va_arg(ap,
unsigned long));
00214 s = number_buffer;
00215
DAZUKO_VSNPRINTF_PRINTSTRING
00216
break;
00217
00218
case '0':
00219 format++;
00220
if (*format !=
'2')
00221 {
00222
00223
goto dazuko_vsnprintf_out;
00224 }
00225 format++;
00226
if (*format !=
'x')
00227 {
00228
00229
goto dazuko_vsnprintf_out;
00230 }
00231 sprintf(number_buffer,
"%02x", va_arg(ap,
int));
00232 s = number_buffer;
00233
DAZUKO_VSNPRINTF_PRINTSTRING
00234
break;
00235
00236
default:
00237
00238
goto dazuko_vsnprintf_out;
00239 }
00240 }
00241
else
00242 {
00243 *target = *format;
00244 target++;
00245 }
00246 }
00247
00248 dazuko_vsnprintf_out:
00249
00250 *target = 0;
00251
00252
00253
00254
00255
00256
00257
return ((target - str) + overflow);
00258 }
00259
00260 int dazuko_snprintf(
char *str, size_t size,
const char *format, ...)
00261 {
00262 va_list ap;
00263
int ret;
00264
00265 va_start(ap, format);
00266 ret =
dazuko_vsnprintf(str, size, format, ap);
00267 va_end(ap);
00268
00269
return ret;
00270 }
00271
00272 inline void dazuko_bzero(
void *p,
int len)
00273 {
00274
00275
00276
char *ptr = (
char *)p;
00277
00278
while (len--)
00279 *ptr++ = 0;
00280 }
00281
00282 static inline int dazuko_get_new_unique(
void)
00283 {
00284
int unique;
00285
00286
00287
call_xp_down(&
mutex_unique_count);
00288
00289 unique =
unique_count;
00290
unique_count++;
00291
00292
call_xp_up(&
mutex_unique_count);
00293
00294
00295
return unique;
00296 }
00297
00298 static inline int dazuko_slot_state(
struct slot *s)
00299 {
00300
int state;
00301
00302
00303
if (
call_xp_down(&(s->
mutex)) != 0)
00304
return XP_ERROR_INTERRUPT;
00305
00306 state = s->
state;
00307
00308
call_xp_up(&(s->
mutex));
00309
00310
00311
return state;
00312 }
00313
00314 static int one_slot_state_not_condition(
void *param)
00315 {
00316
return (
dazuko_slot_state(((
struct one_slot_state_not_condition_param *)param)->
slot)
00317 != ((
struct one_slot_state_not_condition_param *)param)->state);
00318 }
00319
00320 static int two_slot_state_not_condition(
void *param)
00321 {
00322
return (
dazuko_slot_state(((
struct two_slot_state_not_condition_param *)param)->slot1)
00323 != ((
struct two_slot_state_not_condition_param *)param)->state1
00324 &&
dazuko_slot_state(((
struct two_slot_state_not_condition_param *)param)->slot2)
00325 != ((
struct two_slot_state_not_condition_param *)param)->state2);
00326 }
00327
00328 static inline int __dazuko_change_slot_state(
struct slot *s,
int from_state,
int to_state)
00329 {
00330
00331
00332
00333
00334
if (to_state != from_state)
00335 {
00336
00337
00338
if (s->
state != from_state || s->
did.
unique == 0)
00339
return 0;
00340 }
00341
00342 s->
state = to_state;
00343
00344
00345
00346
00347
if (to_state ==
DAZUKO_READY)
00348 {
00349
call_xp_notify(&
wait_kernel_waiting_for_free_slot);
00350 }
00351
else if (to_state ==
DAZUKO_FREE)
00352 {
00353
call_xp_notify(&
wait_kernel_waiting_while_daemon_works);
00354
call_xp_notify(&
wait_daemon_waiting_for_free);
00355 }
00356
00357
return 1;
00358 }
00359
00360 static int dazuko_change_slot_state(
struct slot *s,
int from_state,
int to_state,
int release)
00361 {
00362
00363
00364
00365
00366
00367
00368
00369
int success;
00370
00371
00372
00373
if (
call_xp_down(&(s->
mutex)) != 0)
00374
return 0;
00375
00376 success =
__dazuko_change_slot_state(s, from_state, to_state);
00377
00378
00379
00380
if (!success || release)
00381
call_xp_up(&(s->
mutex));
00382
00383
return success;
00384 }
00385
00386 static struct slot *
_dazuko_find_slot(
struct daemon_id *did,
int release,
struct slot_list *sl)
00387 {
00388
00389
00390
00391
00392
00393
00394
int i;
00395
struct slot *s =
NULL;
00396
00397
if (sl ==
NULL)
00398 {
00399
call_xp_print(
"dazuko: invalid slot_list given (bug!)\n");
00400
return NULL;
00401 }
00402
00403
for (i=0 ; i<
NUM_SLOTS ; i++)
00404 {
00405 s = &(sl->
slots[i]);
00406
00407
00408
00409
if (
call_xp_down(&(s->mutex)) != 0)
00410
return NULL;
00411
00412
if (did ==
NULL)
00413 {
00414
00415
if (s->did.unique == 0 && s->did.xp_id ==
NULL)
00416 {
00417
00418
00419
if (release)
00420
call_xp_up(&(s->mutex));
00421
00422
return s;
00423 }
00424 }
00425
else if (s->did.unique == 0 && s->did.xp_id ==
NULL)
00426 {
00427
00428
00429
00430 }
00431
00432
else if (
call_xp_id_compare(s->did.xp_id, did->
xp_id) == 0)
00433 {
00434
00435
00436
if (did->
unique < 0 || (s->did.unique == did->
unique))
00437 {
00438
00439
00440
if (release)
00441
call_xp_up(&(s->mutex));
00442
00443
return s;
00444 }
00445 }
00446
00447
call_xp_up(&(s->mutex));
00448
00449 }
00450
00451
return NULL;
00452 }
00453
00454 static struct slot *
dazuko_find_slot_and_slotlist(
struct daemon_id *did,
int release,
struct slot_list *slist,
struct slot_list **sl_result)
00455 {
00456
struct slot *s;
00457
int i;
00458
struct slot_list *sl;
00459
00460
if (slist ==
NULL)
00461 {
00462
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
00463 {
00464
00465
00466
00467
if (
call_xp_down(&(
slot_lists[i].mutex)) != 0)
00468
return NULL;
00469
00470 sl =
slot_lists[i].
slot_list;
00471
00472
call_xp_up(&(
slot_lists[i].mutex));
00473
00474
00475
if (sl !=
NULL)
00476 {
00477 s =
_dazuko_find_slot(did, release, sl);
00478
if (s !=
NULL)
00479 {
00480
00481
if (sl_result !=
NULL)
00482 *sl_result = sl;
00483
00484
return s;
00485 }
00486 }
00487 }
00488 }
00489
else
00490 {
00491
return _dazuko_find_slot(did, release, slist);
00492 }
00493
00494
return NULL;
00495 }
00496
00497 static inline struct slot *
dazuko_find_slot(
struct daemon_id *did,
int release,
struct slot_list *slist)
00498 {
00499
return dazuko_find_slot_and_slotlist(did, release, slist,
NULL);
00500 }
00501
00502 static int dazuko_insert_path_fs(
struct path **list,
char *fs_path,
int fs_len)
00503 {
00504
00505
00506
00507
00508
00509
00510
struct path *newitem;
00511
struct path *tmp;
00512
00513
if (fs_path ==
NULL || fs_len < 1)
00514
return XP_ERROR_INVALID;
00515
00516
00517
if (!
call_xp_is_absolute_path(fs_path))
00518
return XP_ERROR_INVALID;
00519
00520
00521 newitem = (
struct path *)
call_xp_malloc(
sizeof(
struct path) + fs_len);
00522
if (!newitem)
00523
return XP_ERROR_FAULT;
00524
00525
00526 memcpy(newitem->path, fs_path, fs_len);
00527
00528 newitem->path[fs_len] = 0;
00529
00530
while (newitem->path[fs_len-1] == 0)
00531 {
00532 fs_len--;
00533
if (fs_len == 0)
00534
break;
00535 }
00536
00537
if (fs_len < 1)
00538 {
00539
call_xp_free(newitem);
00540
return XP_ERROR_INVALID;
00541 }
00542
00543 newitem->len = fs_len;
00544
00545
00546
for (tmp=*list ; tmp ; tmp=tmp->
next)
00547 {
00548
if (newitem->len == tmp->len)
00549 {
00550
if (memcmp(newitem->path, tmp->path, tmp->len) == 0)
00551 {
00552
00553
00554
call_xp_free(newitem);
00555
00556
return 0;
00557 }
00558 }
00559 }
00560
00561
DPRINT((
"dazuko: adding %s %s\n", (list == &
incl_paths) ?
"incl" :
"excl", newitem->path));
00562
00563
00564
00565
call_xp_write_lock(&
lock_lists);
00566 newitem->next = *list;
00567 *list = newitem;
00568
call_xp_write_unlock(&
lock_lists);
00569
00570
00571
return 0;
00572 }
00573
00574 static void dazuko_remove_all_hash(
void)
00575 {
00576
00577
00578
struct hash *tmp;
00579
00580
00581
call_xp_write_lock(&
lock_hash);
00582
while (
hash)
00583 {
00584 tmp =
hash;
00585
hash =
hash->
next;
00586
00587
DPRINT((
"dazuko: removing hash %s\n", tmp->name));
00588
00589
call_xp_free(tmp);
00590 }
00591
call_xp_write_unlock(&
lock_hash);
00592
00593 }
00594
00595 static void dazuko_remove_all_paths(
void)
00596 {
00597
00598
00599
00600
struct path *tmp;
00601
00602
00603
call_xp_write_lock(&
lock_lists);
00604
00605
00606
while (
incl_paths)
00607 {
00608 tmp =
incl_paths;
00609
incl_paths =
incl_paths->
next;
00610
00611
DPRINT((
"dazuko: removing incl %s\n", tmp->path));
00612
00613
call_xp_free(tmp);
00614 }
00615
00616
00617
while (
excl_paths)
00618 {
00619 tmp =
excl_paths;
00620
excl_paths =
excl_paths->
next;
00621
00622
DPRINT((
"dazuko: removing excl %s\n", tmp->path));
00623
00624
call_xp_free(tmp);
00625 }
00626
00627
call_xp_write_unlock(&
lock_lists);
00628
00629 }
00630
00631 static int _dazuko_unregister_daemon(
struct daemon_id *did)
00632 {
00633
00634
00635
00636
00637
struct slot *s;
00638
struct slot_list *sl;
00639
00640
DPRINT((
"dazuko: dazuko_unregister_daemon() [%d]\n", did->
unique));
00641
00642
00643
00644
00645 s =
dazuko_find_slot_and_slotlist(did, 0,
NULL, &sl);
00646
00647
if (s ==
NULL)
00648 {
00649
00650
return 0;
00651 }
00652
00653
00654
00655
00656 s->did.unique = 0;
00657
call_xp_id_free(s->did.xp_id);
00658 s->did.xp_id =
NULL;
00659
00660
00661
__dazuko_change_slot_state(s,
DAZUKO_FREE,
DAZUKO_FREE);
00662
00663
call_xp_atomic_dec(&(sl->use_count));
00664
00665
call_xp_up(&(s->mutex));
00666
00667
00668
00669
00670
if (
call_xp_atomic_read(&
active) > 0)
00671 {
00672
00673
00674
00675
00676
call_xp_atomic_dec(&
active);
00677 }
00678
else
00679 {
00680
call_xp_print(
"dazuko: active count error (possible bug)\n");
00681 }
00682
00683
00684
00685
00686
00687
00688
if (
call_xp_atomic_read(&
active) == 0)
00689 {
00690
00691
00692
dazuko_remove_all_paths();
00693
00694
00695
dazuko_remove_all_hash();
00696 }
00697
00698
call_xp_notify(&
wait_kernel_waiting_for_free_slot);
00699
call_xp_notify(&
wait_kernel_waiting_while_daemon_works);
00700
00701
return 0;
00702 }
00703
00704 int dazuko_unregister_daemon(
struct xp_daemon_id *xp_id)
00705 {
00706
struct daemon_id did;
00707
int ret;
00708
00709
if (xp_id ==
NULL)
00710
return 0;
00711
00712 did.
unique = -1;
00713 did.
xp_id =
call_xp_id_copy(xp_id);
00714
00715 ret =
_dazuko_unregister_daemon(&did);
00716
00717
call_xp_id_free(did.
xp_id);
00718
00719
return ret;
00720 }
00721
00722 static inline int dazuko_state_error(
struct slot *s,
int current_state)
00723 {
00724
if (
dazuko_change_slot_state(s, current_state,
DAZUKO_BROKEN, 1))
00725 {
00726
call_xp_notify(&
wait_kernel_waiting_for_free_slot);
00727
call_xp_notify(&
wait_kernel_waiting_while_daemon_works);
00728 }
00729
00730
return 0;
00731 }
00732
00733 static int dazuko_register_daemon(
struct daemon_id *did,
const char *reg_name,
int string_length,
int write_mode)
00734 {
00735
const char *p1;
00736
char *p2;
00737
struct slot *s;
00738
struct slot_list *sl;
00739
int i;
00740
00741
DPRINT((
"dazuko: dazuko_register_daemon() [%d]\n", did->
unique));
00742
00743
if (did ==
NULL || reg_name ==
NULL)
00744
return XP_ERROR_PERMISSION;
00745
00746 s =
dazuko_find_slot(did, 1,
NULL);
00747
00748
if (s !=
NULL)
00749 {
00750
00751
00752
call_xp_print(
"dazuko: daemon %d already assigned to slot[%d]\n", did->
unique, s->id);
00753
00754
return XP_ERROR_PERMISSION;
00755 }
00756
00757
00758
00759
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
00760 {
00761
00762
00763
00764
if (
call_xp_down(&(
slot_lists[i].mutex)) != 0)
00765
return XP_ERROR_INTERRUPT;
00766
00767 sl =
slot_lists[i].
slot_list;
00768
00769
call_xp_up(&(
slot_lists[i].mutex));
00770
00771
00772
if (sl !=
NULL)
00773 {
00774 p1 = reg_name;
00775 p2 = sl->reg_name;
00776
00777
while (*p1 == *p2)
00778 {
00779
if (*p1 == 0)
00780
break;
00781
00782 p1++;
00783 p2++;
00784 }
00785
00786
if (*p1 == *p2)
00787
break;
00788 }
00789 }
00790
00791
if (i ==
NUM_SLOT_LISTS)
00792 {
00793
00794
00795
00796 sl = (
struct slot_list *)
call_xp_malloc(
sizeof(
struct slot_list) + string_length);
00797
if (!sl)
00798
return XP_ERROR_FAULT;
00799
00800
dazuko_bzero(sl,
sizeof(
struct slot_list) + string_length);
00801
call_xp_atomic_set(&(sl->use_count), 0);
00802
00803 p1 = reg_name;
00804 p2 = sl->reg_name;
00805
00806
while (*p1)
00807 {
00808 *p2 = *p1;
00809
00810 p1++;
00811 p2++;
00812 }
00813 *p2 = 0;
00814
00815
00816
for (i=0 ; i<
NUM_SLOTS ; i++)
00817 {
00818 sl->slots[i].id = i;
00819
call_xp_init_mutex(&(sl->slots[i].mutex));
00820 }
00821
00822
00823
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
00824 {
00825
00826
00827
00828
if (
call_xp_down(&(
slot_lists[i].mutex)) != 0)
00829 {
00830
call_xp_free(sl);
00831
return XP_ERROR_INTERRUPT;
00832 }
00833
00834
if (
slot_lists[i].
slot_list ==
NULL)
00835 {
00836
slot_lists[i].
slot_list = sl;
00837
00838
call_xp_up(&(
slot_lists[i].mutex));
00839
00840
break;
00841 }
00842
00843
call_xp_up(&(
slot_lists[i].mutex));
00844
00845 }
00846
00847
if (i ==
NUM_SLOT_LISTS)
00848 {
00849
00850
call_xp_free(sl);
00851
return XP_ERROR_BUSY;
00852 }
00853 }
00854
00855
00856
00857
00858 s =
dazuko_find_slot(
NULL, 0, sl);
00859
00860
if (s ==
NULL)
00861
return XP_ERROR_BUSY;
00862
00863
00864
00865
00866
00867
00868
00869
00870
call_xp_atomic_inc(&
active);
00871
00872
00873 did->
unique =
dazuko_get_new_unique();
00874
00875 s->did.unique = did->
unique;
00876 s->did.xp_id =
call_xp_id_copy(did->
xp_id);
00877 s->write_mode = write_mode;
00878
00879
call_xp_atomic_inc(&(sl->use_count));
00880
00881
00882
00883
__dazuko_change_slot_state(s,
DAZUKO_FREE,
DAZUKO_FREE);
00884
00885
DPRINT((
"dazuko: slot[%d] assigned to daemon %d\n", s->id, s->did.unique));
00886
00887
call_xp_up(&(s->mutex));
00888
00889
00890
return 0;
00891 }
00892
00893 static struct slot*
dazuko_get_an_access(
struct daemon_id *did)
00894 {
00895
00896
00897
00898
00899
00900
00901
00902
00903
int i;
00904
struct slot *s;
00905
struct one_slot_state_not_condition_param cond_p;
00906
00907 tryagain:
00908
00909 s =
dazuko_find_slot(did, 1,
NULL);
00910
00911
if (s ==
NULL)
00912 {
00913 i =
dazuko_register_daemon(did,
"_COMPAT", 7, 1);
00914
if (i != 0)
00915 {
00916
call_xp_print(
"dazuko: unregistered daemon %d attempted to get access\n", did->
unique);
00917
return NULL;
00918 }
00919
00920 s =
dazuko_find_slot(did, 1,
NULL);
00921
if (s ==
NULL)
00922 {
00923
call_xp_print(
"dazuko: unregistered daemon %d attempted to get access\n", did->
unique);
00924
return NULL;
00925 }
00926
00927
call_xp_print(
"dazuko: warning: daemon %d is using a deprecated protocol\n", did->
unique);
00928 }
00929
00930
00931
dazuko_change_slot_state(s,
DAZUKO_READY,
DAZUKO_READY, 1);
00932
00933 cond_p.
slot = s;
00934 cond_p.
state =
DAZUKO_READY;
00935
if (
call_xp_wait_until_condition(&
wait_daemon_waiting_for_work,
one_slot_state_not_condition, &cond_p, 1) != 0)
00936 {
00937
00938
00939
00940
00941
DPRINT((
"dazuko: daemon %d killed while waiting for work\n", did->
unique));
00942
00943
if (
dazuko_change_slot_state(s,
DAZUKO_READY,
DAZUKO_BROKEN, 1) ||
dazuko_change_slot_state(s,
DAZUKO_WAITING,
DAZUKO_BROKEN, 1))
00944 {
00945
call_xp_notify(&
wait_kernel_waiting_for_free_slot);
00946
call_xp_notify(&
wait_kernel_waiting_while_daemon_works);
00947 }
00948
00949
return NULL;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
if (!
dazuko_change_slot_state(s,
DAZUKO_WAITING,
DAZUKO_WORKING, 0))
00959 {
00960
00961
00962
goto tryagain;
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972
return s;
00973 }
00974
00975 static int dazuko_return_access(
struct daemon_id *did,
int response,
struct slot *s)
00976 {
00977
00978
00979
00980
00981
struct one_slot_state_not_condition_param cond_p;
00982
00983
00984
if (s ==
NULL)
00985 {
00986
00987 s =
dazuko_find_slot(did, 1,
NULL);
00988
00989
if (s ==
NULL)
00990 {
00991
00992
00993
00994
DPRINT((
"dazuko: daemon %d unexpectedly lost slot\n", did->
unique));
00995
00996
return XP_ERROR_PERMISSION;
00997 }
00998 }
00999
01000
01001
01002
01003
01004
if (!
dazuko_change_slot_state(s,
DAZUKO_WORKING,
DAZUKO_DONE, 0))
01005 {
01006
01007
01008
01009
01010
DPRINT((
"dazuko: response from daemon %d on slot[%d] not needed\n", did->
unique, s->
id));
01011
01012
return 0;
01013 }
01014
01015
01016
01017 s->
response = response;
01018
01019
call_xp_up(&(s->
mutex));
01020
01021
01022
01023
01024
call_xp_notify(&
wait_kernel_waiting_while_daemon_works);
01025
01026 cond_p.
slot = s;
01027 cond_p.
state =
DAZUKO_DONE;
01028
if (
call_xp_wait_until_condition(&
wait_daemon_waiting_for_free,
one_slot_state_not_condition, &cond_p, 1) != 0)
01029 {
01030
01031
01032
01033
01034
DPRINT((
"dazuko: daemon %d killed while waiting for response acknowledgement\n", did->
unique));
01035
01036
return XP_ERROR_INTERRUPT;
01037 }
01038
01039
return 0;
01040 }
01041
01042 static inline int dazuko_isdigit(
const char c)
01043 {
01044
return (c >=
'0' && c <=
'9');
01045 }
01046
01047 static inline long dazuko_strtol(
const char *string)
01048 {
01049
long num = 1;
01050
const char *p = string;
01051
01052
if (string ==
NULL)
01053
return 0;
01054
01055
switch (*p)
01056 {
01057
case '-':
01058 num = -1;
01059 p++;
01060
break;
01061
01062
case '+':
01063 p++;
01064
break;
01065 }
01066
01067
if (
dazuko_isdigit(*p))
01068 {
01069 num *= *p -
'0';
01070 p++;
01071 }
01072
else
01073 {
01074
return 0;
01075 }
01076
01077
while (
dazuko_isdigit(*p))
01078 {
01079 num *= 10;
01080 num += *p -
'0';
01081 p++;
01082 }
01083
01084
return num;
01085 }
01086
01087 static inline int dazuko_strlen(
const char *string)
01088 {
01089
const char *p;
01090
01091
if (string ==
NULL)
01092
return -1;
01093
01094
for (p=string ; *p ; p++)
01095
continue;
01096
01097
return (p - string);
01098 }
01099
01100 static inline const char*
dazuko_strchr(
const char *haystack,
char needle)
01101 {
01102
const char *p;
01103
01104
if (haystack ==
NULL)
01105
return NULL;
01106
01107
for (p=haystack ; *p ; p++)
01108 {
01109
if (*p == needle)
01110
return p;
01111 }
01112
01113
return NULL;
01114 }
01115
01116 static inline const char*
dazuko_strstr(
const char *haystack,
const char *needle)
01117 {
01118
const char *p1;
01119
const char *p2;
01120
const char *p3;
01121
01122
if (haystack ==
NULL || needle ==
NULL)
01123
return NULL;
01124
01125
for (p1=haystack ; *p1 ; p1++)
01126 {
01127
for (p2=needle,p3=p1 ; *p2&&*p3 ; p2++,p3++)
01128 {
01129
if (*p2 != *p3)
01130
break;
01131 }
01132
01133
if (*p2 == 0)
01134
return p1;
01135 }
01136
01137
return NULL;
01138 }
01139
01140 int dazuko_get_value(
const char *key,
const char *string,
char **value)
01141 {
01142
const char *p1;
01143
const char *p2;
01144
int size;
01145
01146
if (value ==
NULL)
01147
return -1;
01148
01149 *value =
NULL;
01150
01151
if (key ==
NULL || string ==
NULL)
01152
return -1;
01153
01154 p1 =
dazuko_strstr(string, key);
01155
if (p1 ==
NULL)
01156
return -1;
01157
01158 p1 +=
dazuko_strlen(key);
01159
01160
for (p2=p1 ; *p2 && *p2!=
'\n' ; p2++)
01161
continue;
01162
01163 size = (p2 - p1) + 1;
01164 *value =
call_xp_malloc(size);
01165
if (*value ==
NULL)
01166
return -1;
01167
01168 memcpy(*value, p1, size - 1);
01169 (*value)[size - 1] = 0;
01170
01171
return 0;
01172 }
01173
01174 static inline void dazuko_clear_replybuffer(
struct dazuko_request *request)
01175 {
01176
dazuko_bzero(request->
reply_buffer, request->
reply_buffer_size);
01177 request->
reply_buffer_size_used = 0;
01178 }
01179
01180 static inline void dazuko_close_replybuffer(
struct dazuko_request *request)
01181 {
01182 request->
reply_buffer[request->
reply_buffer_size_used] = 0;
01183 request->
reply_buffer_size_used++;
01184 }
01185
01186 static inline void dazuko_add_keyvalue_to_replybuffer(
struct dazuko_request *request,
const char *key,
void *value,
char vtype)
01187 {
01188
01189
#define DAZUKO_VSNPRINT(type, name) dazuko_snprintf(request->reply_buffer + request->reply_buffer_size_used, (request->reply_buffer_size - request->reply_buffer_size_used) - 1, "%s%" #type , key, *((name *)value))
01190
01191
switch (vtype)
01192 {
01193
case 'd':
01194
DAZUKO_VSNPRINT(d,
const int);
01195
break;
01196
01197
case 's':
01198
DAZUKO_VSNPRINT(s,
const char *);
01199
break;
01200
01201
case 'l':
01202
DAZUKO_VSNPRINT(lu,
const unsigned long);
01203
break;
01204
01205
default:
01206
01207
DAZUKO_VSNPRINT(c,
const char);
01208
break;
01209 }
01210
01211
01212 request->
reply_buffer_size_used += strlen(request->
reply_buffer + request->
reply_buffer_size_used);
01213 }
01214
01215 static inline int dazuko_printable(
char c)
01216 {
01217
01218
01219
return ((c >=
' ') && (c <=
'~') && (c !=
'\\'));
01220 }
01221
01222 static inline void dazuko_add_esc_to_replybuffer(
struct dazuko_request *request,
const char *key,
char **filename)
01223 {
01224
int found = 0;
01225
char *p_rq;
01226
const char *limit;
01227
const char *p_fn;
01228
unsigned char c;
01229
01230
01231
for (p_fn=*filename ; *p_fn ; p_fn++)
01232 {
01233
if (!
dazuko_printable(*p_fn))
01234 {
01235 found = 1;
01236
break;
01237 }
01238 }
01239
01240
if (found)
01241 {
01242
01243
01244 p_rq = request->
reply_buffer + request->
reply_buffer_size_used;
01245 limit = request->
reply_buffer + request->
reply_buffer_size - 1;
01246
01247
dazuko_snprintf(p_rq, limit - p_rq,
"%s", key);
01248 p_rq += strlen(p_rq);
01249
01250
for (p_fn=*filename ; *p_fn && (p_rq<limit) ; p_fn++)
01251 {
01252
if (
dazuko_printable(*p_fn))
01253 {
01254 *p_rq = *p_fn;
01255 p_rq++;
01256 }
01257
else
01258 {
01259 c = *p_fn & 0xFF;
01260
dazuko_snprintf(p_rq, limit - p_rq,
"\\x%02x", c);
01261 p_rq += strlen(p_rq);
01262 }
01263 }
01264
01265 request->
reply_buffer_size_used += strlen(request->
reply_buffer + request->
reply_buffer_size_used);
01266 }
01267
else
01268 {
01269
01270
01271
dazuko_add_keyvalue_to_replybuffer(request, key, filename,
's');
01272 }
01273 }
01274
01275 static int dazuko_set_option(
struct daemon_id *did,
int opt,
void *param,
int len)
01276 {
01277
01278
01279
01280
struct slot *s;
01281
int error;
01282
01283
01284
if (len < 0 || len > 8192)
01285
return XP_ERROR_PERMISSION;
01286
01287
01288
01289
01290
01291 s =
dazuko_find_slot(did, 1,
NULL);
01292
01293
switch (opt)
01294 {
01295
case REGISTER:
01296
call_xp_print(
"dazuko: dazuko_set_option does not support REGISTER (bug!)\n");
01297
return XP_ERROR_PERMISSION;
01298
01299
case UNREGISTER:
01300
if (s ==
NULL)
01301 {
01302
01303
01304
return 0;
01305 }
01306
break;
01307
01308
default:
01309
if (s ==
NULL)
01310 {
01311 error =
dazuko_register_daemon(did,
"_COMPAT", 7, 1);
01312
if (error)
01313 {
01314
call_xp_print(
"dazuko: unregistered daemon %d attempted access\n", did->
unique);
01315
return XP_ERROR_PERMISSION;
01316 }
01317
01318 s =
dazuko_find_slot(did, 1,
NULL);
01319
if (s ==
NULL)
01320 {
01321
call_xp_print(
"dazuko: unregistered daemon %d attempted access\n", did->
unique);
01322
return XP_ERROR_PERMISSION;
01323 }
01324
01325
call_xp_print(
"dazuko: warning: daemon %d is using a deprecated protocol\n", did->
unique);
01326 }
01327
break;
01328 }
01329
01330
01331
switch (opt)
01332 {
01333
case UNREGISTER:
01334 error =
_dazuko_unregister_daemon(did);
01335
if (error)
01336
return error;
01337
break;
01338
01339
case SET_ACCESS_MASK:
01340 memcpy(&
access_mask, (
char *)param,
sizeof(
char));
01341
break;
01342
01343
case ADD_INCLUDE_PATH:
01344 error =
dazuko_insert_path_fs(&
incl_paths, (
char *)param, len);
01345
if (error)
01346
return error;
01347
break;
01348
01349
case ADD_EXCLUDE_PATH:
01350 error =
dazuko_insert_path_fs(&
excl_paths, (
char *)param, len);
01351
if (error)
01352
return error;
01353
break;
01354
01355
case REMOVE_ALL_PATHS:
01356
dazuko_remove_all_paths();
01357
break;
01358
01359
default:
01360
call_xp_print(
"dazuko: daemon %d requested unknown set %d (possible bug)\n", did->
unique, opt);
01361
break;
01362 }
01363
01364
return 0;
01365 }
01366
01367 static int dazuko_handle_request(
struct dazuko_request *request,
struct xp_daemon_id *xp_id)
01368 {
01369
char *value1;
01370
char *value2;
01371
int error = 0;
01372
int type;
01373
struct slot *s;
01374
struct daemon_id did;
01375
01376
if (request ==
NULL || xp_id ==
NULL)
01377
return -1;
01378
01379 type = request->
type[0] + (256 * request->
type[1]);
01380
01381
switch (type)
01382 {
01383
case REGISTER:
01384
01385
01386
01387
if (request->
buffer_size <= 0)
01388
return -1;
01389
01390
if (request->
reply_buffer_size <= 0)
01391
return -1;
01392
01393
if (
dazuko_get_value(
"\nGN=", request->
buffer, &value1) != 0)
01394
return -1;
01395
01396
if (
dazuko_get_value(
"\nRM=", request->
buffer, &value2) != 0)
01397 {
01398
call_xp_free(value1);
01399
return -1;
01400 }
01401
01402 did.
xp_id =
call_xp_id_copy(xp_id);
01403 did.
unique = 0;
01404
01405 error =
dazuko_register_daemon(&did, value1,
dazuko_strlen(value1),
dazuko_strchr(value2,
'W') !=
NULL);
01406
01407
dazuko_clear_replybuffer(request);
01408
dazuko_add_keyvalue_to_replybuffer(request,
"\nID=", &(did.
unique),
'd');
01409
dazuko_close_replybuffer(request);
01410
01411
call_xp_free(value1);
01412
call_xp_free(value2);
01413
call_xp_id_free(did.
xp_id);
01414
01415
break;
01416
01417
case UNREGISTER:
01418
01419
01420
if (request->
buffer_size <= 0)
01421
return -1;
01422
01423
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01424
return -1;
01425
01426 did.
xp_id =
call_xp_id_copy(xp_id);
01427 did.
unique =
dazuko_strtol(value1);
01428
01429 error =
dazuko_set_option(&did,
UNREGISTER,
NULL, 0);
01430
01431
call_xp_free(value1);
01432
call_xp_id_free(did.
xp_id);
01433
01434
break;
01435
01436
case SET_ACCESS_MASK:
01437
01438
01439
if (request->
buffer_size <= 0)
01440
return -1;
01441
01442
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01443
return -1;
01444
01445
if (
dazuko_get_value(
"\nAM=", request->
buffer, &value2) != 0)
01446 {
01447
call_xp_free(value1);
01448
return -1;
01449 }
01450
01451
access_mask = (
char)
dazuko_strtol(value2);
01452
01453
call_xp_free(value1);
01454
call_xp_free(value2);
01455
01456
break;
01457
01458
case ADD_INCLUDE_PATH:
01459
01460
01461
if (request->
buffer_size <= 0)
01462
return -1;
01463
01464
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01465
return -1;
01466
01467
if (
dazuko_get_value(
"\nPT=", request->
buffer, &value2) != 0)
01468 {
01469
call_xp_free(value1);
01470
return -1;
01471 }
01472
01473 did.
xp_id =
call_xp_id_copy(xp_id);
01474 did.
unique =
dazuko_strtol(value1);
01475
01476 error =
dazuko_set_option(&did,
ADD_INCLUDE_PATH, value2,
dazuko_strlen(value2));
01477
01478
call_xp_free(value1);
01479
call_xp_free(value2);
01480
call_xp_id_free(did.
xp_id);
01481
01482
break;
01483
01484
case ADD_EXCLUDE_PATH:
01485
01486
01487
if (request->
buffer_size <= 0)
01488
return -1;
01489
01490
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01491
return -1;
01492
01493
if (
dazuko_get_value(
"\nPT=", request->
buffer, &value2) != 0)
01494 {
01495
call_xp_free(value1);
01496
return -1;
01497 }
01498
01499 did.
xp_id =
call_xp_id_copy(xp_id);
01500 did.
unique =
dazuko_strtol(value1);
01501
01502 error =
dazuko_set_option(&did,
ADD_EXCLUDE_PATH, value2,
dazuko_strlen(value2));
01503
01504
call_xp_free(value1);
01505
call_xp_free(value2);
01506
call_xp_id_free(did.
xp_id);
01507
01508
break;
01509
01510
case REMOVE_ALL_PATHS:
01511
01512
01513
if (request->
buffer_size <= 0)
01514
return -1;
01515
01516
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01517
return -1;
01518
01519 did.
xp_id =
call_xp_id_copy(xp_id);
01520 did.
unique =
dazuko_strtol(value1);
01521
01522 error =
dazuko_set_option(&did,
REMOVE_ALL_PATHS,
NULL, 0);
01523
01524
call_xp_free(value1);
01525
call_xp_id_free(did.
xp_id);
01526
01527
break;
01528
01529
case GET_AN_ACCESS:
01530
01531
01532
01533
if (request->
buffer_size <= 0)
01534
return -1;
01535
01536
if (request->
reply_buffer_size <= 0)
01537
return -1;
01538
01539
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01540
return -1;
01541
01542 did.
xp_id =
call_xp_id_copy(xp_id);
01543 did.
unique =
dazuko_strtol(value1);
01544
01545
call_xp_free(value1);
01546
01547
01548 s =
dazuko_get_an_access(&did);
01549
01550
if (s ==
NULL)
01551 {
01552
call_xp_id_free(did.
xp_id);
01553
return XP_ERROR_INTERRUPT;
01554 }
01555
01556
01557
01558
01559
01560
dazuko_clear_replybuffer(request);
01561
dazuko_add_keyvalue_to_replybuffer(request,
"\nEV=", &(s->event),
'd');
01562
dazuko_add_esc_to_replybuffer(request,
"\nFN=", &(s->filename));
01563
01564
if (s->event_p.set_uid)
01565
dazuko_add_keyvalue_to_replybuffer(request,
"\nUI=", &(s->event_p.uid),
'd');
01566
01567
if (s->event_p.set_pid)
01568
dazuko_add_keyvalue_to_replybuffer(request,
"\nPI=", &(s->event_p.pid),
'd');
01569
01570
if (s->event_p.set_flags)
01571
dazuko_add_keyvalue_to_replybuffer(request,
"\nFL=", &(s->event_p.flags),
'd');
01572
01573
if (s->event_p.set_mode)
01574
dazuko_add_keyvalue_to_replybuffer(request,
"\nMD=", &(s->event_p.mode),
'd');
01575
01576
if (s->file_p.set_size)
01577
dazuko_add_keyvalue_to_replybuffer(request,
"\nFS=", &(s->file_p.size),
'l');
01578
01579
if (s->file_p.set_uid)
01580
dazuko_add_keyvalue_to_replybuffer(request,
"\nFU=", &(s->file_p.uid),
'd');
01581
01582
if (s->file_p.set_gid)
01583
dazuko_add_keyvalue_to_replybuffer(request,
"\nFG=", &(s->file_p.gid),
'd');
01584
01585
if (s->file_p.set_mode)
01586
dazuko_add_keyvalue_to_replybuffer(request,
"\nFM=", &(s->file_p.mode),
'd');
01587
01588
if (s->file_p.set_device_type)
01589
dazuko_add_keyvalue_to_replybuffer(request,
"\nDT=", &(s->file_p.device_type),
'd');
01590
01591
dazuko_close_replybuffer(request);
01592
01593
01594
01595
01596
01597
if (!(s->write_mode))
01598 {
01599
01600
01601
01602
call_xp_up(&(s->mutex));
01603
01604
01605
dazuko_return_access(&did, 0, s);
01606 }
01607
else
01608 {
01609
call_xp_up(&(s->mutex));
01610
01611 }
01612
01613
call_xp_id_free(did.
xp_id);
01614
01615
break;
01616
01617
case RETURN_AN_ACCESS:
01618
01619
01620
if (request->
buffer_size <= 0)
01621
return -1;
01622
01623
if (
dazuko_get_value(
"\nID=", request->
buffer, &value1) != 0)
01624
return -1;
01625
01626
if (
dazuko_get_value(
"\nDN=", request->
buffer, &value2) != 0)
01627 {
01628
call_xp_free(value1);
01629
return -1;
01630 }
01631
01632 did.
xp_id =
call_xp_id_copy(xp_id);
01633 did.
unique =
dazuko_strtol(value1);
01634
01635 error =
dazuko_return_access(&did,
dazuko_strtol(value2),
NULL);
01636
01637
call_xp_free(value1);
01638
call_xp_free(value2);
01639
call_xp_id_free(did.
xp_id);
01640
01641
break;
01642
01643
default:
01644
call_xp_print(
"dazuko: daemon made unknown request %d (possible bug)\n", type);
01645
01646
break;
01647 }
01648
01649
return error;
01650 }
01651
01652 int dazuko_handle_user_request(
struct dazuko_request *user_request,
struct xp_daemon_id *xp_id)
01653 {
01654
int error = 0;
01655
struct dazuko_request *request;
01656
struct dazuko_request *temp_request;
01657
01658
if (user_request ==
NULL || xp_id ==
NULL)
01659
return XP_ERROR_FAULT;
01660
01661
01662 request = (
struct dazuko_request *)
call_xp_malloc(
sizeof(
struct dazuko_request));
01663
if (request ==
NULL)
01664
return XP_ERROR_FAULT;
01665
01666
01667
01668
01669 temp_request = (
struct dazuko_request *)
call_xp_malloc(
sizeof(
struct dazuko_request));
01670
if (request ==
NULL)
01671 {
01672 error =
XP_ERROR_FAULT;
01673
goto dazuko_handle_user_request_out0;
01674 }
01675
01676
01677
01678
01679
if (
call_xp_copyin(user_request, temp_request,
sizeof(
struct dazuko_request)) != 0)
01680 {
01681 error =
XP_ERROR_FAULT;
01682
goto dazuko_handle_user_request_out1;
01683 }
01684
01685 memcpy(request->type, temp_request->type,
sizeof(
char[2]));
01686 request->buffer_size = temp_request->buffer_size;
01687
01688
01689
if (request->buffer_size < 0 || request->buffer_size > 8192)
01690 {
01691 error =
XP_ERROR_FAULT;
01692
goto dazuko_handle_user_request_out1;
01693 }
01694
01695 request->reply_buffer_size = temp_request->reply_buffer_size;
01696
01697
01698
if (request->reply_buffer_size < 0 || request->reply_buffer_size > 8192)
01699 {
01700 error = EPERM;
01701
goto dazuko_handle_user_request_out1;
01702 }
01703
01704
01705 request->buffer = (
char *)
call_xp_malloc(request->buffer_size + 1);
01706
if (request->buffer ==
NULL)
01707 {
01708 error =
XP_ERROR_FAULT;
01709
goto dazuko_handle_user_request_out1;
01710 }
01711
01712
01713
01714
if (request->reply_buffer_size > 0)
01715 {
01716
01717 request->reply_buffer = (
char *)
call_xp_malloc(request->reply_buffer_size + 1);
01718
if (request->reply_buffer ==
NULL)
01719 {
01720 error =
XP_ERROR_FAULT;
01721
goto dazuko_handle_user_request_out2;
01722 }
01723
01724
01725
01726 request->reply_buffer_size_used = 0;
01727 }
01728
01729
01730
if (
call_xp_copyin(temp_request->buffer, request->buffer, request->buffer_size) != 0)
01731 {
01732 error =
XP_ERROR_FAULT;
01733
goto dazuko_handle_user_request_out3;
01734 }
01735
01736 request->buffer[request->buffer_size] = 0;
01737
01738 error =
dazuko_handle_request(request, xp_id);
01739
01740
if (error == 0 && request->reply_buffer_size > 0)
01741 {
01742 request->reply_buffer[request->reply_buffer_size] = 0;
01743
01744 temp_request->reply_buffer_size_used = request->reply_buffer_size_used;
01745
01746
if (
call_xp_copyout(temp_request, user_request,
sizeof(
struct dazuko_request)) != 0)
01747 {
01748 error =
XP_ERROR_FAULT;
01749
goto dazuko_handle_user_request_out3;
01750 }
01751
01752
if (request->reply_buffer_size_used > 0)
01753 {
01754
if (
call_xp_copyout(request->reply_buffer, temp_request->reply_buffer, request->reply_buffer_size_used) != 0)
01755 {
01756 error =
XP_ERROR_FAULT;
01757
goto dazuko_handle_user_request_out3;
01758 }
01759 }
01760 }
01761
01762 dazuko_handle_user_request_out3:
01763
if (request->reply_buffer_size > 0)
01764
call_xp_free(request->reply_buffer);
01765 dazuko_handle_user_request_out2:
01766
call_xp_free(request->buffer);
01767 dazuko_handle_user_request_out1:
01768
call_xp_free(temp_request);
01769 dazuko_handle_user_request_out0:
01770
call_xp_free(request);
01771
01772
return error;
01773 }
01774
01775 int dazuko_handle_user_request_compat12(
void *ptr,
int cmd,
struct xp_daemon_id *xp_id)
01776 {
01777
struct access_compat12 *user_request12;
01778
struct access_compat12 *temp_request12;
01779
int error = 0;
01780
struct slot *s;
01781
char *k_param;
01782
struct daemon_id did;
01783
int temp_length;
01784
int temp_int;
01785
01786
if (ptr ==
NULL || xp_id ==
NULL)
01787
return XP_ERROR_FAULT;
01788
01789 did.
xp_id =
call_xp_id_copy(xp_id);
01790 did.
unique = -1;
01791
01792
switch (cmd)
01793 {
01794
case IOCTL_GET_AN_ACCESS:
01795
01796
01797
01798
01799
01800
01801 user_request12 = (
struct access_compat12 *)ptr;
01802
01803 error =
call_xp_verify_user_writable(user_request12,
sizeof(
struct access_compat12));
01804
if (error)
01805 {
01806 error =
XP_ERROR_FAULT;
01807
break;
01808 }
01809
01810
01811 s =
dazuko_get_an_access(&did);
01812
01813
if (s ==
NULL)
01814 {
01815 error =
XP_ERROR_INTERRUPT;
01816
break;
01817 }
01818
01819
01820
01821
01822
01823
01824
if (s->filenamelength >=
DAZUKO_FILENAME_MAX_LENGTH_COMPAT12)
01825 {
01826
01827
01828 s->filename[
DAZUKO_FILENAME_MAX_LENGTH_COMPAT12 - 1] = 0;
01829 temp_length =
DAZUKO_FILENAME_MAX_LENGTH_COMPAT12;
01830 }
01831
else
01832 {
01833 temp_length = s->filenamelength + 1;
01834 }
01835
01836 temp_request12 = (
struct access_compat12 *)
call_xp_malloc(
sizeof(
struct access_compat12));
01837
if (temp_request12 ==
NULL)
01838 {
01839 error =
XP_ERROR_FAULT;
01840 }
01841
else if (
call_xp_copyin(user_request12, temp_request12,
sizeof(
struct access_compat12)) != 0)
01842 {
01843 error =
XP_ERROR_FAULT;
01844 }
01845
01846
if (error == 0)
01847 {
01848 temp_request12->event = s->event;
01849 temp_request12->o_flags = s->event_p.flags;
01850 temp_request12->o_mode = s->event_p.mode;
01851 temp_request12->uid = s->event_p.uid;
01852 temp_request12->pid = s->event_p.pid;
01853 memcpy(temp_request12->filename, s->filename, temp_length);
01854
01855
if (
call_xp_copyout(temp_request12, user_request12,
sizeof(
struct access_compat12)) != 0)
01856 {
01857 error =
XP_ERROR_FAULT;
01858 }
01859 }
01860
01861
call_xp_up(&(s->mutex));
01862
01863
01864
if (error)
01865 {
01866
dazuko_state_error(s,
DAZUKO_WORKING);
01867 }
01868
01869
if (temp_request12 !=
NULL)
01870 {
01871
call_xp_free(temp_request12);
01872 }
01873
01874
break;
01875
01876
case IOCTL_RETURN_ACCESS:
01877
01878
01879
01880
01881 user_request12 = (
struct access_compat12 *)ptr;
01882
01883 error =
call_xp_verify_user_readable(user_request12,
sizeof(
struct access_compat12));
01884
if (error)
01885 {
01886 error =
XP_ERROR_FAULT;
01887
break;
01888 }
01889
01890 temp_request12 = (
struct access_compat12 *)
call_xp_malloc(
sizeof(
struct access_compat12));
01891
if (temp_request12 ==
NULL)
01892 {
01893 error =
XP_ERROR_FAULT;
01894
break;
01895 }
01896
01897
if (
call_xp_copyin(user_request12, temp_request12,
sizeof(
struct access_compat12)) != 0)
01898 {
01899 error =
XP_ERROR_FAULT;
01900 }
01901
01902 temp_int = temp_request12->deny;
01903
01904
call_xp_free(temp_request12);
01905
01906 error =
dazuko_return_access(&did, temp_int,
NULL);
01907
break;
01908
01909
case IOCTL_SET_OPTION:
01910
01911
01912
01913 error =
call_xp_verify_user_readable(ptr, 2*
sizeof(
int));
01914
if (error)
01915 {
01916 error =
XP_ERROR_FAULT;
01917
break;
01918 }
01919
01920
01921
if (
call_xp_copyin(ptr, &temp_int,
sizeof(
int)) != 0)
01922 {
01923 error =
XP_ERROR_FAULT;
01924
break;
01925 }
01926
01927 ptr = ((
char *)ptr +
sizeof(
int));
01928
01929
01930
if (
call_xp_copyin(ptr, &temp_length,
sizeof(
int)) != 0)
01931 {
01932 error =
XP_ERROR_FAULT;
01933
break;
01934 }
01935
01936
01937
if (temp_length < 0 || temp_length > 4096)
01938 {
01939 error =
XP_ERROR_INVALID;
01940
break;
01941 }
01942
01943 ptr = ((
char *)ptr +
sizeof(
int));
01944
01945 error =
call_xp_verify_user_readable(ptr, temp_length);
01946
if (error)
01947 {
01948 error =
XP_ERROR_FAULT;
01949
break;
01950 }
01951
01952 k_param = (
char *)
call_xp_malloc(temp_length + 1);
01953
if (k_param ==
NULL)
01954 {
01955 error =
XP_ERROR_FAULT;
01956
break;
01957 }
01958
01959
01960
01961
if (
call_xp_copyin(ptr, k_param, temp_length) != 0)
01962 {
01963
call_xp_free(k_param);
01964 error =
XP_ERROR_FAULT;
01965
break;
01966 }
01967
01968 k_param[temp_length] = 0;
01969
01970
if (temp_int ==
REGISTER)
01971 error =
dazuko_register_daemon(&did, k_param, temp_length, 1);
01972
else
01973 error =
dazuko_set_option(&did, temp_int, k_param, temp_length);
01974
01975
call_xp_free(k_param);
01976
01977
break;
01978
01979
default:
01980
call_xp_print(
"dazuko: daemon requested unknown device_ioctl %d (possible bug)\n", cmd);
01981
01982
break;
01983 }
01984
01985
call_xp_id_free(did.
xp_id);
01986
01987
return error;
01988 }
01989
01990 static struct slot *
dazuko_get_and_hold_ready_slot(
struct slot_list *sl)
01991 {
01992
01993
01994
01995
01996
01997
01998
01999
02000
int i;
02001
struct slot *s;
02002
02003
for (i=0 ; i<
NUM_SLOTS ; i++)
02004 {
02005 s = &(sl->
slots[i]);
02006
02007
if (
dazuko_change_slot_state(s,
DAZUKO_READY,
DAZUKO_WAITING, 0))
02008 {
02009
02010
return s;
02011 }
02012 }
02013
02014
02015
02016
return NULL;
02017 }
02018
02019 static int get_ready_slot_condition(
void *param)
02020 {
02021
return ((((
struct get_ready_slot_condition_param *)param)->slot =
dazuko_get_and_hold_ready_slot(((
struct get_ready_slot_condition_param *)param)->slotlist)) !=
NULL
02022 ||
call_xp_atomic_read(&
active) == 0
02023 ||
call_xp_atomic_read(&(((
struct get_ready_slot_condition_param *)param)->slotlist->use_count)) == 0);
02024 }
02025
02026 static int dazuko_run_daemon_on_slotlist(
int event,
char *filename,
int filenamelength,
struct event_properties *event_p,
struct file_properties *file_p,
int prev_response,
struct slot_list *sl)
02027 {
02028
02029
02030
02031
int rc;
02032
int unique;
02033
struct slot *s;
02034
struct get_ready_slot_condition_param cond_p1;
02035
struct two_slot_state_not_condition_param cond_p2;
02036
02037 begin:
02038
02039
02040
02041
02042 s =
NULL;
02043
02044
02045 cond_p1.
slotlist = sl;
02046 cond_p1.
slot = s;
02047
if (
call_xp_wait_until_condition(&
wait_kernel_waiting_for_free_slot,
get_ready_slot_condition, &cond_p1, 0) != 0)
02048 {
02049
02050
02051
02052
02053
DPRINT((
"dazuko: kernel process %d killed while waiting for free slot\n", event_p->
pid));
02054
02055
return -1;
02056 }
02057
02058
02059
02060
02061
02062 s = cond_p1.
slot;
02063
02064
if (s ==
NULL)
02065 {
02066
02067
02068
02069
02070
return 0;
02071 }
02072
02073
02074
02075
02076
02077
02078 unique = s->
did.
unique;
02079
02080
02081
02082
02083
02084
02085 s->filename = filename;
02086 s->event = event;
02087 s->response = prev_response;
02088 s->filenamelength = filenamelength;
02089
02090
if (event_p ==
NULL)
02091
dazuko_bzero(&(s->event_p),
sizeof(
struct event_properties));
02092
else
02093 memcpy(&(s->event_p), event_p,
sizeof(
struct event_properties));
02094
02095
if (file_p ==
NULL)
02096
dazuko_bzero(&(s->file_p),
sizeof(
struct file_properties));
02097
else
02098 memcpy(&(s->file_p), file_p,
sizeof(
struct file_properties));
02099
02100
02101
call_xp_up(&(s->mutex));
02102
02103
02104
02105
call_xp_notify(&
wait_daemon_waiting_for_work);
02106
02107
02108 cond_p2.
slot1 = s;
02109 cond_p2.
state1 =
DAZUKO_WAITING;
02110 cond_p2.
slot2 = s;
02111 cond_p2.
state2 =
DAZUKO_WORKING;
02112
if (
call_xp_wait_until_condition(&
wait_kernel_waiting_while_daemon_works,
two_slot_state_not_condition, &cond_p2, 0) != 0)
02113 {
02114
02115
02116
02117
02118
DPRINT((
"dazuko: kernel process %d killed while waiting for daemon response\n", event_p->
pid));
02119
02120
02121
02122
02123
dazuko_change_slot_state(s,
DAZUKO_FREE,
DAZUKO_FREE, 1);
02124
02125
return -1;
02126 }
02127
02128
02129
02130
02131
if (
call_xp_down(&(s->mutex)) != 0)
02132 {
02133
return -1;
02134 }
02135
02136
02137
if (s->did.unique != unique)
02138 {
02139
02140
02141
02142
call_xp_up(&(s->mutex));
02143
02144
goto begin;
02145 }
02146
02147
02148
if (!
__dazuko_change_slot_state(s,
DAZUKO_DONE,
DAZUKO_FREE))
02149 {
02150
02151
02152
02153
call_xp_up(&(s->mutex));
02154
02155
goto begin;
02156 }
02157
02158
02159 rc = s->response;
02160
02161
call_xp_up(&(s->mutex));
02162
02163
02164
02165
02166
return rc;
02167 }
02168
02169 static int dazuko_run_daemon(
int event,
char *filename,
int filenamelength,
struct event_properties *event_p,
struct file_properties *file_p)
02170 {
02171
struct slot_list *sl;
02172
int i;
02173
int rc = 0;
02174
int error;
02175
02176
if (event_p !=
NULL)
02177 {
02178
if (event_p->
thrown)
02179
return 0;
02180 event_p->
thrown = 1;
02181 }
02182
02183
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
02184 {
02185
02186
02187
if (
call_xp_down(&(
slot_lists[i].mutex)) != 0)
02188
return XP_ERROR_INTERRUPT;
02189
02190 sl =
slot_lists[i].
slot_list;
02191
02192
call_xp_up(&(
slot_lists[i].mutex));
02193
02194
02195
if (sl !=
NULL)
02196 {
02197 error =
dazuko_run_daemon_on_slotlist(event, filename, filenamelength, event_p, file_p, rc, sl);
02198
02199
if (error < 0)
02200 {
02201
02202 rc = error;
02203
break;
02204 }
02205
else if (error > 0)
02206 {
02207
02208 rc = 1;
02209 }
02210 }
02211 }
02212
02213
return rc;
02214 }
02215
02216 inline int dazuko_is_our_daemon(
struct xp_daemon_id *xp_id)
02217 {
02218
02219
02220
02221
struct daemon_id did;
02222
int ret;
02223
02224 did.
xp_id =
call_xp_id_copy(xp_id);
02225 did.
unique = -1;
02226
02227 ret = (
dazuko_find_slot(&did, 1,
NULL) !=
NULL);
02228
02229
call_xp_id_free(did.
xp_id);
02230
02231
return ret;
02232 }
02233
02234 static int dazuko_is_selected(
char *filename,
int len)
02235 {
02236
02237
02238
02239
02240
struct path *
path;
02241
02242
02243
02244
02245
02246
call_xp_read_lock(&
lock_lists);
02247
02248
02249
for (
path=
incl_paths ;
path ;
path=
path->
next)
02250 {
02251
02252
if (
path->len <= len)
02253 {
02254
02255
if (memcmp(
path->path, filename,
path->len) == 0)
02256
break;
02257 }
02258 }
02259
02260
02261
02262
02263
if (!
path)
02264 {
02265
call_xp_read_unlock(&
lock_lists);
02266
02267
return 0;
02268 }
02269
02270
02271
for (
path=
excl_paths ;
path ;
path=
path->
next)
02272 {
02273
02274
if (
path->len <= len)
02275 {
02276
02277
if (memcmp(
path->path,filename,
path->len) == 0)
02278
break;
02279 }
02280 }
02281
02282
call_xp_read_unlock(&
lock_lists);
02283
02284
02285
02286
02287
if (
path)
02288
return 0;
02289
02290
02291
02292
return 1;
02293 }
02294
02295 static int dazuko_add_hash(
struct xp_file *file,
char *filename,
int len)
02296 {
02297
02298
02299
02300
struct hash *h;
02301
02302
02303 h = (
struct hash *)
call_xp_malloc(
sizeof(
struct hash) + len);
02304
if (!h)
02305
return XP_ERROR_FAULT;
02306
02307
02308
02309
call_xp_copy_file(&(h->file), file);
02310 h->dirty = 0;
02311 h->namelen = len;
02312 memcpy(h->name, filename, len);
02313 h->name[len] = 0;
02314
02315
02316
02317
02318
02319
call_xp_write_lock(&
lock_hash);
02320 h->next =
hash;
02321
hash = h;
02322
call_xp_write_unlock(&
lock_hash);
02323
02324
return 0;
02325 }
02326
02327
02328 static void dazuko_mark_hash_dirty(
struct xp_file *file)
02329 {
02330
struct hash *h =
NULL;
02331
struct hash *entry =
NULL;
02332
struct hash *prev =
NULL;
02333
struct hash *prev_entry =
NULL;
02334
02335
02336
call_xp_write_lock(&
lock_hash);
02337
02338
for (h=
hash ; h ; h=h->next)
02339 {
02340
02341
if (h->dirty)
02342 {
02343 entry =
NULL;
02344
break;
02345 }
02346
02347
if (
call_xp_compare_file(&(h->file), file) == 0)
02348 {
02349
02350
02351 prev_entry = prev;
02352 entry = h;
02353
break;
02354 }
02355
02356 prev = h;
02357 }
02358
02359
if (entry)
02360 {
02361
if (!entry->dirty)
02362 {
02363
02364 entry->dirty = 1;
02365
02366
02367
02368
02369
if (entry->next)
02370 {
02371
if (!entry->next->dirty)
02372 {
02373
for (h=entry->next ; h ; h=h->next)
02374 {
02375
if (h->dirty)
02376
break;
02377
02378 prev = h;
02379 }
02380
02381
02382
if (prev_entry)
02383 prev_entry->next = entry->next;
02384
else
02385
hash = entry->
next;
02386
02387
if (prev ==
NULL)
02388 {
02389
02390 entry->
next =
hash;
02391
hash = entry;
02392 }
02393
else if (h)
02394 {
02395
02396 entry->
next = prev->
next;
02397 prev->
next = entry;
02398 }
02399
else
02400 {
02401
02402 entry->
next =
NULL;
02403 prev->next = entry;
02404 }
02405 }
02406 }
02407 }
02408 }
02409
02410
call_xp_write_unlock(&
lock_hash);
02411
02412
02413 }
02414
02415 static struct hash *
dazuko_get_hash(
struct xp_file *file)
02416 {
02417
02418
02419
02420
02421
struct hash *prev;
02422
struct hash *cur;
02423
02424
02425
call_xp_write_lock(&
lock_hash);
02426
02427 prev =
NULL;
02428 cur =
hash;
02429
while (cur)
02430 {
02431
if (
call_xp_compare_file(&(cur->file), file) == 0)
02432 {
02433
02434
02435
02436
if (!prev)
02437
hash = cur->
next;
02438
else
02439 prev->
next = cur->
next;
02440
break;
02441 }
02442
02443 prev = cur;
02444 cur = cur->
next;
02445 }
02446
02447
call_xp_write_unlock(&
lock_hash);
02448
02449
02450
return cur;
02451 }
02452
02453 inline int dazuko_get_filename_length(
char *filename)
02454 {
02455
int len;
02456
02457
for (len=0 ; filename[len] ; len++);
02458
02459
return len;
02460 }
02461
02462 static int dazuko_should_scan(
struct dazuko_file_struct *kfs)
02463 {
02464
02465
02466
02467
02468
02469
int result = 0;
02470
02471
02472
switch (kfs->
should_scan)
02473 {
02474
02475
02476
02477
02478
02479
case 1:
02480
02481
return 1;
02482
02483
case 2:
02484
02485
return 0;
02486 }
02487
02488
02489
if (
call_xp_file_struct_check(kfs) == 0)
02490 {
02491
if (
dazuko_is_selected(kfs->
filename, kfs->
filename_length))
02492 {
02493
02494
02495
02496
02497
02498
02499 kfs->
should_scan = 1;
02500
02501 result = 1;
02502 }
02503
else
02504 {
02505
02506
02507
02508
02509
02510 kfs->
should_scan = 2;
02511 }
02512 }
02513
02514
call_xp_file_struct_check_cleanup(kfs);
02515
02516
return result;
02517 }
02518
02519 inline int dazuko_sys_check(
unsigned long event,
int daemon_is_allowed,
struct xp_daemon_id *xp_id)
02520 {
02521
02522
switch (event)
02523 {
02524
case DAZUKO_ON_OPEN:
02525
02526
02527
02528
if ((
SCAN_ON_OPEN ||
SCAN_ON_CLOSE ||
SCAN_ON_CLOSE_MODIFIED) == 0)
02529
return -1;
02530
break;
02531
02532
case DAZUKO_ON_CLOSE:
02533
02534
02535
if ((
SCAN_ON_CLOSE ||
SCAN_ON_CLOSE_MODIFIED) == 0)
02536
return -1;
02537
break;
02538
02539
default:
02540
if ((
access_mask & event) == 0)
02541
return -1;
02542
break;
02543 }
02544
02545
02546
if (
call_xp_atomic_read(&
active) <= 0)
02547
return -1;
02548
02549
02550
if (daemon_is_allowed)
02551 {
02552
if (
dazuko_is_our_daemon(xp_id))
02553 {
02554
02555
02556
02557
return -1;
02558 }
02559 }
02560
02561
return 0;
02562 }
02563
02564 inline int dazuko_sys_pre(
unsigned long event,
struct dazuko_file_struct *kfs,
struct event_properties *event_p)
02565 {
02566
02567
02568
02569
02570
02571
02572
int error = 0;
02573
02574
switch (event)
02575 {
02576
case DAZUKO_ON_OPEN:
02577
02578
02579
02580
if (!
SCAN_ON_OPEN)
02581
return 0;
02582
break;
02583
02584
case DAZUKO_ON_CLOSE:
02585
02586
02587
return 0;
02588
02589
case DAZUKO_ON_CLOSE_MODIFIED:
02590
02591
02592
return 0;
02593
02594
default:
02595
break;
02596 }
02597
02598
if (kfs ==
NULL)
02599 {
02600
02601
02602
02603
return 0;
02604 }
02605
02606
02607
if (
dazuko_should_scan(kfs))
02608 {
02609 error =
dazuko_run_daemon(event, kfs->
filename, kfs->
filename_length, event_p, &(kfs->
file_p));
02610 }
02611
02612
if (error > 0)
02613 {
02614
02615
02616
02617
02618
return XP_ERROR_PERMISSION;
02619 }
02620
else if (error < 0)
02621 {
02622
02623
02624
02625
02626
return XP_ERROR_INTERRUPT;
02627 }
02628
02629
02630
02631
return 0;
02632 }
02633
02634 inline int dazuko_sys_post(
unsigned long event,
struct dazuko_file_struct *kfs,
struct xp_file *file,
struct event_properties *event_p)
02635 {
02636
struct hash *h =
NULL;
02637
02638
switch (event)
02639 {
02640
case DAZUKO_ON_OPEN:
02641
02642
02643
02644
if ((
call_xp_atomic_read(&
active) > 0) && file !=
NULL && kfs !=
NULL)
02645 {
02646
if (
SCAN_ON_OPEN ||
SCAN_ON_CLOSE ||
SCAN_ON_CLOSE_MODIFIED)
02647 {
02648
02649
if (
dazuko_should_scan(kfs))
02650 {
02651
02652
if (file !=
NULL)
02653
dazuko_add_hash(file, kfs->
filename, kfs->
filename_length);
02654
02655
dazuko_run_daemon(event, kfs->
filename, kfs->
filename_length, event_p, &(kfs->
file_p));
02656 }
02657 }
02658 }
02659
break;
02660
02661
case DAZUKO_ON_CLOSE:
02662
if (file !=
NULL)
02663 {
02664
02665 h =
dazuko_get_hash(file);
02666
02667
02668
02669
if (h !=
NULL)
02670 {
02671
02672
02673
02674
02675
if (
SCAN_ON_CLOSE_MODIFIED && h->dirty)
02676
dazuko_run_daemon(
DAZUKO_ON_CLOSE_MODIFIED, h->name, h->namelen, event_p,
NULL);
02677
else if (
SCAN_ON_CLOSE)
02678
dazuko_run_daemon(
DAZUKO_ON_CLOSE, h->name, h->namelen, event_p,
NULL);
02679
02680
02681
call_xp_free(h);
02682 }
02683 }
02684
else
02685 {
02686
if (
SCAN_ON_CLOSE)
02687 {
02688
if (
dazuko_should_scan(kfs))
02689 {
02690
dazuko_run_daemon(
DAZUKO_ON_CLOSE, kfs->
filename, kfs->
filename_length, event_p, &(kfs->
file_p));
02691 }
02692 }
02693 }
02694
break;
02695
02696
case DAZUKO_ON_CLOSE_MODIFIED:
02697
if (file !=
NULL)
02698 {
02699
02700
02701
02702
02703
dazuko_mark_hash_dirty(file);
02704 }
02705
break;
02706
02707
default:
02708
break;
02709 }
02710
02711
return 0;
02712 }
02713
02714 inline int dazuko_init(
void)
02715 {
02716
int i;
02717
int error;
02718
02719
call_xp_init_mutex(&
mutex_unique_count);
02720
02721
call_xp_init_rwlock(&
lock_hash);
02722
call_xp_init_rwlock(&
lock_lists);
02723
02724
call_xp_init_queue(&
wait_kernel_waiting_for_free_slot);
02725
call_xp_init_queue(&
wait_daemon_waiting_for_work);
02726
call_xp_init_queue(&
wait_kernel_waiting_while_daemon_works);
02727
call_xp_init_queue(&
wait_daemon_waiting_for_free);
02728
02729
dazuko_bzero(&
slot_lists,
sizeof(
slot_lists));
02730
02731
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
02732
call_xp_init_mutex(&(
slot_lists[i].mutex));
02733
02734
call_xp_atomic_set(&
active, 0);
02735
02736 error =
call_xp_sys_hook();
02737
02738
if (error == 0)
02739
call_xp_print(
"dazuko: loaded, version=%s\n",
VERSION);
02740
02741
return error;
02742 }
02743
02744 inline int dazuko_exit(
void)
02745 {
02746
int error;
02747
int i;
02748
int j;
02749
02750 i =
call_xp_atomic_read(&
active);
02751
02752
if (i != 0)
02753 {
02754
call_xp_print(
"dazuko: warning: trying to remove Dazuko with %d process%s still registered\n", i, i==1 ?
"" :
"es");
02755
return -1;
02756 }
02757
02758
dazuko_remove_all_paths();
02759
dazuko_remove_all_hash();
02760
02761 error =
call_xp_sys_unhook();
02762
02763
if (error == 0)
02764 {
02765
call_xp_destroy_mutex(&
mutex_unique_count);
02766
02767
call_xp_destroy_rwlock(&
lock_hash);
02768
call_xp_destroy_rwlock(&
lock_lists);
02769
02770
call_xp_destroy_queue(&
wait_kernel_waiting_for_free_slot);
02771
call_xp_destroy_queue(&
wait_daemon_waiting_for_work);
02772
call_xp_destroy_queue(&
wait_kernel_waiting_while_daemon_works);
02773
call_xp_destroy_queue(&
wait_daemon_waiting_for_free);
02774
02775
for (i=0 ; i<
NUM_SLOT_LISTS ; i++)
02776 {
02777
if (
slot_lists[i].
slot_list !=
NULL)
02778 {
02779
if (
call_xp_atomic_read(&(
slot_lists[i].
slot_list->use_count)) != 0)
02780
call_xp_print(
"dazuko: slot_list count was not 0 (possible bug)\n");
02781
02782
for (j=0 ; j<
NUM_SLOTS ; j++)
02783 {
02784
call_xp_destroy_mutex(&(
slot_lists[i].
slot_list->slots[j].
mutex));
02785 }
02786
02787
call_xp_free(
slot_lists[i].
slot_list);
02788
slot_lists[i].
slot_list =
NULL;
02789 }
02790
02791
call_xp_destroy_mutex(&(
slot_lists[i].mutex));
02792 }
02793
02794
call_xp_print(
"dazuko: unloaded, version=%s\n",
VERSION);
02795 }
02796
02797
return error;
02798 }