Esempio n. 1
0
int diskutil_loop (const char * path, const long long offset, char * lodev, int lodev_size)
{
    int found = 0;
    int done = 0;
    int ret = OK;
    char * output;

    // we retry because we cannot atomically obtain a free loopback
    // device on all distros (some versions of 'losetup' allow a file
    // argument with '-f' options, but some do not)
    for (int i=0; i<LOOP_RETRIES; i++) {
        sem_p (loop_sem);
        output = pruntf (TRUE, "%s %s -f", helpers_path[ROOTWRAP], helpers_path[LOSETUP]);
        sem_v (loop_sem);
        if (output==NULL) // there was a problem
            break;
        if (strstr (output, "/dev/loop")) {
            strncpy (lodev, output, lodev_size);
            char * ptr = strrchr (lodev, '\n');
            if (ptr) {
                *ptr = '\0';
                found = 1;
            }
        }
        free (output);

        if (found) {
            boolean do_log = ((i+1)==LOOP_RETRIES); // log error on last try only
            logprintfl (EUCADEBUG, "{%u} attaching file %s\n", (unsigned int)pthread_self(), path);
            logprintfl (EUCADEBUG, "{%u}             to %s at offset %lld\n", (unsigned int)pthread_self(), lodev, offset);
            sem_p (loop_sem);
            output = pruntf (do_log, "%s %s -o %lld %s %s", helpers_path[ROOTWRAP], helpers_path[LOSETUP], offset, lodev, path);
            sem_v (loop_sem);
            if (output==NULL) {
                logprintfl (EUCADEBUG, "{%u} cannot attach to loop device %s (will retry)\n", (unsigned int)pthread_self(), lodev);
            } else {
                free (output);
                done = 1;
                break;
            }
        }
        
        sleep (1);
        found = 0;
    }
    if (!done) {
        logprintfl (EUCAINFO, "{%u} error: cannot find free loop device or attach to one\n", (unsigned int)pthread_self());
        ret = ERROR;
    }
    
    return ret;
}
Esempio n. 2
0
// TODO: since 'losetup' truncates paths in its output, this
// check is not perfect. It may approve loopback devices
// that are actually pointing at a different path.
int diskutil_loop_check (const char * path, const char * lodev)
{
    int ret = 0;

    char * output = pruntf (TRUE, "%s %s %s", helpers_path[ROOTWRAP], helpers_path[LOSETUP], lodev);
    if (output==NULL)
        return 1;
    
    // output is expected to look like:
    // /dev/loop4: [0801]:5509589 (/var/lib/eucalyptus/volumes/v*)
    char * oparen = strchr (output, '(');
    char * cparen = strchr (output, ')');
    if (oparen==NULL || cparen==NULL) { // no parenthesis => unexpected `losetup` output
        ret = 1;
    } else if ((cparen - oparen) < 3) { // strange paren arrangement => unexpected
        ret = 1;
    } else { // extract just the path, possibly truncated, from inside the parens
        oparen++;
        cparen--;
        if (* cparen == '*') // handle truncated paths, identified with an asterisk
            cparen--;
        * cparen = '\0'; // truncate ')' or '*)'
        if (strstr (path, oparen) == NULL) { // see if path is in the blobstore
            ret = 1;
        }
    }
    free (output);
    
    return ret;
}
Esempio n. 3
0
int diskutil_unloop (const char * lodev)
{
    int ret = OK;
    char * output;
    int retried = 0;

    logprintfl (EUCADEBUG, "{%u} detaching from loop device %s\n", (unsigned int)pthread_self(), lodev);

    // we retry because we have seen spurious errors from 'losetup -d' on Xen:
    //     ioctl: LOOP_CLR_FD: Device or resource bus
    for (int i=0; i<LOOP_RETRIES; i++) {
        boolean do_log = ((i+1)==LOOP_RETRIES); // log error on last try only
        sem_p (loop_sem);
        output = pruntf (do_log, "%s %s -d %s", helpers_path[ROOTWRAP], helpers_path[LOSETUP], lodev);
        sem_v (loop_sem);
        if (!output) {           
            ret = ERROR;
        } else {
            ret = OK;
            free (output);
            break;
        }
        logprintfl (EUCADEBUG, "{%u} cannot detach loop device %s (will retry)\n", (unsigned int)pthread_self(), lodev);
        retried++;
        sleep (1);
    }
    if (ret == ERROR) {
        logprintfl (EUCAWARN, "{%u} error: cannot detach loop device\n", (unsigned int)pthread_self());
    } else if (retried) {
        logprintfl (EUCAINFO, "{%u} succeeded to detach %s after %d retries\n", (unsigned int)pthread_self(), lodev, retried);
    }

    return ret;
}
Esempio n. 4
0
//!
//!
//!
//! @param[in]  path
//! @param[in]  part
//! @param[out] first
//! @param[out] last
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any issue occured.
//!         \li EUCA_INVALID_ERROR: if any paramter does not meet the preconditions.
//!
//! @pre The path, first and last parameters must not be NULL.
//!
//! @post On success, the partition information has been extracted and contained in first and last.
//!
int diskutil_sectors(const char *path, const int part, long long *first, long long *last)
{
    int p = 0;
    int ret = EUCA_ERROR;
    char *ss = NULL;
    char *end = NULL;
    char *comma = NULL;
    char *output = NULL;
    char *section = NULL;
    boolean found = FALSE;

    if (path && first && last) {
        *first = 0L;
        *last = 0L;

        if ((output = pruntf(TRUE, "%s %s", helpers_path[FILECMD], path)) == NULL) {
            LOGERROR("failed to extract partition information for '%s'\n", path);
        } else {
            // parse the output, such as:
            // NAME: x86 boot sector;
            // partition 1: ID=0x83, starthead 1, startsector 63, 32769 sectors;
            // partition 2: ID=0x83, starthead 2, startsector 32832, 32769 sectors;
            // partition 3: ID=0x82, starthead 2, startsector 65601, 81 sectors
            found = FALSE;
            section = strtok(output, ";");  // split by semicolon
            for (p = 0; section != NULL; p++) {
                section = strtok(NULL, ";");
                if (section && (p == part)) {
                    found = TRUE;
                    break;
                }
            }

            if (found) {
                if ((ss = strstr(section, "startsector")) != NULL) {
                    ss += strlen("startsector ");
                    if ((comma = strstr(ss, ", ")) != NULL) {
                        *comma = '\0';
                        comma += strlen(", ");
                        if ((end = strstr(comma, " sectors")) != NULL) {
                            *end = '\0';
                            *first = atoll(ss);
                            *last = *first + atoll(comma) - 1L;
                        }
                    }
                }
            }

            EUCA_FREE(output);
        }

        if (*last > 0)
            ret = EUCA_OK;

        return (ret);
    }

    LOGERROR("failed to extract partition information for '%s'\n", SP(path));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 5
0
int diskutil_mkdir (const char * path)
{
    char * output;

    output = pruntf (TRUE, "%s %s -p %s", helpers_path[ROOTWRAP], helpers_path[MKDIR], path);
    if (!output) {
        return ERROR;
    }
    free (output);

    return OK;
}
Esempio n. 6
0
int diskutil_cp (const char * from, const char * to)
{
    char * output;

    output = pruntf (TRUE, "%s %s %s %s", helpers_path[ROOTWRAP], helpers_path[CP], from, to);
    if (!output) {
        return ERROR;
    }
    free (output);

    return OK;
}
Esempio n. 7
0
int diskutil_sectors (const char * path, const int part, long long * first, long long * last)
{
    int ret = ERROR;
    char * output;
    * first = 0L;
    * last = 0L;

    output = pruntf (TRUE, "%s %s", helpers_path[FILECMD], path);
    if (!output) {
        logprintfl (EUCAINFO, "ERROR: failed to extract partition information for '%s'\n", path);
    } else {
        // parse the output, such as:
        // NAME: x86 boot sector;
        // partition 1: ID=0x83, starthead 1, startsector 63, 32769 sectors;
        // partition 2: ID=0x83, starthead 2, startsector 32832, 32769 sectors;
        // partition 3: ID=0x82, starthead 2, startsector 65601, 81 sectors
        boolean found = FALSE;
        char * section = strtok (output, ";"); // split by semicolon
        for (int p = 0; section != NULL; p++) {
            section = strtok (NULL, ";");
            if (section && p == part) {
                found = TRUE;
                break;
            }
        }
        if (found) {
            char * ss = strstr (section, "startsector");
            if (ss) {
                ss += strlen ("startsector ");
                char * comma = strstr (ss, ", ");
                if (comma) {
                    * comma = '\0';
                    comma += strlen (", ");
                    char * end = strstr (comma, " sectors");
                    if (end) {
                        * end = '\0';
                        * first = atoll (ss);
                        * last = * first + atoll (comma) - 1L;
                    }
                }
            }
        }

        free (output);
    }

    if ( * last > 0 )
        ret = OK;

    return ret;
}
Esempio n. 8
0
int diskutil_ch (const char * path, const char * user, const char * group, const int perms)
{
    int ret = OK;
    char * output;

    logprintfl (EUCAINFO, "{%u} ch(own|mod) '%s' %s.%s %o\n", 
                (unsigned int)pthread_self(), 
                path,
                user?user:"******", 
                group?group:"*", 
                perms);
    if (user) {
        output = pruntf (TRUE, "%s %s %s %s", helpers_path[ROOTWRAP], helpers_path[CHOWN], user, path);
        if (!output) {
            return ERROR;
        }
        free (output);
    }

    if (group) {
        output = pruntf (TRUE, "%s %s :%s %s", helpers_path[ROOTWRAP], helpers_path[CHOWN], group, path);
        if (!output) {
            return ERROR;
        }
        free (output);
    }

    if (perms>0) {
        output = pruntf (TRUE, "%s %s 0%o %s", helpers_path[ROOTWRAP], helpers_path[CHMOD], perms, path);
        if (!output) {
            return ERROR;
        }
        free (output);
    }

    return OK;
}
Esempio n. 9
0
int diskutil_mbr (const char * path, const char * type)
{
    int ret = OK;
    char * output;

    output = pruntf (TRUE, "LD_PRELOAD='' %s %s --script %s mklabel %s", helpers_path[ROOTWRAP], helpers_path[PARTED], path, type);
    if (!output) {
        logprintfl (EUCAINFO, "ERROR: cannot create an MBR\n");
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 10
0
int diskutil_part (const char * path, char * part_type, const char * fs_type, const long long first_sector, const long long last_sector)
{
    int ret = OK;
    char * output;

    output = pruntf (TRUE, "LD_PRELOAD='' %s %s --script %s mkpart %s %s %llds %llds", helpers_path[ROOTWRAP], helpers_path[PARTED], path, part_type, (fs_type)?(fs_type):(""), first_sector, last_sector);
    if (!output) {
        logprintfl (EUCAINFO, "ERROR: cannot add a partition\n");
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 11
0
int diskutil_mkswap (const char * lodev, const long long size_bytes)
{
    int ret = OK;
    char * output;

    output = pruntf (TRUE, "%s %s %s %lld", helpers_path[ROOTWRAP], helpers_path[MKSWAP], lodev, size_bytes/1024);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: cannot format partition on '%s' as swap\n", (unsigned int)pthread_self(), lodev);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 12
0
//!
//!
//!
//! @param[in] from
//! @param[in] to
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if we fail to copy the item.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions
//!
//! @pre Both from and to parameters must not be NULL.
//!
//! @post On success the file has been copied.
//!
int diskutil_cp(const char *from, const char *to)
{
    char *output = NULL;

    if (from && to) {
        if ((output = pruntf(TRUE, "%s %s %s %s", helpers_path[ROOTWRAP], helpers_path[CP], from, to)) == NULL) {
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    return (EUCA_INVALID_ERROR);
}
Esempio n. 13
0
//!
//!
//!
//! @param[in] path
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if we fail to create the directory
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre The path parameter must not be NULL.
//!
//! @post On success, the directory is created.
//!
int diskutil_mkdir(const char *path)
{
    char *output = NULL;

    if (path) {
        if ((output = pruntf(TRUE, "%s %s -p %s", helpers_path[ROOTWRAP], helpers_path[MKDIR], path)) == NULL) {
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    return (EUCA_INVALID_ERROR);
}
Esempio n. 14
0
int diskutil_mkfs (const char * lodev, const long long size_bytes)
{
    int ret = OK;
    char * output;
    int block_size = 4096;

    output = pruntf (TRUE, "%s %s -b %d %s %lld", helpers_path[ROOTWRAP], helpers_path[MKEXT3], block_size, lodev, size_bytes/block_size);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: cannot format partition on '%s' as ext3\n", (unsigned int)pthread_self(), lodev);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 15
0
int diskutil_tune (const char * lodev)
{
    int ret = OK;
    char * output;

    sem_p (loop_sem);
    output = pruntf (TRUE, "%s %s %s -c 0 -i 0", helpers_path[ROOTWRAP], helpers_path[TUNE2FS], lodev);
    sem_v (loop_sem);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: cannot tune file system on '%s'\n", (unsigned int)pthread_self(), lodev);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 16
0
int diskutil_dd (const char * in, const char * out, const int bs, const long long count)
{
    int ret = OK;
    char * output;

    logprintfl (EUCAINFO, "{%u} copying data from '%s'\n", (unsigned int)pthread_self(), in);
    logprintfl (EUCAINFO, "{%u}                to '%s' (blocks=%lld)\n", (unsigned int)pthread_self(), out, count);
    output = pruntf (TRUE, "%s %s if=%s of=%s bs=%d count=%lld", helpers_path[ROOTWRAP], helpers_path[DD], in, out, bs, count);
    if (!output) {
        logprintfl (EUCAERROR, "{%u} error: cannot copy '%s'\n", (unsigned int)pthread_self(), in);
        logprintfl (EUCAERROR, "{%u}                 to '%s'\n", (unsigned int)pthread_self(), out);
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 17
0
int diskutil_umount (const char * dev)
{
    int ret = OK;
    char * output;

    sem_p (loop_sem);
    output = pruntf (TRUE, "%s %s umount %s", helpers_path[ROOTWRAP], helpers_path[MOUNTWRAP], dev);
    sem_v (loop_sem);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: cannot unmount device '%s'\n", (unsigned int)pthread_self(), dev);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 18
0
int diskutil_umount (const char * dev)
{
    int ret = OK;
    char * output;

    sem_p (loop_sem);
    output = pruntf (TRUE, "%s %s umount %s", helpers_path[ROOTWRAP], helpers_path[MOUNTWRAP], dev);
    sem_v (loop_sem);
    if (!output) {
        logprintfl (EUCAERROR, "cannot unmount device '%s'\n", dev);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 19
0
//!
//!
//!
//! @param[in] path
//! @param[in] lodev
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions
//!
//! @pre Both path and lodev parameters must not be NULL.
//!
//! @todo since 'losetup' truncates paths in its output, this check is not perfect. It
//!       may approve loopback devices that are actually pointing at a different path.
//!
int diskutil_loop_check(const char *path, const char *lodev)
{
    int ret = EUCA_OK;
    char *output = NULL;
    char *oparen = NULL;
    char *cparen = NULL;

    if (path && lodev) {
        output = pruntf(TRUE, "%s %s %s", helpers_path[ROOTWRAP], helpers_path[LOSETUP], lodev);
        if (output == NULL)
            return (EUCA_ERROR);

        // output is expected to look like: /dev/loop4: [0801]:5509589 (/var/lib/eucalyptus/volumes/v*)
        oparen = strchr(output, '(');
        cparen = strchr(output, ')');
        if ((oparen == NULL) || (cparen == NULL)) {
            // no parenthesis => unexpected `losetup` output
            ret = EUCA_ERROR;
        } else if ((cparen - oparen) < 3) {
            // strange paren arrangement => unexpected
            ret = EUCA_ERROR;
        } else {
            // extract just the path, possibly truncated, from inside the parens
            oparen++;
            cparen--;
            if (*cparen == '*') {
                // handle truncated paths, identified with an asterisk
                cparen--;
            }
            // truncate ')' or '*)'
            *cparen = '\0';

            // see if path is in the blobstore
            if (strstr(path, oparen) == NULL) {
                ret = EUCA_ERROR;
            }
        }

        EUCA_FREE(output);
        return (ret);
    }

    LOGWARN("bad params: path=%s, lodev=%s\n", SP(path), SP(lodev));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 20
0
//!
//! Creates a Master Boot Record (MBR) of the given type at the given path
//!
//! @param[in] path path where we need to create the MBR
//! @param[in] type type of MBR to create
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if we fail to create the MBR
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions
//!
//! @pre Both path and type parameters must not be NULL.
//!
//! @post On success, the MBR is created
//!
int diskutil_mbr(const char *path, const char *type)
{
    char *output = NULL;

    if (path && type) {
        output = pruntf(TRUE, "LD_PRELOAD='' %s %s --script %s mklabel %s", helpers_path[ROOTWRAP], helpers_path[PARTED], path, type);
        if (!output) {
            LOGERROR("cannot create an MBR\n");
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    LOGWARN("bad params: path=%s, type=%s\n", SP(path), SP(type));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 21
0
//!
//! Format a partition as a swap.
//!
//! @param[in] lodev
//! @param[in] size_bytes
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre The lodev parameters must not be NULL.
//!
//! @post On success, the partition is formatted as swap.
//!
int diskutil_mkswap(const char *lodev, const long long size_bytes)
{
    char *output = NULL;

    if (lodev) {
        output = pruntf(TRUE, "%s %s %s %lld", helpers_path[ROOTWRAP], helpers_path[MKSWAP], lodev, size_bytes / 1024);
        if (!output) {
            LOGERROR("cannot format partition on '%s' as swap\n", lodev);
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    LOGWARN("cannot format partition as swap. lodev=%s\n", SP(lodev));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 22
0
//!
//! Creates a new partition of the given part_type at the given path.
//!
//! @param[in] path path where to create the partition
//! @param[in] part_type the type of partition
//! @param[in] fs_type the type of file system (if NULL, "" is assumed)
//! @param[in] first_sector the first sector of the partition
//! @param[in] last_sector the last sector of this partition
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if we fail to create the partition
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions
//!
//! @pre Both path and part_type parameters must not be NULL.
//!
//! @post On success, the partition is created
//!
int diskutil_part(const char *path, char *part_type, const char *fs_type, const long long first_sector, const long long last_sector)
{
    char *output = NULL;

    if (path && part_type) {
        output = pruntf(TRUE, "LD_PRELOAD='' %s %s --script %s mkpart %s %s %llds %llds",
                        helpers_path[ROOTWRAP], helpers_path[PARTED], path, part_type, ((fs_type != NULL) ? (fs_type) : ("")), first_sector, last_sector);
        if (!output) {
            LOGERROR("cannot add a partition\n");
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    LOGWARN("bad params: path=%s, part_type=%s\n", SP(path), SP(part_type));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 23
0
int diskutil_dd2 (const char * in, const char * out, const int bs, const long long count, const long long seek, const long long skip)
{
    int ret = OK;
    char * output;

    logprintfl (EUCAINFO, "{%u} copying data from '%s'\n", (unsigned int)pthread_self(), in);
    logprintfl (EUCAINFO, "{%u}                to '%s'\n", (unsigned int)pthread_self(), out);
    logprintfl (EUCAINFO, "{%u}                of %lld blocks (bs=%d), seeking %lld, skipping %lld\n", (unsigned int)pthread_self(), count, bs, seek, skip);
    output = pruntf (TRUE, "%s %s if=%s of=%s bs=%d count=%lld seek=%lld skip=%lld conv=notrunc,fsync", helpers_path[ROOTWRAP], helpers_path[DD], in, out, bs, count, seek, skip);
    if (!output) {
        logprintfl (EUCAERROR, "{%u} error: cannot copy '%s'\n", (unsigned int)pthread_self(), in);
        logprintfl (EUCAERROR, "{%u}                 to '%s'\n", (unsigned int)pthread_self(), out);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 24
0
//!
//!
//!
//! @param[in] lodev
//! @param[in] size_bytes
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre The lodev parameters must not be NULL.
//!
//! @post On success, the loop device is attached.
//!
int diskutil_mkfs(const char *lodev, const long long size_bytes)
{
    int block_size = 4096;
    char *output = NULL;

    if (lodev) {
        output = pruntf(TRUE, "%s %s -b %d %s %lld", helpers_path[ROOTWRAP], helpers_path[MKEXT3], block_size, lodev, size_bytes / block_size);
        if (!output) {
            LOGERROR("cannot format partition on '%s' as ext3\n", lodev);
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    LOGWARN("cannot format partition as ext3. lodev=%s\n", SP(lodev));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 25
0
int diskutil_ddzero (const char * path, const long long sectors, boolean zero_fill)
{
    int ret = OK;
    char * output;

    long long count = 1;
    long long seek = sectors - 1;
    if (zero_fill) {
        count = sectors;
        seek = 0;
    }

    output = pruntf (TRUE, "%s %s if=/dev/zero of=%s bs=512 seek=%lld count=%lld", helpers_path[ROOTWRAP], helpers_path[DD], path, seek, count);
    if (!output) {
        logprintfl (EUCAINFO, "ERROR: cannot create disk file %s\n", path);
        ret = ERROR;
    } else {
        free (output);
    }

    return ret;
}
Esempio n. 26
0
//!
//!
//!
//! @param[in] lodev
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre The lodev parameters must not be NULL.
//!
//! @post On success, the loop device is attached.
//!
int diskutil_tune(const char *lodev)
{
    char *output = NULL;

    if (lodev) {
        sem_p(loop_sem);
        {
            output = pruntf(TRUE, "%s %s %s -c 0 -i 0", helpers_path[ROOTWRAP], helpers_path[TUNE2FS], lodev);
        }
        sem_v(loop_sem);

        if (!output) {
            LOGERROR("cannot tune file system on '%s'\n", lodev);
            return (EUCA_ERROR);
        }

        EUCA_FREE(output);
        return (EUCA_OK);
    }

    LOGWARN("cannot tune file system. lodev=%s\n", SP(lodev));
    return (EUCA_INVALID_ERROR);
}
Esempio n. 27
0
int diskutil_grub2_mbr (const char * path, const int part, const char * mnt_pt)
{
    char cmd [1024];
    int rc = 1;

    if (grub_version!=1 && grub_version!=2) {
        logprintfl (EUCAERROR, "{%u} internal error: invocation of diskutil_grub2_mbr without grub found\n", (unsigned int)pthread_self());
        return ERROR;
    } else if (mnt_pt==NULL && grub_version!=1) {
        logprintfl (EUCAERROR, "{%u} internal error: invocation of diskutil_grub2_mbr with grub 1 params\n", (unsigned int)pthread_self());
        return ERROR;
    }
    
    logprintfl (EUCAINFO, "{%u} installing grub in MBR\n", (unsigned int)pthread_self());
    if (grub_version==1) {
        char tmp_file [EUCA_MAX_PATH] = "/tmp/euca-temp-XXXXXX";
        int tfd = safe_mkstemp (tmp_file);
        if (tfd < 0) {
            logprintfl (EUCAINFO, "{%u} error: mkstemp() failed: %s\n", (unsigned int)pthread_self(), strerror (errno));
            return ERROR;
        }

        // create a soft link of the first partition's device mapper entry in the
        // form that grub is looking for (not DISKp1 but just DISK1)
        boolean created_partition_softlink = FALSE;
        char part_path [EUCA_MAX_PATH];
        snprintf (part_path, sizeof (EUCA_MAX_PATH), "%s1", path);
        if (check_path (part_path) != 0) {
            char *output = pruntf (TRUE, "%s /bin/ln -s %sp1 %s", helpers_path[ROOTWRAP], path, part_path);
            if (!output) {
                logprintfl (EUCAINFO, "{%u} warning: failed to create partition device soft-link (%s)\n", (unsigned int)pthread_self(), part_path);
            } else {
                created_partition_softlink = TRUE;
                free (output);
            }
        }

        // we now invoke grub through euca_rootwrap because it may need to operate on
        // devices that are owned by root (e.g. /dev/mapper/euca-dsk-7E4E131B-fca1d769p1)
        snprintf(cmd, sizeof (cmd), "%s %s --batch >%s 2>&1", helpers_path[ROOTWRAP], helpers_path[GRUB], tmp_file);
        logprintfl (EUCADEBUG, "{%u} running %s\n", (unsigned int)pthread_self(), cmd);
        errno = 0;
        FILE * fp = popen (cmd, "w");
        if (fp!=NULL) {
            char s [EUCA_MAX_PATH];
#define _PR fprintf (fp, "%s", s); // logprintfl (EUCADEBUG, "\t%s", s)
            snprintf (s, sizeof (s), "device (hd0) %s\n", path); _PR;
            snprintf (s, sizeof (s), "root (hd0,%d)\n", part);   _PR;
            snprintf (s, sizeof (s), "setup (hd0)\n");           _PR;
            snprintf (s, sizeof (s), "quit\n");                  _PR;
            rc = pclose (fp); // base success on exit code of grub
        }
        if (rc) {
            logprintfl (EUCAERROR, "{%u} error: failed to run grub 1 on disk '%s': %s\n", (unsigned int)pthread_self(), path, strerror (errno));
        } else {
            int read_bytes;
            char buf [1024];
            bzero (buf, sizeof (buf));
            boolean saw_done = FALSE;
            do {
                // read in a line
                int bytes_read = 0;
                while ((sizeof (buf) - 2 - bytes_read)>0 // there is space in buffer for \n and \0
                       && ((read_bytes = read (tfd, buf + bytes_read, 1)) > 0))
                    if (buf [bytes_read++] == '\n')
                        break;
                if (read_bytes < 0) // possibly truncated output, ensure there is newline
                    buf [bytes_read++] = '\n';
                buf [bytes_read] = '\0';
                logprintfl (EUCADEBUG, "\t%s", buf); // log grub 1 prompts and our inputs
                if (strstr (buf, "Done.")) // this indicates that grub 1 succeeded (the message has been there since 2000)
                    saw_done = TRUE;
            } while (read_bytes>0);
            close (tfd);

            if (saw_done==FALSE) {
                logprintfl (EUCAERROR, "{%u} error: failed to run grub 1 on disk '%s'\n", (unsigned int)pthread_self(), path);
                rc = 1;
            } else {
                rc = 0;
            }
        }

        // try to remove the partition device soft link that may have been created above
        if (created_partition_softlink) {
            char * output = pruntf (TRUE, "%s /bin/rm %s", helpers_path[ROOTWRAP], part_path);
            if(!output) {
                logprintfl (EUCAINFO, "{%u} warning: failed to remove partition device soft-link\n", (unsigned int)pthread_self());
            } else {
                free(output);
            }
        }

    } else if (grub_version==2) {
        // create device.map file
        char device_map_path [EUCA_MAX_PATH];
        char device_map_buf  [512];
        snprintf (device_map_path, sizeof (device_map_path), "%s/boot/grub/device.map", mnt_pt);
        snprintf (device_map_buf,  sizeof (device_map_buf),  "(hd0) %s\n", path);
        if (diskutil_write2file (device_map_path, device_map_buf)!=OK) {
            logprintfl (EUCAWARN, "{%u} error: failed to create device.map file\n", (unsigned int)pthread_self());
        } else {
            logprintfl (EUCAINFO, "{%u} wrote to '%s':\n", (unsigned int)pthread_self(), device_map_path);
            logprintfl (EUCAINFO, "{%u} %s", (unsigned int)pthread_self(), device_map_buf);
        }

        char * output = pruntf (TRUE, "%s %s --modules='part_msdos ext2' --root-directory=%s '(hd0)'", helpers_path[ROOTWRAP], helpers_path[GRUB_INSTALL], mnt_pt);
        if (!output) {
            logprintfl (EUCAINFO, "{%u} error: failed to install grub 2 on disk '%s' mounted on '%s'\n", (unsigned int)pthread_self(), path, mnt_pt);
        } else {
            free (output);
            rc = 0;
        }
    }
    
    if (rc==0) 
        return OK;    
    else
        return ERROR;
}
Esempio n. 28
0
int diskutil_grub_files (const char * mnt_pt, const int part, const char * kernel, const char * ramdisk)
{
    int ret = OK;
    char * output = NULL;
    char * kfile = "euca-vmlinuz";
    char * rfile = "euca-initrd";

    logprintfl (EUCAINFO, "{%u} installing kernel and ramdisk\n", (unsigned int)pthread_self());
    output = pruntf (TRUE, "%s %s -p %s/boot/grub/", helpers_path[ROOTWRAP], helpers_path[MKDIR], mnt_pt);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: failed to create grub directory\n", (unsigned int)pthread_self());
        return ERROR;
    }
    free (output);

    if (grub_version==1) {
        output = pruntf (TRUE, "%s %s %s/*stage* %s/boot/grub", helpers_path[ROOTWRAP], helpers_path[CP], stage_files_dir, mnt_pt);
        if (!output) {
            logprintfl (EUCAINFO, "{%u} error: failed to copy stage files into grub directory\n", (unsigned int)pthread_self());
            return ERROR;
        }
        free (output);
    }

    output = pruntf (TRUE, "%s %s %s %s/boot/%s", helpers_path[ROOTWRAP], helpers_path[CP], kernel, mnt_pt, kfile);
    if (!output) {
        logprintfl (EUCAINFO, "{%u} error: failed to copy the kernel to boot directory\n", (unsigned int)pthread_self());
        ret = ERROR;
        goto cleanup;
    }
    free (output);

    if (ramdisk) {
        output = pruntf (TRUE, "%s %s %s %s/boot/%s", helpers_path[ROOTWRAP], helpers_path[CP], ramdisk, mnt_pt, rfile);
        if (!output) {
            logprintfl (EUCAINFO, "{%u} error: failed to copy the ramdisk to boot directory\n", (unsigned int)pthread_self());
            ret = ERROR;
            goto cleanup;
        }
        free (output);
    }

    char buf [1024];
    char grub_conf_path [EUCA_MAX_PATH];
    if (grub_version==1) {
        char menu_lst_path [EUCA_MAX_PATH];
        snprintf (menu_lst_path, sizeof (menu_lst_path),   "%s/boot/grub/menu.lst", mnt_pt);
        snprintf (grub_conf_path, sizeof (grub_conf_path), "%s/boot/grub/grub.conf", mnt_pt);
    
        snprintf (buf, sizeof (buf), "default=0\n"
                  "timeout=2\n\n"
                  "title TheOS\n"
                  "root (hd0,%d)\n"
                  "kernel /boot/%s root=/dev/sda1 ro\n", part, kfile); // grub 1 expects 0 for first partition
        if (ramdisk) {
            char buf2 [1024];
            snprintf (buf2, sizeof (buf2), "initrd /boot/%s\n", rfile);
            strncat (buf, buf2, sizeof (buf) - 1);
        }    
        if (diskutil_write2file (menu_lst_path, buf)!=OK) {
            ret = ERROR;
            goto cleanup;
        }
        
    } else if (grub_version==2) {
        snprintf (grub_conf_path, sizeof (grub_conf_path), "%s/boot/grub/grub.cfg", mnt_pt);
        char initrd [1024] = "";
        if (ramdisk) {
            snprintf (initrd, sizeof (initrd), "  initrd /boot/%s\n", rfile);
        }    
        snprintf (buf, sizeof (buf), "set default=0\n"
                  "set timeout=2\n"
                  "insmod part_msdos\n"
                  "insmod ext2\n"
                  "set root='(hd0,%d)'\n"
                  "menuentry 'TheOS' --class os {\n"
                  "  linux /boot/%s root=/dev/sda1 ro\n"
                  "%s"
                  "}\n", part+1, kfile, initrd); // grub 2 expects 1 for first partition
    }
    if (diskutil_write2file (grub_conf_path, buf)!=OK) {
        ret = ERROR;
        goto cleanup;
    }
    
 cleanup:        
    return ret;
}
Esempio n. 29
0
int diskutil_get_parts(const char *path, struct partition_table_entry entries[], int num_entries)
{
    assert(path);
    assert(entries);
    assert(num_entries > 0);
    bzero(entries, sizeof(struct partition_table_entry) * num_entries);

    // output of 'parted DEV unit s print' looks roughly like:
    //
    // Model:  (file)
    // Disk /dev/loop8: 3072063s
    // Sector size (logical/physical): 512B/512B
    // Partition Table: msdos
    //
    //
    // Number  Start    End       Size      Type     File system  Flags
    //  2      63s      204862s   204800s   primary  ext3
    //  1      204863s  3072062s  2867200s  primary  ext3
    char *output = pruntf(TRUE, "LD_PRELOAD='' %s %s --script %s unit s print",
                          helpers_path[ROOTWRAP], helpers_path[PARTED], path);
    if (!output) {
        LOGERROR("cannot obtain partition information on device %s\n", path);
        return -1;
    }

    char *s = strstr(output, "Number");
    if (s == NULL) {
        LOGERROR("cannot parse 'parted print' output for device %s (no 'Number')\n", path);
        free(output);
        return -1;
    }
    s = strstr(output, "Flags\n");
    if (s == NULL) {
        LOGERROR("cannot parse 'parted print' output for device %s (no 'Flags')\n", path);
        free(output);
        return -1;
    }
    s += strlen("Flags\n");            // onto the next line

    // parse the partitions lines thatfollow the headers returned by 'parted print'
    char *pline = strtok(s, "\n");     // split by semicolon
    for (int p = 0; pline != NULL; p++) {
        int index;
        long long start;
        long long end;
        long long size;
        char *type;
        char *filesystem;

        // expect syntax like: 1      204863s  3072062s  2867200s  primary  ext3
        if (sscanf(pline, "%d %llds %llds %llds %ms %ms", &index, &start, &end, &size, &type, &filesystem) == 6) {
            int n = index - 1;
            if (n >= num_entries) {    // do not have room for this entry
                break;
            }
            entries[n].start_sector = start;
            entries[n].end_sector = end;
            euca_strncpy(entries[n].type, type, sizeof(entries[n].type));
            euca_strncpy(entries[n].filesystem, filesystem, sizeof(entries[n].filesystem));
            free(type);
            free(filesystem);
        }
        pline = strtok(NULL, "\n");
    }
    free(output);

    // run through the entries[], ensure they are contiguous, starting with [0]
    int count = 0;
    for (int n = 0; n < num_entries; n++) {
        if (entries[n].end_sector > 0) {
            count++;
        } else {
            break;
        }
    }

    return count;
}
Esempio n. 30
0
//!
//!
//!
//! @param[in] path
//! @param[in] offset
//! @param[in] lodev name of the loop device
//! @param[in] lodev_size
//!
//! @return EUCA_OK on success or the following error codes:
//!         \li EUCA_ERROR: if any error occured.
//!         \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions.
//!
//! @pre Both path and lodev parameters must not be NULL.
//!
//! @post On success, the loop device is attached.
//!
int diskutil_loop(const char *path, const long long offset, char *lodev, int lodev_size)
{
    int i = 0;
    int ret = EUCA_OK;
    char *ptr = NULL;
    char *output = NULL;
    boolean done = FALSE;
    boolean found = FALSE;
    boolean do_log = FALSE;

    if (path && lodev) {
        // we retry because we cannot atomically obtain a free loopback device on all distros (some
        // versions of 'losetup' allow a file argument with '-f' options, but some do not)
        for (i = 0, done = FALSE, found = FALSE; i < LOOP_RETRIES; i++) {
            sem_p(loop_sem);
            {
                output = pruntf(TRUE, "%s %s -f", helpers_path[ROOTWRAP], helpers_path[LOSETUP]);
            }
            sem_v(loop_sem);

            if (output == NULL) {
                // there was a problem
                break;
            }

            if (strstr(output, "/dev/loop")) {
                strncpy(lodev, output, lodev_size);
                if ((ptr = strrchr(lodev, '\n')) != NULL) {
                    *ptr = '\0';
                    found = TRUE;
                }
            }

            EUCA_FREE(output);

            if (found) {
                do_log = ((i + 1) == LOOP_RETRIES); // log error on last try only
                LOGDEBUG("attaching file %s\n", path);
                LOGDEBUG("            to %s at offset %lld\n", lodev, offset);
                sem_p(loop_sem);
                {
                    char str_offset[64];
                    snprintf(str_offset, sizeof(str_offset), "%lld", offset);
                    output = execlp_output(do_log, helpers_path[ROOTWRAP], helpers_path[LOSETUP], "-o", str_offset, lodev, path, NULL);
                }
                sem_v(loop_sem);

                if (output == NULL) {
                    LOGDEBUG("cannot attach to loop device %s (will retry)\n", lodev);
                } else {
                    EUCA_FREE(output);
                    done = TRUE;
                    break;
                }
            }

            sleep(1);
            found = FALSE;
        }

        if (!done) {
            LOGERROR("cannot find free loop device or attach to one\n");
            ret = EUCA_ERROR;
        }

        return (ret);
    }

    LOGWARN("cannot attach to loop device. path=%s, lodev=%s\n", SP(path), SP(lodev));
    return (EUCA_INVALID_ERROR);
}