2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 //%% (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%% (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%% (c) Copyright 1993, 1994 Novell, Inc.
27 //%% $XConsortium: api_spec.C /main/3 1995/10/23 09:54:31 rswiston $
28 /* @(#)api_spec.C 1.15 @(#)
32 * Copyright (c) 1990 by Sun Microsystems, Inc.
35 #include <sys/types.h>
38 #include "api/c/tt_c.h"
39 #include "api/c/api_api.h"
40 #include "api/c/api_mp.h"
41 #include "api/c/api_handle.h"
42 #include "api/c/api_spec_map_ref.h"
43 #include "api/c/api_error.h"
44 #include "db/tt_db_property.h"
45 #include "db/tt_db_access.h"
46 #include "util/tt_audit.h"
47 #include "util/tt_path.h"
49 static Tt_status objid_to_spec(const char *objid, _Tt_objid_spec_ptr &specP);
51 /************************************************************************
52 * Node Functions (FSpec A.7) *
53 ************************************************************************/
56 tt_spec_bprop(const char *objid, const char *propname, int i,
57 unsigned char **value, int *length)
60 Tt_status status = audit.entry("ori", TT_SPEC_BPROP, objid,
63 if (status != TT_OK) {
68 status = _tt_spec_bprop(objid, propname, i, value, length);
76 tt_spec_bprop_add(const char *objid, const char *propname,
77 const unsigned char *value, int length)
80 Tt_status status = audit.entry("ornI", TT_SPEC_BPROP_ADD, objid,
81 propname, value, length);
83 if (status != TT_OK) {
88 status = _tt_spec_bprop_add(objid, propname, value, length);
96 tt_spec_bprop_set(const char *objid, const char *propname,
97 const unsigned char *value, int length)
100 Tt_status status = audit.entry("ornI", TT_SPEC_BPROP_SET, objid,
101 propname, value, length);
103 if (status != TT_OK) {
108 status = _tt_spec_bprop_set(objid, propname, value, length);
116 tt_spec_create(const char *filepath)
119 Tt_status status = audit.entry("C", TT_SPEC_CREATE, filepath);
122 if (status != TT_OK) {
123 audit.exit((char *)error_pointer(status));
124 return (char *)error_pointer(status);
127 result = _tt_spec_create(filepath);
135 tt_spec_destroy(const char *objid)
138 Tt_status status = audit.entry("o", TT_SPEC_DESTROY, objid);
140 if (status != TT_OK) {
145 status = _tt_spec_destroy(objid);
153 tt_spec_file(const char *objid)
156 Tt_status status = audit.entry("o", TT_SPEC_FILE, objid);
159 if (status != TT_OK) {
160 audit.exit((char *)error_pointer(status));
161 return (char *)error_pointer(status);
164 result = _tt_spec_file(objid);
172 tt_spec_move(const char *objid, const char *newfilepath)
175 Tt_status status = audit.entry("oC", TT_SPEC_MOVE, objid,
179 if (status != TT_OK) {
180 audit.exit((char *)error_pointer(status));
181 return (char *)error_pointer(status);
184 result = _tt_spec_move(objid, newfilepath);
192 tt_spec_type_set(const char * objid, const char * otid)
195 Tt_status status = audit.entry("oo", TT_SPEC_TYPE_SET, objid, otid);
197 if (status != TT_OK) {
202 status = _tt_spec_type_set(objid, otid);
210 tt_spec_type(const char * objid)
213 Tt_status status = audit.entry("o", TT_SPEC_PROP, objid);
216 if (status != TT_OK) {
217 audit.exit((char *)error_pointer(status));
218 return (char *)error_pointer(status);
221 result = _tt_spec_type(objid);
229 tt_spec_prop(const char *objid, const char *propname, int i)
232 Tt_status status = audit.entry("ori", TT_SPEC_PROP, objid,
236 if (status != TT_OK) {
237 audit.exit((char *)error_pointer(status));
238 return (char *)error_pointer(status);
241 result = _tt_spec_prop(objid, propname, i);
249 tt_spec_prop_add(const char *objid, const char *propname, const char *value)
252 Tt_status status = audit.entry("ornI", TT_SPEC_PROP_ADD, objid,
254 (char *) 0 == value ? 0 : strlen(value));
256 if (status != TT_OK) {
261 status = _tt_spec_prop_add(objid, propname, value);
269 tt_spec_prop_count(const char *objid, const char *propname)
272 Tt_status status = audit.entry("or", TT_SPEC_PROP_COUNT, objid,
276 if (status != TT_OK) {
277 audit.exit(error_int(status));
278 return error_int(status);
281 result = _tt_spec_prop_count(objid, propname);
289 tt_spec_prop_set(const char *objid, const char *propname, const char *value)
292 Tt_status status = audit.entry("ornI", TT_SPEC_PROP_SET, objid,
294 (char *) 0 == value ? 0 : strlen(value));
296 if (status != TT_OK) {
301 status = _tt_spec_prop_set(objid, propname, value);
309 tt_spec_propname(const char *objid, int n)
312 Tt_status status = audit.entry("oi", TT_SPEC_PROPNAME, objid, n);
315 if (status != TT_OK) {
316 audit.exit((char *)error_pointer(status));
317 return (char *)error_pointer(status);
320 result = _tt_spec_propname(objid, n);
328 tt_spec_propnames_count(const char *objid)
331 Tt_status status = audit.entry("o", TT_SPEC_PROPNAMES_COUNT,
335 if (status != TT_OK) {
336 audit.exit(error_int(status));
337 return error_int(status);
340 result = _tt_spec_propnames_count(objid);
348 tt_spec_write(const char *objid)
351 Tt_status status = audit.entry("o", TT_SPEC_WRITE, objid);
353 if (status != TT_OK) {
358 status = _tt_spec_write(objid);
366 tt_objid_equal(const char *objid1, const char *objid2)
369 Tt_status status = audit.entry("oo", TT_OBJID_EQUAL, objid1,
373 if (status != TT_OK) {
374 audit.exit(error_int(status));
375 return error_int(status);
378 result = _tt_objid_equal(objid1, objid2);
386 tt_objid_objkey(const char *objid)
389 Tt_status status = audit.entry("o", TT_OBJID_OBJKEY, objid);
392 if (status != TT_OK) {
393 audit.exit((char *)error_pointer(status));
394 return (char *)error_pointer(status);
397 result = _tt_objid_objkey(objid);
402 // _tt_spec_bprop() - retrive the `i'-th value, starting at 0, of
403 // the property `propname' specified.
405 _tt_spec_bprop(const char * objid, const char * propname, int i,
406 unsigned char ** value, int * length)
410 _Tt_objid_spec_ptr specP;
412 // find spec for objid
413 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
417 _Tt_db_property_ptr propP;
419 // Initialize return value
420 *value = (unsigned char *)NULL;
422 // get list of values for specified property
423 propP = specP->getProperty(propname);
424 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
430 case TT_ERR_PROPNAME:
433 case TT_WRN_STALE_OBJID:
434 if ((i < 0) || (i > propP->values->count())) {
437 if (propP->values->count() == i) {
441 temp = (*(propP->values))[i];
443 *length = temp.len();
444 *value = (unsigned char *) _tt_strdup((char *) temp,
448 return TT_ERR_INTERNAL;
451 } // end -_tt_spec_bprop()-
455 _tt_spec_bprop_add(const char * objid, const char * propname,
456 unsigned const char * value, int length)
459 _Tt_objid_spec_ptr specP;
460 _Tt_string temp(value, length);
463 // find spec for objid
464 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
468 _Tt_db_property_ptr newPropP = new _Tt_db_property;
472 newPropP->name = propname;
473 newPropP->values->append(temp);
476 specP->addProperty(newPropP);
477 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
479 case TT_WRN_STALE_OBJID:
480 specP->setOnDiskFlag(FALSE);
486 case TT_ERR_PROPNAME:
489 return TT_ERR_INTERNAL;
492 } // end -_tt_spec_bprop_add()-
496 _tt_spec_bprop_set(const char * objid, const char * propname,
497 unsigned const char * value, int length)
500 _Tt_objid_spec_ptr specP;
501 _Tt_string temp(value, length);
503 // find spec for objid
504 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
508 _Tt_db_property_ptr newPropP = new _Tt_db_property;
512 newPropP->name = propname;
513 newPropP->values->append(temp);
515 specP->setProperty(newPropP);
516 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
518 case TT_WRN_STALE_OBJID:
519 specP->setOnDiskFlag(FALSE);
525 case TT_ERR_PROPNAME:
528 return TT_ERR_INTERNAL;
531 } // end -_tt_spec_bprop_set()-
534 // _tt_spec_create()- create a new spec, and associated tt_db_object,
538 _tt_spec_create(const char * filepath)
542 _Tt_db_access_ptr accessP;
543 _Tt_objid_spec_ptr newSpecP = new _Tt_objid_spec; // create a new spec
545 // create new tt_db_object in memory, checking for db error
546 objid = newSpecP->create(filepath);
547 switch (result = _tt_get_api_error(newSpecP->getDBResults(), _TT_API_SPEC)) {
549 case TT_WRN_STALE_OBJID:
557 return (char *)error_pointer(result);
559 return (char *)error_pointer(TT_ERR_INTERNAL);
562 // Make the object so that everyone can read and write it
563 accessP = new _Tt_db_access;
564 accessP->mode = (mode_t)-1;
565 newSpecP->setAccess(accessP);
566 switch (result = _tt_get_api_error(newSpecP->getDBResults(), _TT_API_SPEC)) {
568 case TT_WRN_STALE_OBJID:
575 return (char *)error_pointer(result);
577 return (char *)error_pointer(TT_ERR_INTERNAL);
580 _Tt_api_spec_map_ref specMap;
583 // add new spec to map.
584 specMap.addSpec(newSpecP);
586 return _tt_strdup(objid);
587 } // end -_tt_spec_create()-
590 // _tt_spec_destroy()- destroy a spec, and associated tt_db_object.
593 _tt_spec_destroy(const char * objid)
597 _Tt_objid_spec_ptr specP;
598 _Tt_api_spec_map_ref specMap;
600 // find spec for objid
601 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
605 specP->remove(); // remove associated tt_db_object
606 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
608 case TT_WRN_STALE_OBJID:
617 return TT_ERR_INTERNAL;
619 specMap.deleteSpec(objid);// delete spec from table
621 } // end -_tt_spec_destroy()-
624 // _tt_spec_file()- retrieves the name of the file containing the
625 // object described by the spec.
628 _tt_spec_file(const char * objid)
632 _Tt_objid_spec_ptr specP;
633 _Tt_api_spec_map_ref specMap;
635 // find spec for objid
636 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
637 return (char *)error_pointer(result);
640 filepath = specP->getFile();
641 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
643 case TT_WRN_STALE_OBJID:
649 return (char *)error_pointer(result);
651 return (char *)error_pointer(TT_ERR_INTERNAL);
653 return _tt_strdup(_tt_network_path_to_local_path(filepath));
654 } // end -_tt_spec_file()-
657 // _tt_spec_move()- tell tooltalk service ythat the object has moved
658 // to a different file
661 _tt_spec_move(const char * objid, const char * newfilepath)
665 _Tt_objid_spec_ptr specP;
667 // find spec for objid
668 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
669 return (char *)error_pointer(result);
672 newObjid = specP->move(newfilepath);
673 if ((result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) != TT_OK) {
674 return (char *)error_pointer(result);
676 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
678 case TT_WRN_STALE_OBJID:
679 case TT_WRN_SAME_OBJID:
687 return (char *)error_pointer(result);
689 return (char *)error_pointer(TT_ERR_INTERNAL);
691 return _tt_strdup(newObjid);
692 } // end -_tt_spec_move()-
696 _tt_spec_type_set(const char * objid, const char * otid)
699 _Tt_objid_spec_ptr specP;
702 if (TT_WRN_LAST < (result = _tt_valid_otype(otid))) {
706 // find spec for objid
707 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
711 // set otid on object
712 switch (result = _tt_get_api_error(specP->setType(otid), _TT_API_SPEC)) {
714 case TT_WRN_STALE_OBJID:
719 case TT_ERR_READONLY:
722 return TT_ERR_INTERNAL;
725 } // end -_tt_spec_type_set()-
729 _tt_spec_type(const char * objid)
733 _Tt_objid_spec_ptr specP;
735 // find spec for objid
736 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
737 return (char *)error_pointer(result);
740 objType = specP->getType();
741 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
743 case TT_WRN_STALE_OBJID:
749 return (char *)error_pointer(result);
751 return (char *)error_pointer(TT_ERR_INTERNAL);
753 return _tt_strdup(objType);
754 } // end -_tt_spec_type()-
758 _tt_spec_prop(const char * objid, const char * propname, int i)
762 unsigned char *value;
764 err = _tt_spec_bprop(objid, propname, i, &value, &len);
767 case TT_WRN_STALE_OBJID:
770 return (char *)error_pointer(err);
772 return _tt_strdup((const char *)value);
773 } // end -_tt_spec_prop()-
777 _tt_spec_prop_add(const char * objid, const char * propname, const char * value)
779 return _tt_spec_bprop_add(objid, propname, (unsigned char *)value,
780 (char *) 0 == value ? 0 : strlen(value));
781 } // end -_tt_spec_prop_add()-
785 _tt_spec_prop_count(const char * objid, const char * propname)
788 _Tt_objid_spec_ptr specP;
790 // find spec for objid
791 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
792 return tt_error_int(result);
795 _Tt_db_property_list_ptr propListP;
798 propListP = specP->getProperties();
799 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
801 case TT_WRN_STALE_OBJID:
807 case TT_ERR_PROPNAME:
809 return tt_error_int(result);
811 return tt_error_int(TT_ERR_INTERNAL);
814 _Tt_db_property_list_cursor properties_cursor(propListP);
815 while (properties_cursor.next()) {
816 if ((*properties_cursor)->name == propname) {
817 if (!(*properties_cursor)->values.is_null()) {
818 return (*properties_cursor)->values->count();
827 } // end _tt_spec_prop_count()-
831 _tt_spec_prop_set(const char * objid, const char * propname, const char * value)
833 return _tt_spec_bprop_set(objid, propname, (unsigned char *)value,
834 (char *)0==value?0:strlen(value));
835 } // end -_tt_spec_prop_set()-
839 _tt_spec_propname(const char *objid, int n)
843 _Tt_objid_spec_ptr specP;
845 // find spec for objid
846 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
847 return (char *)error_pointer(result);
850 _Tt_db_property_ptr propP;
851 _Tt_db_property_list_ptr propListP;
855 propListP = specP->getProperties();
856 if ((result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) != TT_OK) {
857 return (char *)error_pointer(result);
860 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
862 case TT_WRN_STALE_OBJID:
869 return (char *)error_pointer(result);
871 return (char *)error_pointer(TT_ERR_INTERNAL);
874 // range check index number
875 if ((n < 0) || (n > propListP->count()-1)) {
876 return (char *)error_pointer(TT_ERR_NUM);
879 // get individual property
880 propP = (*propListP)[n];
882 // return propname of individual property
883 return (_tt_strdup((char *) propP->name));
885 } // end -_tt_spec_propname()-
889 _tt_spec_propnames_count(const char * objid)
892 _Tt_objid_spec_ptr specP;
893 _Tt_db_property_list_ptr propListP;
895 // find spec for objid
896 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
897 return tt_error_int(result);
900 propListP = specP->getProperties();
901 switch (result = _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC)) {
903 case TT_WRN_STALE_OBJID:
910 return tt_error_int(result);
912 return tt_error_int(TT_ERR_INTERNAL);
914 return propListP->count();
915 } // end -_tt_spec_propnames_count()-
919 _tt_spec_write(const char * objid)
922 _Tt_db_results db_results = TT_DB_OK;
923 _Tt_objid_spec_ptr specP;
924 _Tt_api_spec_map_ref specMap;
926 // find spec for objid
927 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
931 // Check the properties for special access privilege properties
932 // and generate the approptiate setAccess call
933 _Tt_db_property_list_ptr properties = specP->getProperties();
934 _Tt_db_property_list_cursor properties_cursor(properties);
936 bool_t access_prop_found = FALSE;
937 uid_t user = (uid_t)-1;
938 gid_t group = (gid_t)-1;
939 mode_t mode = (mode_t)-1;
940 _Tt_string temp_string;
941 while (properties_cursor.next()) {
943 if (properties_cursor->name == TT_OBJECT_OWNER_PROPERTY) {
944 access_prop_found = TRUE;
946 if (!properties_cursor->is_empty() &&
947 !(*properties_cursor->values)[0].is_null()) {
948 temp_string = (*properties_cursor->values)[0];
949 user = (uid_t)atoi((char *)temp_string);
952 else if (properties_cursor->name == TT_OBJECT_OWNER_PROPERTY) {
953 access_prop_found = TRUE;
955 if (!properties_cursor->is_empty() &&
956 !(*properties_cursor->values)[0].is_null()) {
957 temp_string = (*properties_cursor->values)[0];
958 group = (gid_t)atoi((char *)temp_string);
961 else if (properties_cursor->name == TT_OBJECT_MODE_PROPERTY) {
962 access_prop_found = TRUE;
964 if (!properties_cursor->is_empty() &&
965 !(*properties_cursor->values)[0].is_null()) {
966 temp_string = (*properties_cursor->values)[0];
967 mode = (mode_t)atoi((char *)temp_string);
972 if (access_prop_found) {
973 _Tt_db_access_ptr access = new _Tt_db_access;
975 access->group = group;
977 db_results = specP->setAccess(access);
980 if (db_results == TT_DB_OK) {
981 // write associated tt_db_object to disk
982 db_results = specP->write();
985 switch (result = _tt_get_api_error(db_results, _TT_API_SPEC)) {
987 case TT_WRN_STALE_OBJID:
988 specP->setOnDiskFlag(TRUE);
998 return TT_ERR_INTERNAL;
1002 } // end -tt_spec_write()-
1006 _tt_objid_equal(const char *objid1, const char *objid2)
1009 _Tt_objid_spec_ptr spec1, spec2;
1011 if ((err = objid_to_spec(objid1, spec1)) > TT_WRN_LAST) {
1012 return tt_error_int(err);
1014 if ((err = objid_to_spec(objid2, spec2)) > TT_WRN_LAST) {
1015 return tt_error_int(err);
1018 return spec1->getObjectKey() == spec2->getObjectKey();
1019 } // end -tty_objid_equal()-
1023 _tt_objid_objkey(const char *objid)
1026 _Tt_objid_spec_ptr specP;
1029 if ((result = objid_to_spec(objid, specP)) > TT_WRN_LAST) {
1030 return (char *)error_pointer(TT_ERR_OBJID);
1032 return _tt_strdup(specP->getObjectKey());
1033 } // end -tt_objid_key()-
1037 * Following service functions take care of changing from externally
1038 * visible objid to internal node structure pointers and back.
1039 * This isn't really the right place for it, since the external
1040 * form is not specific to the C api, but it's not clear where
1041 * the code should really be; it doesn't really belong to
1046 objid_to_spec(const char * objid, _Tt_objid_spec_ptr &specP)
1048 _Tt_api_spec_map_ref specMap;
1051 // find spec for objid
1052 specP = specMap.getSpec(objid);
1053 if (specP.is_null()) {
1054 return TT_ERR_OBJID;
1057 return _tt_get_api_error(specP->getDBResults(), _TT_API_SPEC);
1058 } // end -objid_to_spec()-