Пример #1
0
//Creates a xenstore battery dir with the specified index if it doesn't already exist.
static void make_xenstore_battery_dir(unsigned int battery_index) {

    char xenstore_path[256];
    char ** dir_entries;
    unsigned int num_entries, i;
    bool flag;

    dir_entries = xenstore_ls(&num_entries, "/pm");
    if (!dir_entries) {
        xcpmd_log(LOG_WARNING,
            "Listing directory /pm failed with error `%s'\n", strerror(errno));
        return;
    }

    snprintf(xenstore_path, 255, "%s%i", XS_BATTERY_PATH, battery_index);

    flag = false;
    for (i = 0; i < num_entries; ++i) {
        if (!strcmp(dir_entries[i], xenstore_path)) {
            flag = true;
            break;
        }
    }
    if (!flag)
        xenstore_mkdir(xenstore_path);

    //xenstore_ls() calls malloc(), so be sure to free().
    free(dir_entries);

}
Пример #2
0
//Finds the maximum battery index that exists in the sysfs.
static int get_max_battery_index(void) {

    int max_index, index;
    DIR * dir;
    struct dirent * dp;

    dir = opendir(BATTERY_DIR_PATH);
    if (!dir) {
        xcpmd_log(LOG_ERR, "opendir in get_max_battery_index failed for directory %s with error %d\n", BATTERY_DIR_PATH, errno);
        return -1;
    }

    max_index = -1;
    while ((dp = readdir(dir)) != NULL) {
        if (!strncmp(dp->d_name, "BAT", 3)) {
            index = get_terminal_number(dp->d_name);
            if (index > -1 && index > max_index) {
                max_index = index;
            }
        }
    }

    closedir(dir);

    return max_index;
}
Пример #3
0
//Allocates memory! Frees *str1 if it's not null!
//Places a pointer to the concatenation of *str1 and the sprintf of the
//remaining args into str1.
void safe_str_append(char ** str1, char * format, ...) {

    if (str1 == NULL || format == NULL)
        return;

    int length;
    char *formatted, *concatted;
    va_list args;

    va_start(args, format);
    length = vsnprintf(NULL, 0, format, args) + 1;
    formatted = (char *)malloc(length * sizeof(char));
    if (formatted == NULL) {
        xcpmd_log(LOG_ERR, "Couldn't allocate memory\n");
        return;
    }
    vsnprintf(formatted, length, format, args);
    va_end(args);

    if (*str1 == NULL) {
        *str1 = formatted;
    }
    else {
        concatted = safe_sprintf("%s%s", *str1, formatted);
        free(*str1);
        free(formatted);

        *str1 = concatted;
    }
}
Пример #4
0
//Retrieves a property over DBus. Returns 0 on failure or 1 on success.
int dbus_get_property(xcdbus_conn_t * xc_conn, const char * service, const char * path, const char * interface, const char * property, GValue * outv) {

    GError *error = NULL;
    GValue var = G_VALUE_INIT;
    DBusGProxy *p = xcdbus_get_proxy(xc_conn, service, path, "org.freedesktop.DBus.Properties");

    if (!p) {
        xcpmd_log(LOG_DEBUG, "Failed to get dbusgproxy");
        return 0;
    }

    if (!dbus_g_proxy_call(p, "Get", &error, G_TYPE_STRING, interface, G_TYPE_STRING, property, G_TYPE_INVALID, G_TYPE_VALUE, &var, G_TYPE_INVALID )) {
        xcpmd_log(LOG_DEBUG, "proxy call failed: %s", error->message);
        return 0;
    }
    *outv = var;
    return 1;

}
Пример #5
0
//Exactly what it says on the tin.
void write_battery_info_to_xenstore(unsigned int battery_index) {

    if (battery_slot_exists(battery_index) == NO || battery_index >= num_battery_structs_allocd) {
        xcpmd_log(LOG_INFO, "Detected removal of battery slot %d in info.\n", battery_index);
        cleanup_removed_battery(battery_index);
        return;
    }

    struct battery_info * info;
    char bif[1024], string_info[256], xenstore_path[128];

    info = &last_info[battery_index];

    memset(bif, 0, 1024);
    memset(string_info, 0, 256);
    // write 9 dwords (so 9*4) + length of 4 strings + 4 null terminators
    snprintf(bif, 3, "%02x",
             (unsigned int)(9*4 +
                            strlen(info->model_number) +
                            strlen(info->serial_number) +
                            strlen(info->battery_type) +
                            strlen(info->oem_info) + 4));
    write_ulong_lsb_first(bif+2, info->power_unit);
    write_ulong_lsb_first(bif+10, info->design_capacity);
    write_ulong_lsb_first(bif+18, info->last_full_capacity);
    write_ulong_lsb_first(bif+26, info->battery_technology);
    write_ulong_lsb_first(bif+34, info->design_voltage);
    write_ulong_lsb_first(bif+42, info->design_capacity_warning);
    write_ulong_lsb_first(bif+50, info->design_capacity_low);
    write_ulong_lsb_first(bif+58, info->capacity_granularity_1);
    write_ulong_lsb_first(bif+66, info->capacity_granularity_2);

    snprintf(string_info, 256, "%02x%s%02x%s%02x%s%02x%s",
             (unsigned int)strlen(info->model_number), info->model_number,
             (unsigned int)strlen(info->serial_number), info->serial_number,
             (unsigned int)strlen(info->battery_type), info->battery_type,
             (unsigned int)strlen(info->oem_info), info->oem_info);
    strncat(bif+73, string_info, 1024-73-1);

    //Ensure the directory exists before trying to write the leaves
    make_xenstore_battery_dir(battery_index);

    //Now write the leaves.
    snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BIF_LEAF);
    xenstore_write(bif, xenstore_path);


    //Here for compatibility--will be removed eventually
    if (battery_index == 0)
        xenstore_write(bif, XS_BIF);
    else
        xenstore_write(bif, XS_BIF1);
}
Пример #6
0
//Adds a DBus match for the specified string and registers a filter function,
//with optional argument func_data and optional function free_func that will
//be called on func_data when this match is removed.
//Returns 0 on failure or 1 on success.
//TODO: Cache DBus connection, since libxcdbus doesn't.
int add_dbus_filter(char * match, DBusHandleMessageFunction filter_func, void * func_data, DBusFreeFunction free_func) {

    DBusConnection * connection;

    if (xcdbus_conn == NULL) {
        xcpmd_log(LOG_WARNING, "xcdbus connection is unavailable");
        return 0;
    }

    connection = xcdbus_get_dbus_connection(xcdbus_conn);
    if (connection == NULL) {
        xcpmd_log(LOG_WARNING, "Unable to get DBus connection from xcdbus");
        return 0;
    }

    dbus_bus_add_match(connection, match, NULL);
    if (!dbus_connection_add_filter(connection, filter_func, func_data, free_func)) {
        xcpmd_log(LOG_ERR, "Couldn't add DBus filter--not enough memory");
        return 0;
    }

    return 1;
}
Пример #7
0
//Allocates memory!
//Deep clones a string. Don't forget to free() later.
char * clone_string(char * string) {

    char * clone;
    int length;

    length = strlen(string) + 1;
    clone = (char *)malloc(length * sizeof(char));
    if (clone == NULL) {
        xcpmd_log(LOG_ERR, "Couldn't allocate memory\n");
        return NULL;
    }
    strcpy(clone, string);

    return clone;
}
Пример #8
0
//Allocates memory!
//Allocates an appropriately sized string and prints to it.
char * safe_sprintf(char * format, ...) {

    int length;
    char * string;
    va_list args;

    va_start(args, format);
    length = vsnprintf(NULL, 0, format, args) + 1;
    string = (char *)malloc(length * sizeof(char));
    if (string == NULL) {
        xcpmd_log(LOG_ERR, "Couldn't allocate memory\n");
        return NULL;
    }
    vsnprintf(string, length, format, args);
    va_end(args);

    return string;
}
Пример #9
0
//Removes a DBus filter previously added with add_dbus_filter.
//Returns 0 on failure or 1 on success.
//TODO: Cache DBus connection, since libxcdbus doesn't.
int remove_dbus_filter(char * match, DBusHandleMessageFunction filter_func, void * func_data) {

    DBusConnection * connection;

    //Don't segfault if something else has already torn down the DBus connection.
    if (xcdbus_conn == NULL) {
        //xcpmd_log(LOG_WARNING, "Tried removing filter, but xcdbus connection is unavailable");
        return 0;
    }

    connection = xcdbus_get_dbus_connection(xcdbus_conn);
    if (connection == NULL) {
        xcpmd_log(LOG_WARNING, "Unable to get dbus connection from xcdbus");
        return 0;
    }

    dbus_bus_remove_match(connection, match, NULL);
    dbus_connection_remove_filter(connection, filter_func, func_data);

    return 1;
}
Пример #10
0
//Counts the number of batteries present in the sysfs.
int get_num_batteries_present(void) {

    int count;
    DIR * dir;
    struct dirent * dp;
    FILE * file;
    char data[128];
    char filename[289];

    dir = opendir(BATTERY_DIR_PATH);
    if (!dir) {
        xcpmd_log(LOG_ERR, "opendir in get_num_batteries_present() failed for directory %s with error %d\n", BATTERY_DIR_PATH, errno);
        return 0;
    }

    //Check all /sys/class/power_supply/BAT*/present.
    count = 0;
    while ((dp = readdir(dir)) != NULL) {

        if (!strncmp(dp->d_name, "BAT", 3)) {
            snprintf(filename, sizeof (filename), "%s/%s/present", BATTERY_DIR_PATH, dp->d_name);
            file = fopen(filename, "r");
            if (file == NULL)
                continue;

            fgets(data, sizeof(data), file);
            fclose(file);

            if (strstr(data, "1")) {
                ++count;
            }
        }
    }

    closedir(dir);

    return count;
}
Пример #11
0
//Counts the number of battery slots in the sysfs.
int get_num_batteries(void) {

    int count = 0;
    DIR * dir;
    struct dirent * dp;

    dir = opendir(BATTERY_DIR_PATH);
    if (!dir) {
        xcpmd_log(LOG_ERR, "opendir in get_num_batteries failed for directory %s with error %d\n", BATTERY_DIR_PATH, errno);
        return 0;
    }

    //Count all entries whose names start with BAT.
    while ((dp = readdir(dir)) != NULL) {
        if (!strncmp(dp->d_name, "BAT", 3)) {
            ++count;
        }
    }

    closedir(dir);

    return count;
}
Пример #12
0
//Updates status and info of all batteries locally and in the xenstore.
void update_batteries(void) {

    struct battery_status *old_status = NULL;
    struct battery_info *old_info = NULL;
    char path[256];
    unsigned int old_num_batteries = 0;
    unsigned int num_batteries = 0;
    unsigned int i, new_array_size, old_array_size, num_batteries_to_update;
    bool present_batteries_changed = false;

    if ( pm_specs & PM_SPEC_NO_BATTERIES )
        return;

    //Keep a copy of what the battery status/info used to be.
    old_status = (struct battery_status *)malloc(num_battery_structs_allocd * sizeof(struct battery_status));
    old_info = (struct battery_info *)malloc(num_battery_structs_allocd * sizeof(struct battery_info));

    if (last_status != NULL)
        memcpy(old_status, last_status, num_battery_structs_allocd * sizeof(struct battery_status));
    else
        memset(old_status, 0, num_battery_structs_allocd * sizeof(struct battery_status));

    if (last_info != NULL)
        memcpy(old_info, last_info, num_battery_structs_allocd * sizeof(struct battery_info));
    else
        memset(old_info, 0, num_battery_structs_allocd * sizeof(struct battery_info));

    old_array_size = num_battery_structs_allocd;


    //Resize the arrays if necessary.
    new_array_size = (unsigned int)(get_max_battery_index() + 1);
    if (new_array_size != old_array_size) {
        if (new_array_size == 0) {
            xcpmd_log(LOG_INFO, "All batteries removed.\n");
            free(last_info);
            free(last_status);
        }
        else {
            last_info = (struct battery_info *)realloc(last_info, new_array_size * sizeof(struct battery_info));
            last_status = (struct battery_status *)realloc(last_status, new_array_size * sizeof(struct battery_status));
            memset(last_info, 0, new_array_size * sizeof(struct battery_info));
            memset(last_status, 0, new_array_size * sizeof(struct battery_status));
        }
        num_battery_structs_allocd = new_array_size;
    }

    num_batteries_to_update = (new_array_size > old_array_size) ? new_array_size : old_array_size;

    //Updating all status/info before writing to the xenstore prevents bad
    //calculations of aggregate data (e.g., warning level).
    for (i=0; i < num_batteries_to_update; ++i) {
        update_battery_status(i);
        update_battery_info(i);
    }

    //Write back to the xenstore and only send notifications if things have changed.
    for (i=0; i < num_batteries_to_update; ++i) {

        //No need to update status/info in Xenstore if there was no battery to begin with.
        //   On some latops, batteries index are not contiguous. It is not a big
        //   deal to have one or two empty array slot, but it should not be
        //   reported as a removed battery (OXT-614).
        if (last_status[i].present || old_status[i].present) {
            write_battery_status_to_xenstore(i);
            write_battery_info_to_xenstore(i);
        }

        if (i < old_array_size && i < new_array_size) {
            if (memcmp(&old_info[i], &last_info[i], sizeof(struct battery_info))) {
                snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
                xenstore_write("1", path);
            }

            if (memcmp(&old_status[i], &last_status[i], sizeof(struct battery_status))) {
                snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
                xenstore_write("1", path);
            }

            if (old_status[i].present == YES)
                ++old_num_batteries;

            if (last_status[i].present == YES)
                ++num_batteries;

            if (old_status[i].present != last_status[i].present)
                present_batteries_changed = true;

        }
        else if (new_array_size > old_array_size) {
            //a battery has been added
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
            xenstore_write("1", path);
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
            xenstore_write("1", path);

            if (last_status[i].present == YES)
                ++num_batteries;

            if (i < old_array_size) {
                if (old_status[i].present != last_status[i].present)
                    present_batteries_changed = true;
            }
            else {
                if (last_status[i].present == YES)
                    present_batteries_changed = true;
            }
        }
        else if (new_array_size < old_array_size) {
            //a battery has been removed
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_INFO_EVENT_LEAF);
            xenstore_write("1", path);
            snprintf(path, 255, "%s%i/%s", XS_BATTERY_EVENT_PATH, i, XS_BATTERY_STATUS_EVENT_LEAF);
            xenstore_write("1", path);

            if (old_status[i].present == YES)
                ++old_num_batteries;

            if (i < new_array_size) {
                if (old_status[i].present != last_status[i].present)
                    present_batteries_changed = true;
            }
            else {
                if (old_status[i].present == YES)
                    present_batteries_changed = true;
            }
        }
    }

    if ((old_array_size != new_array_size) || (memcmp(old_info, last_info, new_array_size * sizeof(struct battery_info)))) {
        notify_com_citrix_xenclient_xcpmd_battery_info_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    if ((old_array_size != new_array_size) || (memcmp(old_status, last_status, new_array_size * sizeof(struct battery_status)))) {
        //Here for compatibility--should eventually be removed
        xenstore_write("1", XS_BATTERY_STATUS_CHANGE_EVENT_PATH);
        notify_com_citrix_xenclient_xcpmd_battery_status_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    if (present_batteries_changed) {
        notify_com_citrix_xenclient_xcpmd_num_batteries_changed(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
    }

    free(old_info);
    free(old_status);
}
Пример #13
0
//Exactly what it says on the tin.
void write_battery_status_to_xenstore(unsigned int battery_index) {

    struct battery_status * status;
    char bst[35], xenstore_path[128];
    int num_batteries, current_battery_level;

    if (battery_index >= num_battery_structs_allocd) {
        cleanup_removed_battery(battery_index);
    }

    num_batteries = get_num_batteries_present();
    if (num_batteries == 0) {
        xenstore_write("0", XS_BATTERY_PRESENT);
        return;
    }
    else {
        xenstore_write("1", XS_BATTERY_PRESENT);
    }

    status = &last_status[battery_index];

    //Delete the BST and reset the "present" flag if the battery is not currently present.
    if (status->present != YES) {

        snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BST_LEAF);
        xenstore_rm(xenstore_path);

        snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BATTERY_PRESENT_LEAF);
        xenstore_write("0", xenstore_path);
        return;
    }

    //Build the BST structure.
    memset(bst, 0, 35);
    snprintf(bst, 3, "%02x", 16);
    write_ulong_lsb_first(bst+2, status->state);
    write_ulong_lsb_first(bst+10, status->present_rate);
    write_ulong_lsb_first(bst+18, status->remaining_capacity);
    write_ulong_lsb_first(bst+26, status->present_voltage);

    //Ensure the directory exists before trying to write the leaves
    make_xenstore_battery_dir(battery_index);

    //Now write the leaves.
    snprintf(xenstore_path, 255, XS_BATTERY_PATH "%i/" XS_BST_LEAF, battery_index);
    xenstore_write(bst, xenstore_path);

    snprintf(xenstore_path, 255, "%s%i/%s", XS_BATTERY_PATH, battery_index, XS_BATTERY_PRESENT_LEAF);
    xenstore_write("1", xenstore_path);

    //Here for compatibility--will be removed eventually
    if (battery_index == 0)
        xenstore_write(bst, XS_BST);
    else
        xenstore_write(bst, XS_BST1);

    current_battery_level = get_current_battery_level();
    if (current_battery_level == NORMAL || get_ac_adapter_status() == ON_AC)
        xenstore_rm(XS_CURRENT_BATTERY_LEVEL);
    else {
        xenstore_write_int(current_battery_level, XS_CURRENT_BATTERY_LEVEL);
        notify_com_citrix_xenclient_xcpmd_battery_level_notification(xcdbus_conn, XCPMD_SERVICE, XCPMD_PATH);
        xcpmd_log(LOG_ALERT, "Battery level below normal - %d!\n", current_battery_level);
    }

#ifdef XCPMD_DEBUG
    xcpmd_log(LOG_DEBUG, "~Updated battery information in xenstore\n");
#endif
}
Пример #14
0
//Gets a battery's info from the sysfs and stores it in last_info.
int update_battery_info(unsigned int battery_index) {

    DIR *battery_dir;
    struct dirent * dp;
    FILE *file;
    char filename[295];
    char data[128];
    char *ptr;

    struct battery_info info;
    memset(&info, 0, sizeof(struct battery_info));

    if (battery_index >= num_battery_structs_allocd)
        return 0;

    if (battery_slot_exists(battery_index) == NO) {
        memcpy(&last_info[battery_index], &info, sizeof(struct battery_info));
        return 0;
    }

    battery_dir = get_battery_dir(battery_index);
    if (!battery_dir) {
        xcpmd_log(LOG_ERR, "opendir in update_battery_info() for directory %s/BAT%d failed with error %d\n", BATTERY_DIR_PATH, battery_index, errno);
        return 0;
    }

    //Loop over the files in the directory.
    while ((dp = readdir(battery_dir)) != NULL) {

        //Convert from dirent to file and read out the data.
        if (dp->d_type == DT_REG) {

            memset(filename, 0, sizeof(filename));
            snprintf(filename, sizeof (filename), "%s/BAT%u/%s", BATTERY_DIR_PATH, battery_index, dp->d_name);

            file = fopen(filename, "r");
            if (file == NULL)
                continue;

            memset(data, 0, sizeof(data));
            fgets(data, sizeof(data), file);

            fclose(file);

            //Trim off leading spaces.
            ptr = data;
            while(*ptr == ' ')
                ptr += sizeof(char);

            //Set the attribute represented by this file.
            set_battery_info_attribute(dp->d_name, ptr, &info);

        }
    }

    //In sysfs, the charge nodes are for batteries reporting in mA and
    //the energy nodes are for mW.
    if (info.charge_full_design != 0) {
        info.power_unit = mA;
        info.design_capacity = info.charge_full_design;
        info.last_full_capacity = info.charge_full;
    }
    else {
        info.power_unit = mW;
        info.design_capacity = info.energy_full_design;
        info.last_full_capacity = info.energy_full;
    }

    //Unlike the old procfs files, sysfs does not report some values like the
    //warn and low levels. These values are generally ignored anyway. The
    //various OS's decide what to do at different depletion levels through
    //their own policies. These are just some approximate values to pass.
    //TODO govern these by policy
    info.design_capacity_warning = info.last_full_capacity * (BATTERY_WARNING_PERCENT / 100);
    info.design_capacity_low = info.last_full_capacity * (BATTERY_LOW_PERCENT / 100);

    info.capacity_granularity_1 = 1;
    info.capacity_granularity_2 = 1;

    closedir(battery_dir);
    memcpy(&last_info[battery_index], &info, sizeof(struct battery_info));

    return 1;
}
Пример #15
0
//Allocates memory!
//Creates a new VM identifier table from a GPtrArray of VMs as retrieved from
//DBus. Does not modify the global vm identifier table.
struct vm_identifier_table * new_vm_identifier_table(GPtrArray * vm_list) {

    struct vm_identifier_table * table;
    char * tmp;
    char * vm;
    unsigned int i;

    if (vm_list == NULL) {
        return NULL;
    }

    //Alloc the table itself.
    table = (struct vm_identifier_table *)calloc(1, sizeof(struct vm_identifier_table));
    table->num_entries = vm_list->len;
    table->entries = (struct vm_identifier_table_row *)calloc(table->num_entries, sizeof(struct vm_identifier_table_row));

    if ((table == NULL) || (table->entries == NULL)) {
        xcpmd_log(LOG_ERR, "Failed to allocate memory\n");
        free_vm_identifier_table(table);
        return NULL;
    }

    //Create a table row for each entry in the GPtrArray of VM paths.
    for (i = 0; i < table->num_entries; ++i) {

        vm = g_ptr_array_index(vm_list, i);

        //Get the VM name.
        property_get_com_citrix_xenclient_xenmgr_vm_name_(xcdbus_conn, XENMGR_SERVICE, vm, &tmp);
        if(tmp == NULL) {
            xcpmd_log(LOG_ERR, "Error: Couldn't get name of %s.\n", vm);
            free_vm_identifier_table(table);
            return NULL;
        }

        table->entries[i].name = (char *)malloc(strlen(tmp) + 1);
        if (table->entries[i].name == NULL) {
            xcpmd_log(LOG_ERR, "Failed to allocate memory\n");
            free_vm_identifier_table(table);
            return NULL;
        }
        strcpy(table->entries[i].name, tmp);

        //Copy the VM path.
        table->entries[i].path = (char *)malloc(VM_PATH_LEN + 1); //path_len = 40 = 32 path bytes + 4 underscores + "/vm/" (4), and 1 byte for \0
        if (table->entries[i].path == NULL) {
            xcpmd_log(LOG_ERR, "Failed to allocate memory\n");
            free_vm_identifier_table(table);
            return NULL;
        }
        strncpy(table->entries[i].path, vm, VM_PATH_LEN + 1);

        //Extract the VM UUID from the path.
        table->entries[i].uuid = (char *)malloc(VM_PATH_LEN - VM_PATH_UUID_PREFIX_LEN + 1); //path_len = 36 = 32 path bytes + 4 hyphens, and 1 byte for \0
        if (table->entries[i].uuid == NULL) {
            xcpmd_log(LOG_ERR, "Failed to allocate memory\n");
            free_vm_identifier_table(table);
            return NULL;
        }
        strncpy(table->entries[i].uuid, vm+VM_PATH_UUID_PREFIX_LEN, VM_PATH_LEN - VM_PATH_UUID_PREFIX_LEN + 1);

        //Convert _ to - in uuid
        //000000000011111111112222222222333333
        //012345678901234567890123456789012345
        //12345678-1234-1234-1234-123456789012
        table->entries[i].uuid[8] = '-';
        table->entries[i].uuid[13] = '-';
        table->entries[i].uuid[18] = '-';
        table->entries[i].uuid[23] = '-';
    }

    return table;
}
Пример #16
0
int main(int argc, char *argv[]) {

    int ret = 0;

#ifndef RUN_STANDALONE
    openlog("xcpmd", 0, LOG_DAEMON);
    daemonize();
#endif

    xcpmd_log(LOG_INFO, "Starting XenClient power management daemon.\n");

    //Initialize libevent library
    event_init();

    //Initialize xenstore.
    if (xenstore_init() == -1) {
        xcpmd_log(LOG_ERR, "Unable to init xenstore\n");
        return -1;
    }

    // Allow everyone to read from /pm/ in xenstore
    xenstore_rm("/pm");
    xenstore_mkdir("/pm");
    xenstore_chmod("r0", 1, "/pm");

    initialize_platform_info();


    xcpmd_log(LOG_INFO, "Starting DBUS server.\n");
    if (xcpmd_dbus_initialize() == -1) {
        xcpmd_log(LOG_ERR, "Failed to initialize DBUS server\n");
        goto xcpmd_err;
    }

    xcpmd_log(LOG_INFO, "Starting ACPI events monitor.\n");
    if (acpi_events_initialize() == -1) {
        xcpmd_log(LOG_ERR, "Failed to initialize ACPI events monitor\n");
        goto xcpmd_err;
    }

    // Load modules
    xcpmd_log(LOG_INFO, "Loading modules.\n");
    if (init_modules() == -1) {
        xcpmd_log(LOG_ERR, "Failed to load all modules\n");
        goto xcpmd_err;
    }

    //This relies on both acpi-events and acpi-module having been initialized
    xcpmd_log(LOG_INFO, "Initializing ACPI state.\n");
    acpi_initialize_state();

    // Load policy
    xcpmd_log(LOG_INFO, "Loading policy.\n");
    if (load_policy_from_db() == -1) {
        xcpmd_log(LOG_WARNING, "Error loading policy from DB; continuing...\n");
    }

#ifdef POLICY_FILE_PATH
    if (load_policy_from_file(POLICY_FILE_PATH) == -1) {
        xcpmd_log(LOG_WARNING, "Error loading policy from file %s; continuing...\n", POLICY_FILE_PATH);
    }
#endif

#ifdef XCPMD_DEBUG
    xcpmd_log(LOG_DEBUG, "Rules loaded:\n");
    print_rules();
#endif

    xcpmd_log(LOG_INFO, "Entering event loop.\n");
    event_dispatch();

    goto xcpmd_out;

xcpmd_err:
    ret = -1;
xcpmd_out:
    uninit_modules();
    acpi_events_cleanup();
    xcpmd_dbus_cleanup();
#ifndef RUN_STANDALONE
    closelog();
#endif

    return ret;
}
Пример #17
0
//Gets a battery's status from the sysfs and stores it in last_status.
int update_battery_status(unsigned int battery_index) {

    DIR *battery_dir;
    struct dirent * dp;
    FILE *file;
    char filename[295];
    char data[128];
    char *ptr;

    struct battery_status status;
    memset(&status, 0, sizeof(struct battery_status));

    if (battery_index >= num_battery_structs_allocd)
        return -1;

    if (battery_slot_exists(battery_index) == NO) {
        status.present = NO;
        memcpy(&last_status[battery_index], &status, sizeof(struct battery_status));
        return 1;
    }

    battery_dir = get_battery_dir(battery_index);
    if (!battery_dir) {
        //Battery directory does not exist--this normally occurs when a battery slot is removed
        if (errno == ENOENT) {
            status.present = NO;
            memcpy(&last_status[battery_index], &status, sizeof(struct battery_status));
            return 1;
        }
        else {
            xcpmd_log(LOG_ERR, "opendir in update_battery_status for directory %s/BAT%d failed with error %d\n", BATTERY_DIR_PATH, battery_index, errno);
            return 0;
        }
    }

    //Loop over the files in the directory.
    while ((dp = readdir(battery_dir)) != NULL) {

        //Convert from dirent to file and read out the data.
        if (dp->d_type == DT_REG) {

            snprintf(filename, sizeof (filename), "%s/BAT%u/%s", BATTERY_DIR_PATH, battery_index, dp->d_name);

            file = fopen(filename, "r");
            if (file == NULL)
                continue;

            memset(data, 0, sizeof(data));
            fgets(data, sizeof(data), file);

            fclose(file);

            //Trim off leading spaces.
            ptr = data;
            while(*ptr == ' ')
                ptr += sizeof(char);

            //Set the attribute represented by this file.
            set_battery_status_attribute(dp->d_name, ptr, &status);
        }
    }

    // This check handles both cases for mA batteries: if are not charging
    // (current_now == 0) but have capacity or the battery is totally dead
    // (charge_now == 0) but it is charging. If both are zero, they will
    // both be zero in the end.
    if (status.charge_now != 0 || status.current_now != 0) {
        // Rate in mA, remaining in mAh
        status.present_rate = status.current_now;
        status.remaining_capacity = status.charge_now;
    }
    else {
        // Rate in mW, remaining in mWh
        status.present_rate = status.power_now;
        status.remaining_capacity = status.energy_now;
    }

    closedir(battery_dir);
    memcpy(&last_status[battery_index], &status, sizeof(struct battery_status));
#ifdef XCPMD_DEBUG
    print_battery_status(battery_index);
#endif
    return 1;
}