コード例 #1
0
ファイル: rbh_undo_rm.c プロジェクト: mjtrangoni/robinhood
static inline void display_rm_entry(entry_id_t * id, const char *last_known_path,
#ifdef _HSM_LITE
                             const char *bkpath,
#endif
                             time_t soft_rm_time, time_t expiration_time)
{
    char           date_rm[128];
    char           date_exp[128];
    struct tm      t;

    strftime( date_rm, 128, "%Y/%m/%d %T", localtime_r( &soft_rm_time, &t ) );
    strftime( date_exp, 128, "%Y/%m/%d %T", localtime_r( &expiration_time, &t ) );

    printf( "Fid:               "DFID"\n", PFID(id) );
    if ( !EMPTY_STRING(last_known_path) )
        printf( "Last known path:   %s\n", last_known_path );
#ifdef _HSM_LITE
    if ( !EMPTY_STRING(bkpath) )
        printf( "Backend path:      %s\n", bkpath );
#endif
    printf( "Removal time:      %s\n", date_rm );
    if ( expiration_time <= time(NULL) )
        printf( "Delayed until:     %s (expired)\n", date_exp );
    else
        printf( "Delayed until:     %s\n", date_exp );
}
コード例 #2
0
ファイル: rbh_undo_rm.c プロジェクト: fred-lefebvre/robinhood
static inline void undo_rm_helper( entry_id_t * id, const char *last_known_path,
#ifdef _HSM_LITE
                             const char *bkpath
#endif
                             )
{
    entry_id_t new_id;
    recov_status_t st;
    attr_set_t     attrs, new_attrs;
    int rc;

    /* XXX src path must be in the same filesystem as backend
     * because it we be renamed */

    if ( EMPTY_STRING( last_known_path ) )
    {
        fprintf(stderr, "Last filesystem path is not known for fid "DFID", backend_path=%s.\n",
                PFID(id), bkpath);
        fprintf(stderr, " ----> skipped\n");
        return;
    }

    printf("Restoring '%s'...\n", last_known_path );

    ATTR_MASK_INIT(&attrs);
    ATTR_MASK_SET(&attrs, fullpath);
    strcpy( ATTR(&attrs, fullpath), last_known_path );

    if ( !EMPTY_STRING( bkpath ) )
    {
        ATTR_MASK_SET(&attrs, backendpath);
        strcpy( ATTR(&attrs, backendpath), bkpath );
    }

    /* copy file to Lustre */
    ATTR_MASK_INIT(&new_attrs);
    st = rbhext_recover( id, &attrs, &new_id, &new_attrs, NULL );
    if ((st == RS_FILE_OK) || (st == RS_FILE_DELTA)|| (st == RS_FILE_EMPTY)
        ||  (st == RS_NON_FILE))
    {
        printf("Success\n");
        /* discard entry from remove list */
        if ( ListMgr_SoftRemove_Discard(&lmgr, id) != 0 )
            fprintf(stderr, "Error: could not remove previous id "DFID" from database\n", PFID(id) );
        /* clean read-only attrs */
        new_attrs.attr_mask &= ~readonly_attr_set;
        /* insert or update it in the db */
        rc = ListMgr_Insert( &lmgr, &new_id, &new_attrs, TRUE );
        if ( rc == 0 )
            printf("Entry successfully updated in the dabatase\n");
        else
            fprintf(stderr, "ERROR %d inserting entry in the database\n", rc );
    }
    else
    {
        printf("ERROR\n");
    }
}
コード例 #3
0
int InitializeLogs(const char *program_name)
{
    struct utsname uts;
    char          *tmp;
    int            rc;

    /* get node name */
    if (uname(&uts) == -1)
        strcpy(machine_name, "???");
    else
        rh_strncpy(machine_name, uts.nodename, RBH_PATH_MAX);

    /* if the name is the full machine name (node.subnet.domain.ext),
     * only kief the brief name */
    if ((tmp = strchr(machine_name, '.')) != NULL)
        *tmp = '\0';

    if (program_name == NULL)
        strcpy(prog_name, "???");
    else
        rh_strncpy(prog_name, program_name, RBH_PATH_MAX);

    /* open log files */
    rc = init_log_descr(log_config.log_file, &log);
    if (rc)
        return rc;

    rc = init_log_descr(log_config.report_file, &report);
    if (rc)
        return rc;

    if (!EMPTY_STRING(log_config.alert_file)) {
        rc = init_log_descr(log_config.alert_file, &alert);
        if (rc)
            return rc;
    }
#ifdef HAVE_CHANGELOGS
    if (!EMPTY_STRING(log_config.changelogs_file)) {
        rc = init_log_descr(log_config.changelogs_file, &chglogs);
        if (rc)
            return rc;
    }
#endif

    /* Update log level for external components we get logs from (LLAPI...) */
    rbh_adjust_log_level_external();

    last_time_test = time(NULL);
    log_initialized = true;

    return 0;

}   /* InitializeLogs */
コード例 #4
0
static void test_file_names(void)
{
    log_init_check();

    test_log_descr(log_config.log_file, &log);
    test_log_descr(log_config.report_file, &report);

    if (!EMPTY_STRING(log_config.alert_file))
        test_log_descr(log_config.alert_file, &alert);

#ifdef HAVE_CHANGELOGS
    if (!EMPTY_STRING(log_config.changelogs_file))
        test_log_descr(log_config.changelogs_file, &chglogs);
#endif
}
コード例 #5
0
ファイル: lustre_tools.c プロジェクト: mjtrangoni/robinhood
int File_CreateSetStripe( const char * path, const stripe_info_t * old_stripe )
{
    int rc;

    /* try to restripe using previous pool name */
    if ( !EMPTY_STRING( old_stripe->pool_name ) )
    {
        rc = llapi_file_create_pool( path, old_stripe->stripe_size,
                                     -1, old_stripe->stripe_count, 0,
                                     (char *)old_stripe->pool_name );
        if ( rc == 0 || rc == -EEXIST )
            return rc;
        else
        {
            DisplayLog( LVL_MAJOR, TAG_CR_STRIPE, "Error %d creating '%s' in pool '%s': %s",
                        rc, path, old_stripe->pool_name, strerror(-rc) );
            DisplayLog( LVL_MAJOR, TAG_CR_STRIPE, "Trying to create it without pool information..." );
        }
    }

    rc = llapi_file_create( path, old_stripe->stripe_size,
                            -1, old_stripe->stripe_count, 0 );
    if ( rc != 0 || rc == -EEXIST )
        DisplayLog( LVL_MAJOR, TAG_CR_STRIPE,
                    "Error %d creating '%s' with stripe. Trying to create it without specific stripe...",
                    rc, path );
    return rc;
}
コード例 #6
0
ファイル: lustre_tools.c プロジェクト: seagate-ssg/robinhood
int CreateStriped( const char * path, const stripe_info_t * old_stripe, int overwrite )
{
    int rc;

    /* try to restripe using previous pool name */
    if ( !EMPTY_STRING( old_stripe->pool_name ) )
        rc = llapi_file_create_pool( path, old_stripe->stripe_size,
                                     -1, old_stripe->stripe_count, 0,
                                     (char *)old_stripe->pool_name );
    else
        rc = llapi_file_create( path, old_stripe->stripe_size,
                                -1, old_stripe->stripe_count, 0 );
    if ((rc == -EEXIST) && overwrite)
    {
        if (unlink(path)) {
            rc = -errno;
            DisplayLog( LVL_MAJOR, TAG_CR_STRIPE, "Can't remove previous entry %s: %s",
                        path, strerror(-rc));
            return rc;
        }
        return CreateStriped(path, old_stripe, false /*target not expected to exist*/);
    }
    else if ( rc != 0 && rc != -EEXIST )
    {
        DisplayLog( LVL_MAJOR, TAG_CR_STRIPE, "Error %d creating '%s' with stripe.",
                    rc, path );
    }
    return rc;
}
コード例 #7
0
static int log_cfg_set(void *cfg, bool reload)
{
    log_config_t *config = (log_config_t *) cfg;
    char old_log_file[RBH_PATH_MAX] = "";
    int old_level = -1;

    if (reload)
        return log_cfg_reload(config);

    /* keep previous values in case log level is forced */
    if (log_config.force_debug_level)
        old_level = log_config.debug_level;

    if (log_config.force_log_file)
        rh_strncpy(old_log_file, log_config.log_file, sizeof(old_log_file));

    log_config = *config;

    /* restore previous values */
    if (old_level != -1) {
        log_config.force_debug_level = true;
        log_config.debug_level = old_level;
    }
    if (!EMPTY_STRING(old_log_file)) {
        log_config.force_log_file = true;
        rh_strncpy(log_config.log_file, old_log_file,
                   sizeof(log_config.log_file));
    }

    return 0;
}
コード例 #8
0
void RaiseAlert(const char *title, const char *format, ...)
{
    va_list     args;
    char        mail[MAX_MAIL_LEN];
    char        title2[1024];
    int         written;
    time_t      now = time(NULL);
    struct tm   date;

    log_init_check();

    /* send alert mail, if an address was specified in config file */
    if (!EMPTY_STRING(log_config.alert_mail)) {
        localtime_r(&now, &date);
        written = snprintf(mail, MAX_MAIL_LEN,
                           "===== %s =====\n"
                           "Date: %.4d/%.2d/%.2d %.2d:%.2d:%.2d\n"
                           "Program: %s (pid %lu)\n"
                           "Host: %s\n"
                           "Filesystem: %s\n",
                           title, 1900 + date.tm_year, date.tm_mon + 1,
                           date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec,
                           prog_name, (unsigned long)getpid(), machine_name,
                           global_config.fs_path);

        va_start(args, format);
        vsnprintf(mail + written, MAX_MAIL_LEN - written, format, args);
        va_end(args);

        snprintf(title2, 1024, "%s (%s on %s)", title, global_config.fs_path,
                 machine_name);
        SendMail(log_config.alert_mail, title2, mail);
    }

    if (!EMPTY_STRING(log_config.alert_file)) {
        display_line_log_(&alert, "ALERT", "%s", title);
        va_start(args, format);
        display_line_log(&alert, "ALERT", format, args);
        va_end(args);

        /* always flush alerts, because we don't want to lose events */
        flush_log_descr(&alert);
    }

}   /* DisplayAlert */
コード例 #9
0
ファイル: RobinhoodLogs.c プロジェクト: bringhurst/robinhood
void RaiseEntryAlert( const char *alert_name, /* alert name (if set) */
                      const char *alert_string, /* alert description */
                      const char *entry_path,   /* entry path */
                      const char *entry_info)  /* alert related attributes */
{
   char title[1024];

   /* lockless check (not a big problem if some alerts are sent without
    * being batched).
    */
   if ( alert_batching )
   {
        if ( alert_name && !EMPTY_STRING(alert_name) )
            strcpy(title, alert_name );
        else
        {
            if ( snprintf(title, 1024, "unnamed alert %s", alert_string ) > 80 )
            {
                /* truncate at 80 char: */
                strcpy( title+77, "..." );
            }
        }

        Alert_Add( title, entry_path, entry_info );
   }
   else
   {
        if ( alert_name && !EMPTY_STRING(alert_name) )
            snprintf(title, 1024, "Robinhood alert (%s on %s): %s", global_config.fs_path,
                    machine_name, alert_name );
        else
            snprintf(title, 1024, "Robinhood alert (%s on %s): entry matches alert rule",
                    global_config.fs_path, machine_name );

        if ( log_config.alert_show_attrs )
            RaiseAlert( title, "Entry: %s\nAlert condition: %s\n"
                        "Entry info:\n%s", entry_path, alert_string,
                        entry_info );
        else
            RaiseAlert( title, "Entry: %s\nAlert condition: %s\n",
                        entry_path, alert_string );
    }
}
コード例 #10
0
ファイル: search_cb.c プロジェクト: Longdengyu/gtk-gnutella
/* Display XML data from the result if any */
static void
search_set_xml_metadata(const record_t *rc)
{
	char *indented;

	indented = (rc && rc->xml) ? xml_indent(rc->xml) : NULL;
	set_text_buffer(gui_main_window_lookup("text_result_info_xml"),
		EMPTY_STRING(indented));
	HFREE_NULL(indented);
}
コード例 #11
0
ファイル: search_cb.c プロジェクト: Longdengyu/gtk-gnutella
void
search_gui_append_detail(const gchar *name, const gchar *value)
{
 	const gchar *titles[2];

	g_return_if_fail(clist_search_details);

	titles[0] = name;
	titles[1] = EMPTY_STRING(value);
    gtk_clist_append(clist_search_details, (gchar **) titles);
}
コード例 #12
0
void DisplayChangelogs(const char *format, ...)
{
    va_list args;

    /* Bail out if no file defined */
    if (EMPTY_STRING(log_config.changelogs_file))
        return;

    va_start(args, format);
    display_line_log(&chglogs, NULL, format, args);
    va_end(args);
}
コード例 #13
0
ファイル: rbh_undo_rm.c プロジェクト: mjtrangoni/robinhood
static int is_fid_filter(entry_id_t * id)
{
    lustre_fid  fid;
    if ( !EMPTY_STRING( path_filter ) )
    {
        if (sscanf(path_filter, SFID, RFID(&fid)) != 3)
            return FALSE;
        else {
            if (id)
                *id = fid;
            return TRUE;
        }
    }
    return FALSE;
}
コード例 #14
0
ファイル: rbh_undo_rm.c プロジェクト: mjtrangoni/robinhood
/*
 * Append global filters on path
 * \param do_display [in] display filters?
 * \param initialized [in/out] indicate if the filter is initialized.
 */
static int mk_path_filter( lmgr_filter_t * filter, int do_display, int * initialized )
{
    filter_value_t fv;
    char path_regexp[RBH_PATH_MAX] = "";
    size_t  len;

    /* is a filter on path specified? */
    if ( !EMPTY_STRING( path_filter ) )
    {
        if ( (initialized != NULL) && !(*initialized) )
        {
            lmgr_simple_filter_init( filter );
            *initialized = TRUE;
        }
        if ( do_display )
            printf("filter path: %s\n", path_filter );

        len = strlen(path_filter);
        if ( path_filter[len-1] != '/' )
        {
            /* ( fullpath LIKE 'path' OR fullpath LIKE 'path/%' ) */
            fv.val_str = path_filter;
            lmgr_simple_filter_add( filter, ATTR_INDEX_fullpath, LIKE, fv,
                                    FILTER_FLAG_BEGIN );

            snprintf( path_regexp, RBH_PATH_MAX, "%s/*", path_filter );
            fv.val_str = path_regexp;
            lmgr_simple_filter_add( filter, ATTR_INDEX_fullpath, LIKE, fv,
                                    FILTER_FLAG_OR | FILTER_FLAG_END );
        }
        else /* ends with slash */
        {
            snprintf( path_regexp, RBH_PATH_MAX, "%s*", path_filter );
            /* directory or directory/% */

            fv.val_str = path_regexp;
            lmgr_simple_filter_add( filter, ATTR_INDEX_fullpath, LIKE, fv,
                                    FILTER_FLAG_BEGIN );
            /* remove last slash */
            path_filter[len-1] = '\0';
            fv.val_str = path_filter;
            lmgr_simple_filter_add( filter, ATTR_INDEX_fullpath, LIKE, fv,
                                    FILTER_FLAG_OR | FILTER_FLAG_END );
        }
    }
    return 0;
}
コード例 #15
0
ファイル: RobinhoodLogs.c プロジェクト: bringhurst/robinhood
int InitializeLogs( char *program_name, const log_config_t * config )
{
    struct utsname uts;
    char          *tmp;
    int            rc;

    /* store module configuration */
    log_config = *config;

    /* get node name */

    if ( uname( &uts ) == -1 )
        strcpy( machine_name, "???" );
    else
        strncpy( machine_name, uts.nodename, RBH_PATH_MAX );

    /* if the name is the full machine name (node.subnet.domain.ext),
     * only kief the brief name */
    if ( ( tmp = strchr( machine_name, '.' ) ) != NULL )
        *tmp = '\0';

    if ( program_name == NULL )
        strcpy( prog_name, "???" );
    else
        strncpy( prog_name, program_name, RBH_PATH_MAX );

    /* open log files */
    rc = init_log_descr( log_config.log_file, &log );
    if (rc) return rc;

    rc = init_log_descr( log_config.report_file, &report );
    if (rc) return rc;

    if ( !EMPTY_STRING( log_config.alert_file ) )
    {
        rc = init_log_descr( log_config.alert_file, &alert );
        if (rc) return rc;
    }

    last_time_test = time( NULL );


    log_initialized = TRUE;

    return 0;

}   /* InitializeLogs */
コード例 #16
0
ファイル: RobinhoodLogs.c プロジェクト: bringhurst/robinhood
static void test_file_names(  )
{
    log_init_check(  );

    /* if the lock is taken, return immediately
     * (another thread is doing the check)
     */
    if ( pthread_mutex_trylock( &mutex_reopen ) != 0 )
        return;

    test_log_descr( log_config.log_file, &log );
    test_log_descr( log_config.report_file, &report );

    if ( !EMPTY_STRING( log_config.alert_file ) )
        test_log_descr( log_config.alert_file, &alert );

    pthread_mutex_unlock( &mutex_reopen );

}
コード例 #17
0
ファイル: rbh_undo_rm.c プロジェクト: fred-lefebvre/robinhood
/*
 * Append global filters on path
 * \param do_display [in] display filters?
 * \param initialized [in/out] indicate if the filter is initialized.
 */
static int mk_path_filter( lmgr_filter_t * filter, int do_display, int * initialized )
{
    filter_value_t fv;
    char path_regexp[RBH_PATH_MAX] = "";
    size_t  len;

    /* is a filter on path specified? */
    if ( !EMPTY_STRING( path_filter ) )
    {
        if ( (initialized != NULL) && !(*initialized) )
        {
            lmgr_simple_filter_init( filter );
            *initialized = TRUE;
        }
        if ( do_display )
            printf("filter path: %s\n", path_filter );

        len = strlen(path_filter);
        /* remove last slash */
        if (path_filter[len-1] == '/')
            path_filter[len-1] = '\0';

        /* as this is a RLIKE matching, shell regexp must be replaced by perl:
         * [abc] => OK
         * '*' => '.*'
         * '?' => '.'
         */
        str_replace(path_filter, "*", ".*");
        str_replace(path_filter, "?", ".");

        /* match 'path$' OR 'path/.*' */
        snprintf(path_regexp, RBH_PATH_MAX, "%s($|/.*)", path_filter);
        fv.value.val_str = path_regexp;

        lmgr_simple_filter_add(filter, ATTR_INDEX_fullpath, RLIKE, fv, 0);
    }
    return 0;
}
コード例 #18
0
ファイル: namemaps.c プロジェクト: bahamas10/openzfs
idmap_stat
idmap_init_namemaps(idmap_nm_handle_t **adh,
    char *user, char *passwd, char *auth, char *windomain,
    int direction)
{
	idmap_stat rc;
	idmap_nm_handle_t *p;

	p = (idmap_nm_handle_t *)calloc(1, sizeof (idmap_nm_handle_t));
	if (p == NULL)
		return (IDMAP_ERR_MEMORY);

	rc = idmap_get_prop_str(PROP_DEFAULT_DOMAIN,
	    &p->default_domain);
	if (rc != IDMAP_SUCCESS) {
		namemap_log(
		    gettext("Error obtaining default domain from idmapd (%s)"),
		    idmap_stat2string(rc));
		goto cleanup;
	}

	rc = idmap_get_prop_str(PROP_AD_UNIXUSER_ATTR,
	    &p->ad_unixuser_attr);
	if (rc != IDMAP_SUCCESS) {
		namemap_log(
		    gettext("Error obtaining AD unixuser attribute (%s)"),
		    idmap_stat2string(rc));
		goto cleanup;
	}

	rc = idmap_get_prop_str(PROP_AD_UNIXGROUP_ATTR,
	    &p->ad_unixgroup_attr);
	if (rc != IDMAP_SUCCESS) {
		namemap_log(
		    gettext("Error obtaining AD unixgroup attribute (%s)"),
		    idmap_stat2string(rc));
		goto cleanup;
	}


	rc = idmap_get_prop_str(PROP_NLDAP_WINNAME_ATTR,
	    &p->nldap_winname_attr);
	if (rc != IDMAP_SUCCESS) {
		namemap_log(
		    gettext("Error obtaining AD unixgroup attribute (%s)"),
		    idmap_stat2string(rc));
		goto cleanup;
	}

	if (windomain != NULL) {
		p->windomain = strdup(windomain);
		if (p->windomain == NULL) {
			rc = IDMAP_ERR_MEMORY;
			goto cleanup;
		}
	} else if (!EMPTY_STRING(p->default_domain)) {
		p->windomain = strdup(p->default_domain);
		if (p->windomain == NULL) {
			rc = IDMAP_ERR_MEMORY;
			goto cleanup;
		}
	} else if (direction == IDMAP_DIRECTION_W2U) {
		namemap_log(
		    gettext("Windows domain not given and idmapd daemon"
		    " didn't provide a default one"));
		rc = IDMAP_ERR_ARG;
		goto cleanup;
	}

	p->direction = direction;

	if ((p->ad_unixuser_attr != NULL || p->ad_unixgroup_attr != NULL) &&
	    direction != IDMAP_DIRECTION_U2W) {
		rc = idmap_init_ad(p);
		if (rc != IDMAP_SUCCESS) {
			goto cleanup;
		}
	}

	if (p->nldap_winname_attr != NULL && direction != IDMAP_DIRECTION_W2U) {
		rc = idmap_init_nldap(p);
		if (rc != IDMAP_SUCCESS) {
			goto cleanup;
		}

		rc = strings2cred(&p->nsc, user, passwd, auth);
		if (rc != IDMAP_SUCCESS) {
			goto cleanup;
		}
	}

cleanup:

	if (rc == IDMAP_SUCCESS) {
		*adh = p;
		return (IDMAP_SUCCESS);
	}

	/* There was an error: */
	idmap_fini_namemaps(*adh);
	return (rc);
}
コード例 #19
0
/**
 * Extract information from SOAP fault tree.
 *
 * @param fault		the XML <Fault> tree
 * @param code		where UPnP error code is written, if non-NULL
 * @param error		where address of UPnP error string is written, if non-NULL
 *
 * @attention
 * The error string is pointing in the XML tree and will become invalid as
 * soon as the tree is freed so it needs to be duplicated if it must persist.
 *
 * @return TRUE if OK, FALSE on error.
 */
static gboolean
upnp_ctrl_extract_fault(xnode_t *fault, int *code, const char **error)
{
	xnode_t *fcode, *fstring, *detail, *uerror;
	const char *parse_error = NULL;

	g_assert(fault != NULL);

	/*
	 * The SOAP specification for the <faultcode> element are very bad.
	 * Indeed, the content is a string bearing the *prefix* of the SOAP
	 * namespace, which is completely arbitrary and not accessible at this
	 * level since all nodes are normalized with their namespace, the prefix
	 * string being irrelevant once parsing is done.  And namespace have no
	 * meaning in element *content*.
	 *
	 * Sure, we know we force the "s" prefix for SOAP, and most UPnP stacks
	 * are going to use that prefix as well, but matching the <faultcode>
	 * content to look for "s:Client" or "s:MustUnderstand" is just plain
	 * wrong, and a blatant encapsulation violation.
	 *
	 * So instead we look backwards in the string to find the first ':' and
	 * consider the tail part of the string, totally ignoring the prefix.
	 * That's a lousy parsing, but in practice it's going to work and should
	 * be safe since there's little choice anyway according to the SOAP
	 * specifications (meaning they could have just as well ignored the
	 * prefix in this string and just mandate "Client" or "MustUnderstand").
	 *
	 * Also note that <faultcode>, <faultstring> and <detail> elements are
	 * architected without any SOAP namespace.  That's surprising.
	 */

	fcode = xnode_tree_find_depth(fault, 1, node_named_as,
		deconstify_gchar(SOAP_FAULT_CODE));

	if (NULL == fcode) {
		parse_error = "cannot find <faultcode>";
		goto error;
	} else {
		const char *value;
		const char *name;

		value = xnode_first_text(fcode);
		if (NULL == value) {
			parse_error = "<faultcode> does not contain text";
			goto error;
		}

		/*
		 * We're only handling "Client" errors.
		 */

		name = strrchr(value, ':');
		if (NULL == name) {
			parse_error = "no ':' in fault code name";
			goto error;
		}

		name++;

		if (0 != strcmp(name, SOAP_CLIENT_FAULT)) {
			parse_error = "not a Client fault";
			goto error;
		}
	}

	/*
	 * Here is a sample fault tree from the UPnP 1.0 architecture:
	 *
	 * <s:Fault>
	 *   <faultcode>s:Client</faultcode>
	 *   <faultstring>UPnPError</faultstring>
	 *   <detail>
	 *     <UPnpError xmlns="urn:schemas-upnp-org:control-1-0">
	 *       <errorCode>error code</errorCode>
	 *       <errorDescription>error string</errorDescription>
	 *     </UPnPError>
	 *   </detail>
	 * <s:Fault>
	 *
	 * Note that the UPnP tags are in the "urn:schemas-upnp-org:control-1-0"
	 * namespace.
	 */

	fstring = xnode_tree_find_depth(fault, 1, node_named_as,
		deconstify_gchar(SOAP_FAULT_STRING));

	if (NULL == fstring) {
		parse_error = "no <faultstring> found";
		goto error;
	} else {
		const char *value;

		value = xnode_first_text(fstring);
		if (NULL == value) {
			parse_error = "<faultstring> does not contain text";
			goto error;
		}

		if (0 != strcmp(value, SOAP_UPNP_ERROR)) {
			parse_error = "<faultstring> is not an UPnP error";
			goto error;
		}
	}

	detail = xnode_tree_find_depth(fault, 1, node_named_as,
		deconstify_gchar(SOAP_FAULT_DETAIL));

	if (NULL == detail) {
		parse_error = "no <detail> found";
		goto error;
	}

	/*
	 * First child must be a <UPnpError> tag.
	 */

	uerror = xnode_first_child(detail);
	if (xnode_is_element_named(uerror, UPNP_NS_ERROR, SOAP_UPNP_ERROR)) {
		xnode_t *xn;

		if (code != NULL) {
			const char *value;
			int err;

			xn = xnode_tree_find_depth(uerror, 1,
				node_named_as, deconstify_gchar(UPNP_ERROR_CODE));

			if (NULL == xn) {
				parse_error = "no <errorCode> found";
				goto error;
			}

			value = xnode_first_text(xn);
			if (NULL == value) {
				parse_error = "<errorCode> doest not contain text";
				goto error;
			}

			*code = parse_uint32(value, NULL, 10, &err);
			if (err) {
				parse_error = "cannot parse <errorCode> value";
				goto error;
			}
		}

		if (error != NULL) {
			xn = xnode_tree_find_depth(uerror, 1,
				node_named_as, deconstify_gchar(UPNP_ERROR_DESC));

			*error = (NULL == xn) ? NULL : xnode_first_text(xn);
		}
	} else {
		parse_error = "no <UPnPError> found";
		goto error;
	}

	return TRUE;

error:
	if (GNET_PROPERTY(upnp_debug))
		g_warning("UPNP fault parsing error: %s", EMPTY_STRING(parse_error));

	return FALSE;
}
コード例 #20
0
ファイル: tls_common.c プロジェクト: Longdengyu/gtk-gnutella
/**
 * Initiates a new TLS session.
 *
 * @return 0 on success, -1 on error.
 */
int
tls_init(struct gnutella_socket *s)
{
    /**
     * ANON-DH is enabled because we don't use PKI.
     * DEFLATE is disabled because it seems to cause crashes.
     * ARCFOUR-40 is disabled because it is deprecated.
     */
    static const char prio_want[] = "NORMAL:+ANON-DH:-ARCFOUR-40:-COMP-DEFLATE";
    /* "-COMP-DEFLATE" is causing an error on MinGW with GnuTLS 2.10.2 */
    static const char prio_must[] = "NORMAL:+ANON-DH:-ARCFOUR-40";
    const bool server = SOCK_CONN_INCOMING == s->direction;
    struct tls_context *ctx;
    const char *fn;
    int e;

#define TRY(function) (fn = (#function)), e = function

    socket_check(s);

    WALLOC0(ctx);
    ctx->s = s;
    s->tls.ctx = ctx;

    if (
        TRY(gnutls_init)(&ctx->session, server ? GNUTLS_SERVER : GNUTLS_CLIENT)
    ) {
        ctx->session = NULL;
        goto failure;
    }

    if (TRY(gnutls_priority_set_direct)(ctx->session, prio_want, NULL)) {
        const char *error;
        if (TRY(gnutls_priority_set_direct)(ctx->session, prio_must, &error)) {
            g_warning("%s() failed at \"%s\"", fn, error);
            goto failure;
        }
    }

    if (TRY(gnutls_credentials_set)(ctx->session,
                                    GNUTLS_CRD_CERTIFICATE, cert_cred))
        goto failure;

    gnutls_dh_set_prime_bits(ctx->session, TLS_DH_BITS);

#ifdef USE_TLS_CUSTOM_IO
    gnutls_transport_set_ptr(ctx->session, s);
    gnutls_transport_set_push_function(ctx->session, tls_push);
    gnutls_transport_set_pull_function(ctx->session, tls_pull);
#if !HAS_TLS(2, 12)
    /*
     * This routine has been removed starting TLS 3.0.  It was used to disable
     * the lowat feature, and apparently this is now always the case in recent
     * TLS versions.	--RAM, 2011-09-28
     *
     * It's also flagged as deprecated in 2.12.x, so don't use it there.
     *		--RAM, 2011-12-15
     */
    gnutls_transport_set_lowat(ctx->session, 0);
#endif
#else	/* !USE_TLS_CUSTOM_IO */
    g_assert(is_valid_fd(s->file_desc));
    gnutls_transport_set_ptr(ctx->session, int_to_pointer(s->file_desc));
#endif	/* USE_TLS_CUSTOM_IO */

    if (server) {
        if (TRY(gnutls_anon_allocate_server_credentials)(&ctx->server_cred))
            goto failure;

        gnutls_anon_set_server_dh_params(ctx->server_cred, get_dh_params());

        if (TRY(gnutls_credentials_set)(ctx->session,
                                        GNUTLS_CRD_ANON, ctx->server_cred))
            goto failure;

    } else {
        if (TRY(gnutls_anon_allocate_client_credentials)(&ctx->client_cred))
            goto failure;

        if (TRY(gnutls_credentials_set)(ctx->session,
                                        GNUTLS_CRD_ANON, ctx->client_cred))
            goto failure;
    }

    return 0;

failure:
    g_warning("%s() failed: %s", EMPTY_STRING(fn), gnutls_strerror(e));
    tls_free(s);
    return -1;
#undef TRY
}
コード例 #21
0
ファイル: rbh_rebind.c プロジェクト: cea-hpc/robinhood
/**
 * Main daemon routine
 */
int main(int argc, char **argv)
{
    int c, option_index = 0;
    const char *bin;
    char config_file[MAX_OPT_LEN] = "";

    int rc;
    char err_msg[4096];
    bool chgd = false;
    char badcfg[RBH_PATH_MAX];
    char sm_name[SM_NAME_MAX + 1] = "";

    bin = rh_basename(argv[0]);

    /* parse command line options */
    while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab,
                            &option_index)) != -1) {
        switch (c) {
        case 'f':
            rh_strncpy(config_file, optarg, MAX_OPT_LEN);
            break;
        case 'l':
        {
            int log_level = str2debuglevel(optarg);

            if (log_level == -1) {
                fprintf(stderr,
                        "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n",
                        optarg);
                exit(1);
            }
            force_debug_level(log_level);
            break;
        }

        case 's':
            if (!EMPTY_STRING(sm_name))
                fprintf(stderr,
                        "WARNING: only a single status manager is expected "
                        "on command line. '%s' ignored.\n", optarg);
            else
                rh_strncpy(sm_name, optarg, sizeof(sm_name));
            break;

        case 'h':
            display_help(bin);
            exit(EXIT_SUCCESS);
            break;
        case 'V':
            display_version(bin);
            exit(EXIT_SUCCESS);
            break;
        case ':':
        case '?':
        default:
            display_help(bin);
            exit(1);
            break;
        }
    }

    /* 2 expected argument: old backend path, new path is FS */
    if (optind > argc - 3) {
        fprintf(stderr, "Error: missing arguments on command line.\n");
        display_help(bin);
        exit(1);
    } else if (optind < argc - 4) {
        fprintf(stderr, "Error: too many arguments on command line.\n");
        display_help(bin);
        exit(1);
    }

    rc = rbh_init_internals();
    if (rc != 0)
        exit(EXIT_FAILURE);

    /* get default config file, if not specified */
    if (SearchConfig(config_file, config_file, &chgd, badcfg,
                     MAX_OPT_LEN) != 0) {
        fprintf(stderr, "No config file (or too many) found matching %s\n",
                badcfg);
        exit(2);
    } else if (chgd) {
        fprintf(stderr, "Using config file '%s'.\n", config_file);
    }

    /* only read common config (listmgr, ...) (mask=0) */
    if (rbh_cfg_load(0, config_file, err_msg)) {
        fprintf(stderr, "Error reading configuration file '%s': %s\n",
                config_file, err_msg);
        exit(1);
    }

    if (!log_config.force_debug_level)
        log_config.debug_level = LVL_MAJOR; /* no event message */

    /* Set logging to stderr */
    strcpy(log_config.log_file, "stderr");
    strcpy(log_config.report_file, "stderr");
    strcpy(log_config.alert_file, "stderr");

    /* Initialize logging */
    rc = InitializeLogs(bin);
    if (rc) {
        fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n",
                rc, errno, strerror(errno));
        exit(EXIT_FAILURE);
    }

    /* Initialize Filesystem access */
    rc = InitFS();
    if (rc)
        exit(EXIT_FAILURE);

    /* Initialize status managers (XXX all or just the one used for undelete?)
     */
    rc = smi_init_all(0);
    if (rc)
        exit(EXIT_FAILURE);

    /* load the status manager */
    if (!EMPTY_STRING(sm_name)) {
        rc = load_smi(sm_name, &smi);
        if (rc)
            exit(EXIT_FAILURE);
    } else {
        /* if there is a single smi that allows undelete, use it */
        rc = load_single_smi(&smi);
        if (rc)
            exit(EXIT_FAILURE);
    }

    if (optind == argc - 3)
        rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2],
                          NULL);
    else if (optind == argc - 4)
        rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2],
                           argv[optind + 3]);

    exit(rc ? EXIT_FAILURE: EXIT_SUCCESS);
}
コード例 #22
0
// -----------------------------------------------------------------------------
// CLibxml2Tester::SerializeGZIPL
// test GZIP Serialize
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TInt CLibxml2Tester::SerializeGZIPL(CStifItemParser& aItem)
{
    TInt error(KErrGeneral);

    //get test controls, input&output paths
    TPtrC pControl;
    aItem.GetNextString( pControl );

    TPtrC pBinary;
    aItem.GetNextString( pBinary );

    TPtrC pXml;
    aItem.GetNextString( pXml );

    TPtrC pSerialized;
    aItem.GetNextString( pSerialized );

    TPtrC pGzipSerialized;
    aItem.GetNextString( pGzipSerialized );

    TPtrC pOptions;
    aItem.GetNextString( pOptions );

    // saves xml file with binary data added ( default serialize )
    RXmlEngDocument iDocument;
    CleanupClosePushL( iDocument );
    if( pControl.FindF( SINGLE ) != KErrNotFound )
    {
        error = SaveXmlWithBinaryDataL( iDocument, pOptions, pBinary, pXml, EMPTY_STRING() );
    }
    else if ( pControl.FindF( MULTI ) != KErrNotFound )
    {
        error = SaveXmlWithBinaryDataL( iDocument, pOptions,  pBinary, pXml, EMPTY_STRING(), TRUE );
    }
    else
    {
        User::Leave(KErrArgument);
    }

    if ( pControl.FindF( ONE_PARA ) != KErrNotFound )
    {
        User::LeaveIfError( TestSerialize1paraToFileL( iDocument, pGzipSerialized, pOptions, ESerializerGZip ) );
    }

    if ( pControl.FindF( THREE_PARA ) != KErrNotFound )
    {
        User::LeaveIfError ( TestSerialize3paraToFileL( iDocument, pGzipSerialized, pOptions, ESerializerGZip ) );
    }

    if ( pControl.FindF( TO_RFS ) != KErrNotFound )
    {
        User::LeaveIfError( TestSerializeRFsL( iDocument, pGzipSerialized, pOptions, ESerializerGZip ) );
    }

    if ( pControl.FindF( BUFFER ) != KErrNotFound )
    {
        User::LeaveIfError( TestSerializeToBufferL( iDocument, pGzipSerialized, pOptions, ESerializerGZip ) );
    }
    CleanupStack::PopAndDestroy( 1 );
    return error;
}
コード例 #23
0
static enum shell_reply
shell_exec_download_show(struct gnutella_shell *sh,
	int argc, const char *argv[])
{
	fileinfo_t *fi;
	struct guid guid;
	const char *id, *property;
	gnet_fi_status_t status;
	gnet_fi_info_t *info;
	int i;

	shell_check(sh);
	g_assert(argv);
	g_assert(argc > 0);

	if (argc < 3) {
		shell_set_msg(sh, "parameter missing");
		goto error;
	}
	id = argv[2];

	if (!hex_to_guid(id, &guid)) {
		shell_set_msg(sh, "Unparsable ID");
		goto error;
	}

	fi = file_info_by_guid(&guid);
	if (NULL == fi) {
		shell_set_msg(sh, "Invalid ID");
		goto error;
	}

	info = guc_fi_get_info(fi->fi_handle);
	guc_fi_get_status(fi->fi_handle, &status);

	for (i = 3; i < argc; i++) {
		property = argv[i];

		if (0 == strcmp(property, "id")) {
			show_property(sh, property, guid_to_string(info->guid));
		} else if (0 == strcmp(property, "filename")) {
			show_property(sh, property, info->filename);
		} else if (0 == strcmp(property, "pathname")) {
			show_property(sh, property, fi->pathname);
		} else if (0 == strcmp(property, "size")) {
			show_property(sh, property, filesize_to_string(info->size));
		} else if (0 == strcmp(property, "sha1")) {
			show_property(sh, property,
				info->sha1 ? sha1_to_urn_string(info->sha1) : "");
		} else if (0 == strcmp(property, "tth")) {
			show_property(sh, property,
				info->tth ? tth_to_urn_string(info->tth) : "");
		} else if (0 == strcmp(property, "bitprint")) {
			show_property(sh, property,
				(info->sha1 && info->tth)
					? bitprint_to_urn_string(info->sha1, info->tth) : "");
		} else if (0 == strcmp(property, "created")) {
			show_property(sh, property,
				info->created ? timestamp_to_string(info->created) : "");
		} else if (0 == strcmp(property, "modified")) {
			show_property(sh, property,
				status.modified ? timestamp_to_string(status.modified) : "");
		} else if (0 == strcmp(property, "downloaded")) {
			show_property(sh, property, filesize_to_string(status.done));
		} else if (0 == strcmp(property, "uploaded")) {
			show_property(sh, property, uint64_to_string(status.uploaded));
		} else if (0 == strcmp(property, "paused")) {
			show_property(sh, property, boolean_to_string(status.paused));
		} else if (0 == strcmp(property, "seeding")) {
			show_property(sh, property, boolean_to_string(status.seeding));
		} else if (0 == strcmp(property, "verifying")) {
			show_property(sh, property, boolean_to_string(status.verifying));
		} else if (0 == strcmp(property, "finished")) {
			show_property(sh, property, boolean_to_string(status.finished));
		} else if (0 == strcmp(property, "complete")) {
			show_property(sh, property, boolean_to_string(status.complete));
		} else if (0 == strcmp(property, "magnet")) {
			char *magnet = file_info_build_magnet(fi->fi_handle);
			show_property(sh, property, EMPTY_STRING(magnet));
			HFREE_NULL(magnet);
		}
	}
	guc_fi_free_info(info);
	return REPLY_READY;

error:
	return REPLY_ERROR;
}
コード例 #24
0
/**
 * Misc. tools for config parsing
 */
int            GetStringParam(config_item_t block, const char *block_name,
                              const char *var_name, param_flags_t flags, char *target,
                              unsigned int target_size, char ***extra_args_tab,
                              unsigned int *nb_extra_args, char *err_msg)
{
    config_item_t  curr_item;
    int            rc;
    int            extra = 0;
    char          *name;
    char          *value;
    gsize          sz;

    err_msg[0] = '\0';

    if ( nb_extra_args )
        *nb_extra_args = 0;
    if ( extra_args_tab )
        *extra_args_tab = NULL;

    rc = get_cfg_param(block, block_name, var_name, flags, &name, &value,
                       &extra, &curr_item, err_msg);
    if (rc)
        return rc;

    sz = g_strlcpy(target, value, target_size);
    if (sz >= target_size) {
        sprintf(err_msg, "Option too long for parameter '%s::%s', line %d", block_name,
                var_name, rh_config_GetItemLine(curr_item));
        return EINVAL;
    }

    if ( extra )
    {
        if ( !extra_args_tab || !nb_extra_args )
        {
            sprintf( err_msg, "Unexpected options for parameter '%s::%s', line %d", block_name,
                     var_name, rh_config_GetItemLine( curr_item ) );
            return EINVAL;
        }
        else
        {
            *nb_extra_args = rh_config_GetExtraArgs( curr_item, extra_args_tab );
        }
    }

    /* checks */

    /* empty string? */
    if ((flags & PFLG_NOT_EMPTY) && EMPTY_STRING(target))
    {
        sprintf(err_msg, "Unexpected empty parameter '%s::%s', line %d",
                block_name, var_name, rh_config_GetItemLine(curr_item));
        return EINVAL;
    }

    /* are stdio names allowed ? */
    if ((flags & PFLG_STDIO_ALLOWED) && is_stdname(target))
            return 0;

    if ((flags & PFLG_ABSOLUTE_PATH) && !IS_ABSOLUTE_PATH(target))
    {
        sprintf( err_msg, "Absolute path expected for parameter '%s::%s', line %d", block_name,
                 var_name, rh_config_GetItemLine( curr_item ) );
        return EINVAL;
    }

    if ((flags & PFLG_NO_WILDCARDS) && WILDCARDS_IN(target))
    {
        sprintf( err_msg, "Wildcards are not allowed in '%s::%s', line %d", block_name,
                 var_name, rh_config_GetItemLine( curr_item ) );
        return EINVAL;
    }

    if (flags & PFLG_MAIL)
    {
        char          *arob = strchr( target, '@' );

        /* check there is an arobase, and this arobase has text before and after */
        if ( ( arob == NULL ) || ( arob == target ) || ( *( arob + 1 ) == '\0' ) )
        {
            sprintf( err_msg, "Invalid mail address in '%s::%s', line %d", block_name, var_name,
                     rh_config_GetItemLine( curr_item ) );
            return EINVAL;
        }
    }

    if ((flags & PFLG_REMOVE_FINAL_SLASH) && FINAL_SLASH(target))
         REMOVE_FINAL_SLASH(target);

    return 0;

}
コード例 #25
0
ファイル: soap.c プロジェクト: Haxe/gtk-gnutella
/**
 * Process the SOAP reply from the server.
 */
static void
soap_process_reply(soap_rpc_t *sr)
{
	const char *buf;
	vxml_parser_t *vp;
	vxml_error_t e;
	xnode_t *root = NULL;
	xnode_t *xn = NULL;
	const char *charset;

	soap_rpc_check(sr);

	if (sr->reply_len != 0 && (GNET_PROPERTY(soap_trace) & SOCK_TRACE_IN)) {
		g_debug("----Got SOAP HTTP reply data from %s:", sr->url);
		if (log_printable(LOG_STDERR)) {
			fwrite(sr->reply_data, sr->reply_len, 1, stderr);
			fputs("----End SOAP HTTP reply\n", stderr);
		}
	}

	if (GNET_PROPERTY(soap_debug) > 2) {
		g_debug("SOAP \"%s\" at \"%s\": processing reply (%lu byte%s) HTTP %d",
			sr->action, sr->url, (unsigned long) sr->reply_len,
			1 == sr->reply_len ? "" : "s", sr->http_code);
	}

	/*
	 * If we got a 2xx reply, we need to parse up to the <Body> element
	 * and then pass up the remaining to the user for parsing specific
	 * elemnts accordingly.
	 *
	 * Other reply codes indicate an error.  On 4xx replies we may not
	 * have any XML to parse.  On 5xx replies, we should usually have
	 * a <Fault> indication under the <Body>.
	 *
	 * The strategy used here is to parse the XML reply into a tree and then
	 * analyse the tree, ignoring the HTTP status code which is redundant.
	 */

	buf = header_get(sr->header, "Content-Type");
	if (NULL == buf)
		goto no_xml;

	/*
	 * MIME type and subtypes are case-insensitive (see RFC 2616, section 3.7).
	 */

	if (
		!http_field_starts_with(buf, SOAP_TEXT_REPLY, FALSE) &&
		!http_field_starts_with(buf, SOAP_APPLICATION_REPLY, FALSE)
	) {
		if (GNET_PROPERTY(soap_debug)) {
			g_debug("SOAP \"%s\" at \"%s\": got unexpected Content-Type: %s",
				sr->action, sr->url, buf);
		}
		goto no_xml;
	}

	/*
	 * Extract charset if given.
	 */

	charset = http_parameter_get(buf, "charset");

	/*
	 * Parse the SOAP envelope.
	 */

	vp = vxml_parser_make(sr->action, VXML_O_STRIP_BLANKS);
	vxml_parser_add_data(vp, sr->reply_data, sr->reply_len);

	if (!vxml_parser_set_charset(vp, charset)) {
		g_warning("SOAP \"%s\" at \"%s\": ignoring unknown charset \"%s\"",
			sr->action, sr->url, charset);
	}

	e = vxml_parse_tree(vp, &root);
	vxml_parser_free(vp);

	if (e != VXML_E_OK) {
		if (GNET_PROPERTY(soap_debug)) {
			g_debug("SOAP \"%s\" at \"%s\": cannot parse XML reply: %s",
				sr->action, sr->url, vxml_strerror(e));
		}
		goto bad_xml;
	}

	g_assert(root != NULL);

	/*
	 * Make sure we got a SOAP reply.
	 */

	if (!xnode_is_element_named(root, SOAP_NAMESPACE, SOAP_X_ENVELOPE))
		goto not_soap;

	/*
	 * Look for the <SOAP:Body> element.
	 */

	for (xn = xnode_first_child(root); TRUE; xn = xnode_next_sibling(xn)) {
		if (NULL == xn || !xnode_within_namespace(xn, SOAP_NAMESPACE))
			goto bad_soap;
		if (0 == strcmp(SOAP_X_BODY, xnode_element_name(xn)))
			break;
	}

	/*
	 * Inspect the first child of the <SOAP:Body> element.
	 *
	 * If it's a <SOAP:Fault>, go process it and return an error.
	 * If it's another SOAP tag, we have an unknown structure.
	 * Otherwise it's the reply, for user code to handle.
	 */

	xn = xnode_first_child(xn);

	if (NULL == xn)
		goto bad_soap;

	if (xnode_is_element_named(xn, SOAP_NAMESPACE, SOAP_X_FAULT)) {
		xnode_detach(xn);
		soap_fault(sr, xn);
	} else if (xnode_within_namespace(xn, SOAP_NAMESPACE)) {
		goto bad_soap;
	} else {
		xnode_detach(xn);
		soap_reply(sr, xn);
	}

	xnode_tree_free(root);
	return;

not_soap:
	if (GNET_PROPERTY(soap_debug)) {
		g_debug("SOAP \"%s\" at \"%s\": unexpected root XML "
			"element <%s:%s>",
			sr->action, sr->url, EMPTY_STRING(xnode_element_ns(root)),
			xnode_element_name(root));
	}
	xnode_tree_free(root);
	/* FALL THROUGH */

no_xml:
	soap_error(sr, SOAP_E_PROTOCOL);
	return;

bad_soap:
	if (GNET_PROPERTY(soap_debug)) {
		g_debug("SOAP \"%s\" at \"%s\": unexpected XML structure",
			sr->action, sr->url);
	}
	if (GNET_PROPERTY(soap_debug) > 1) {
		g_debug("SOAP current node is %s", xnode_to_string(xn));
	}
	if (GNET_PROPERTY(soap_debug) > 2)
		xfmt_tree_dump(root, stderr);

	xnode_tree_free(root);
	/* FALL THROUGH */

bad_xml:
	soap_error(sr, SOAP_E_PROCESSING);
	return;
}
コード例 #26
0
ファイル: RobinhoodMisc.c プロジェクト: bringhurst/robinhood
/**
 * Search for Robinhood config file.
 * search a config file with the given name (+extension)
 * If cfg_in is empty: search any config in config paths
 * /!\ not thread safe
 */
int SearchConfig( const char * cfg_in, char * cfg_out, int * changed )
{
    static const char * default_cfg_paths[] =
    {
       "/etc/robinhood.d/"PURPOSE_EXT,
       "/etc/robinhood.d",
       "/etc/robinhood",
       ".",
       NULL
    };
    const char * current_path;
    int i;
    DIR * dir;
    struct dirent * ent;
    struct stat stbuf;
    *changed = 1; /* most of the cases */

    if (cfg_in == NULL || EMPTY_STRING(cfg_in))
    {
       for ( i = 0, current_path = default_cfg_paths[0];
             current_path != NULL;
             i++, current_path = default_cfg_paths[i] )
       {
            /* look for files in current path */
            dir = opendir( current_path );
            if ( !dir )
                continue;

            while ( (ent = readdir(dir)) != NULL )
            {
                /* ignore .xxx files */
                if (ent->d_name[0] == '.')
                    continue;

                sprintf( cfg_out, "%s/%s", current_path, ent->d_name );
                if ( (stat( cfg_out, &stbuf ) == 0)
                     && S_ISREG(stbuf.st_mode) )
                {
                    /* file found: OK */
                    closedir(dir);
                    return 0;
                }
            }

            closedir(dir);
       }
    }
    else if (access(cfg_in, F_OK) == 0)
    {
        /* the specified config file exists */
        strcpy(cfg_out, cfg_in);
        *changed=0;
        return 0;
    }
    else if (strchr(cfg_in, '/'))
    {
        /* the argument is a path (not a single name
         * and this path was not found) */
        *changed=0;
        return -ENOENT;
    }
    else /* look for a file in the given paths */
    {
        char cfg_cp[RBH_PATH_MAX];
        int has_ext = (strchr(cfg_in, '.') != NULL);

        strcpy(cfg_cp, cfg_in);

        for ( i = 0, current_path = default_cfg_paths[0];
             current_path != NULL;
             i++, current_path = default_cfg_paths[i] )
        {
            /* if the file already has an extension, try path/name */
            if (has_ext)
            {
                sprintf(cfg_out, "%s/%s", current_path, cfg_cp);
                if (access(cfg_out, F_OK) == 0)
                    return 0;
            }

            /* try path/name.cfg, path/name.conf */
            sprintf(cfg_out, "%s/%s.conf", current_path, cfg_cp);
            if (access(cfg_out, F_OK) == 0)
                return 0;

            sprintf(cfg_out, "%s/%s.cfg", current_path, cfg_cp);
            if (access(cfg_out, F_OK) == 0)
                return 0;
        }
    }

    /* no file found, cleaning cfg_out */
    cfg_out[0] = '\0';
    return -ENOENT;
}
コード例 #27
0
ファイル: rbh_diff.c プロジェクト: karig/robinhood
/**
 * Main daemon routine
 */
int main( int argc, char **argv )
{
    int            c, i, option_index = 0;
    char          *bin = basename( argv[0] );

    int            rc;
    char           err_msg[4096];
    robinhood_config_t rh_config;
    int chgd = 0;
    char           badcfg[RBH_PATH_MAX];
    char           tag_name[256] = "";

    start_time = time( NULL );

    zero_options( &options );

    /* parse command line options */
    while ( ( c = getopt_long( argc, argv, SHORT_OPT_STRING, option_tab, &option_index ) ) != -1 )
    {
        switch ( c )
        {
        case 's':
            options.partial_scan = TRUE;
            rh_strncpy(options.partial_scan_path, optarg, RBH_PATH_MAX);
            /* clean final slash */
            if (FINAL_SLASH(options.partial_scan_path))
                REMOVE_FINAL_SLASH(options.partial_scan_path);
            break;

        case 'd':
            if (parse_diff_mask(optarg, &options.diff_mask, err_msg))
            {
                fprintf(stderr,
                        "Invalid argument for --diff: %s\n", err_msg);
                exit( 1 );
            }
            break;

        case 'a':
            if (optarg)
            {
                if (!strcasecmp(optarg,"fs"))
                    options.diff_arg.apply = APPLY_FS;
                else if (!strcasecmp(optarg,"db"))
                    options.diff_arg.apply = APPLY_DB;
                else
                {
                    fprintf(stderr, "Invalid argument for --apply: '%s' (fs or db expected)\n",
                            optarg);
                    exit( 1 );
                }
            }
            else
                options.diff_arg.apply = APPLY_DB;
            break;

        case 'D':
                options.flags |= FLAG_DRY_RUN;
            break;

        case 'f':
            rh_strncpy(options.config_file, optarg, MAX_OPT_LEN);
            break;
#ifdef _HSM_LITE
        case 'b':
            options.diff_arg.recov_from_backend  = 1;
            break;
#endif
#ifdef _HAVE_FID /* only for lustre 2.x */
        case 'o':
            rh_strncpy(options.output_dir, optarg, MAX_OPT_LEN);
            break;
#endif
        case 'l':
            options.force_log_level = TRUE;
            options.log_level = str2debuglevel( optarg );
            if ( options.log_level == -1 )
            {
                fprintf( stderr,
                         "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n",
                         optarg );
                exit( 1 );
            }
            break;
        case 'h':
            display_help( bin );
            exit( 0 );
            break;
        case 'V':
            display_version( bin );
            exit( 0 );
            break;
        case ':':
        case '?':
        default:
            fprintf(stderr,"Run '%s --help' for more details.\n", bin);
            exit( 1 );
            break;
        }
    }

    /* check there is no extra arguments */
    if ( optind != argc )
    {
        fprintf( stderr, "Error: unexpected argument on command line: %s\n", argv[optind] );
        exit( 1 );
    }

    /* Initialize global tools */
#ifdef _LUSTRE
    if ( ( rc = Lustre_Init(  ) ) )
    {
        fprintf( stderr, "Error %d initializing liblustreapi\n", rc );
        exit( 1 );
    }
#endif

    /* Initilize uidgid cache */
    if ( InitUidGid_Cache(  ) )
    {
        fprintf( stderr, "Error initializing uid/gid cache\n" );
        exit( 1 );
    }

    /* get default config file, if not specified */
    if (SearchConfig(options.config_file, options.config_file, &chgd,
                      badcfg, MAX_OPT_LEN) != 0)
    {
        fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg);
        exit(2);
    }
    else if (chgd)
    {
        fprintf(stderr, "Using config file '%s'.\n", options.config_file );
    }

    if ( ReadRobinhoodConfig( MODULE_MASK_FS_SCAN | MODULE_MASK_ENTRY_PROCESSOR,
                              options.config_file, err_msg,
                              &rh_config, FALSE ) )
    {
        fprintf( stderr, "Error reading configuration file '%s': %s\n",
                 options.config_file, err_msg );
        exit( 1 );
    }
    process_config_file = options.config_file;

    /* set global configuration */
    global_config = rh_config.global_config;

    /* set policies info */
    policies = rh_config.policies;

    if (options.force_log_level)
        rh_config.log_config.debug_level = options.log_level;
    else
        rh_config.log_config.debug_level = LVL_CRIT; /* no event message */

    /* Set logging to stderr */
    strcpy( rh_config.log_config.log_file, "stderr" );
    strcpy( rh_config.log_config.report_file, "stderr" );
    strcpy( rh_config.log_config.alert_file, "stderr" );

    /* Initialize logging */
    rc = InitializeLogs( bin, &rh_config.log_config );
    if ( rc )
    {
        fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n",
                 rc, errno, strerror( errno ) );
        exit( rc );
    }

    /* Initialize filesystem access */
    rc = InitFS();
    if (rc)
        exit(rc);

#ifdef _HSM_LITE
    rc = Backend_Start( &rh_config.backend_config, options.flags );
    if ( rc )
    {
        DisplayLog( LVL_CRIT, DIFF_TAG, "Error initializing backend" );
        exit( 1 );
    }
#endif

    /* Initialize list manager */
    rc = ListMgr_Init( &rh_config.lmgr_config, FALSE );
    if ( rc )
    {
        DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing list manager", rc );
        exit( rc );
    }
    else
        DisplayLog( LVL_VERB, DIFF_TAG, "ListManager successfully initialized" );


    if ( CheckLastFS(  ) != 0 )
        exit( 1 );

    if (options.diff_mask)
        rh_config.entry_proc_config.diff_mask = options.diff_mask;
    else
    {
        /* parse "all" */
        char tmpstr[] = "all";
        if (parse_diff_mask(tmpstr, &rh_config.entry_proc_config.diff_mask, err_msg))
        {
            DisplayLog(LVL_CRIT, DIFF_TAG, "unexpected error parsing diff mask: %s", err_msg);
            exit(1);
        }
    }

#ifdef LUSTRE_DUMP_FILES
    if (options.diff_arg.apply == APPLY_FS && !(options.flags & FLAG_DRY_RUN))
    {
        /* open the file to write LOV EA and FID remapping */
        if (!EMPTY_STRING(options.output_dir))
        {
            char fname[RBH_PATH_MAX];
            if (mkdir(options.output_dir, 0700) && (errno != EEXIST))
            {
                DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to create directory %s: %s",
                           options.output_dir, strerror(errno));
                exit(1);
            }
            snprintf(fname, RBH_PATH_MAX-1, "%s/"LOVEA_FNAME, options.output_dir);
            options.diff_arg.lovea_file = fopen(fname, "w");
            if (options.diff_arg.lovea_file == NULL)
            {
                DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writting: %s",
                           fname, strerror(errno));
                exit(1);
            }
            snprintf(fname, RBH_PATH_MAX-1, "%s/"FIDREMAP_FNAME, options.output_dir);
            options.diff_arg.fid_remap_file = fopen(fname, "w");
            if (options.diff_arg.fid_remap_file == NULL)
            {
                DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writting: %s",
                           fname, strerror(errno));
                exit(1);
            }
        }
    }
#endif

    /* if no DB apply action is specified, can't use md_update field for checking
     * removed entries. So, create a special tag for that. */
    if ((options.diff_arg.apply != APPLY_DB) || (options.flags & FLAG_DRY_RUN))
    {
        fprintf(stderr, "Preparing diff table...\n");

        /* create a connexion to the DB. this is safe to use the global lmgr var
         * as statistics thread is not running */
        if (!ensure_db_access())
            exit(1);
        /* create a tag to clear entries after the scan */

        /* There could be several diff running in parallel,
         * so set a suffix to avoid conflicts */
        sprintf(tag_name, "DIFF_%u", (unsigned int) getpid());
        options.diff_arg.db_tag = tag_name;

        /* add filter for partial scan */
        if (options.partial_scan)
        {
            lmgr_filter_t  filter;
            filter_value_t val;
            lmgr_simple_filter_init( &filter );

            char tmp[RBH_PATH_MAX];
            strcpy(tmp, options.partial_scan_path);
            strcat(tmp, "/*");
            val.value.val_str = tmp;
            lmgr_simple_filter_add(&filter, ATTR_INDEX_fullpath, LIKE, val, 0);

            rc = ListMgr_CreateTag(&lmgr, tag_name, &filter, FALSE);
            lmgr_simple_filter_free(&filter);
        }
        else
            rc = ListMgr_CreateTag(&lmgr, tag_name, NULL, FALSE);

        if (rc)
            exit(rc);
    }

    /* Initialise Pipeline */
    rc = EntryProcessor_Init(&rh_config.entry_proc_config, DIFF_PIPELINE,
                             options.flags, &options.diff_arg);
    if ( rc )
    {
        DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing EntryProcessor pipeline", rc );
        goto clean_tag;
    }
    else
        DisplayLog( LVL_VERB, DIFF_TAG, "EntryProcessor successfully initialized" );

    fprintf(stderr, "Starting scan\n");

    /* print header to indicate the content of diff
     * #<diff cmd>
     * ---fs[=/subdir]
     * +++db
     */
    for (i = 0; i < argc; i++)
        printf("%s%s", i==0?"# ":" ", argv[i]);
    printf("\n");
    if (options.diff_arg.apply == APPLY_FS)
    {
        if (options.partial_scan)
            printf("---fs=%s\n",options.partial_scan_path);
        else
            printf("---fs\n");
        printf("+++db\n");
    }
    else
    {
        printf("---db\n");
        if (options.partial_scan)
            printf("+++fs=%s\n",options.partial_scan_path);
        else
            printf("+++fs\n");
    }

    /* Start FS scan */
    if (options.partial_scan)
        rc = FSScan_Start(&rh_config.fs_scan_config, options.flags,
                          options.partial_scan_path);
    else
        rc = FSScan_Start(&rh_config.fs_scan_config, options.flags, NULL);

    if ( rc )
    {
        DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing FS Scan module", rc );
        goto clean_tag;
    }
    else
        DisplayLog( LVL_VERB, DIFF_TAG, "FS Scan module successfully initialized" );

    /* Flush logs now, to have a trace in the logs */
    FlushLogs(  );

    /* both pipeline and scan are now running, can now trap events and display stats */

    /* create signal handling thread */
    rc = pthread_create( &sig_thr, NULL, signal_handler_thr, NULL );
    if ( rc )
    {
        DisplayLog( LVL_CRIT, DIFF_TAG, "Error starting signal handler thread: %s",
                    strerror( errno ) );
        goto clean_tag;
    }
    else
        DisplayLog( LVL_VERB, DIFF_TAG, "Signal handler thread started successfully" );

    pthread_create(&stat_thread, NULL, stats_thr, NULL);

    /* wait for FS scan to end */
    FSScan_Wait(  );
    DisplayLog( LVL_MAJOR, DIFF_TAG, "FS Scan finished" );

    /* Pipeline must be flushed */
    EntryProcessor_Terminate( TRUE );

#ifdef LUSTRE_DUMP_FILES
    /* flush the lovea file */
    if (options.diff_arg.lovea_file)
    {
        fprintf(stderr, " > LOV EA information written to %s/"LOVEA_FNAME"\n", options.output_dir);
        fclose(options.diff_arg.lovea_file);
    }
    if (options.diff_arg.fid_remap_file)
    {
        fprintf(stderr, " > FID remapping written to %s/"FIDREMAP_FNAME"\n", options.output_dir);
        fclose(options.diff_arg.fid_remap_file);
    }
#endif

    fprintf(stderr, "End of scan\n");

    DisplayLog( LVL_MAJOR, DIFF_TAG, "All tasks done! Exiting." );
    rc = 0;

clean_tag:
    /* destroy the tag before exit */
    if (options.diff_arg.db_tag != NULL && ensure_db_access())
    {
        fprintf(stderr, "Cleaning diff table...\n");
        ListMgr_DestroyTag(&lmgr, options.diff_arg.db_tag);
    }

    exit(rc);
    return rc; /* for compiler */
}
コード例 #28
0
/* Flush batched alerts.
 * Must be called under the protection of alert_mutex
 * release mutex ASAP if release_mutex_asap is true,
 * else: don't release it.
 */
static void FlushAlerts(bool release_mutex_asap)
{
    alert_type_t   *pcurr;
    unsigned int    alert_types = 0;
    unsigned int    mail_size = 0;
    char            title[MAIL_TITLE_MAX];
    GString        *contents = NULL;
    time_t          now;
    struct tm       date;

    /* first list scan, to determine the number of alerts, etc... */
    for (pcurr = alert_list; pcurr != NULL; pcurr = pcurr->next) {
        alert_types++;
        mail_size += pcurr->estim_size;
    }

    if (alert_count == 0) {
        if (release_mutex_asap)
            V(alert_mutex);
        return;
    }

    now = time(NULL);
    localtime_r(&now, &date);

    snprintf(title, MAIL_TITLE_MAX,
             "robinhood alert summary (%s on %s): %u alerts",
             global_config.fs_path, machine_name, alert_count);

    contents = g_string_new("");
    g_string_printf(contents, "Date: %.4d/%.2d/%.2d %.2d:%.2d:%.2d\n"
                    "Program: %s (pid %lu)\n"
                    "Host: %s\n"
                    "Filesystem: %s\n",
                    1900 + date.tm_year, date.tm_mon + 1, date.tm_mday,
                    date.tm_hour, date.tm_min, date.tm_sec, prog_name,
                    (unsigned long)getpid(), machine_name,
                    global_config.fs_path);

    g_string_append(contents, "\n===== alert summary ====\n\n");
    g_string_append_printf(contents, "%u alerts:\n", alert_count);

    for (pcurr = alert_list; pcurr != NULL; pcurr = pcurr->next) {
        g_string_append_printf(contents, "\t* %u %s\n", pcurr->count,
                               pcurr->title);
    }

    for (pcurr = alert_list; pcurr != NULL;) {
        unsigned int i;

        g_string_append_printf(contents, "\n==== alert '%s' ====\n\n",
                               pcurr->title);

        for (i = 0; i < pcurr->count; i++) {
            /* print and free */
            if (pcurr->entries[i]) {
                g_string_append_printf(contents, "%s\n", pcurr->entries[i]);
                if (log_config.alert_show_attrs)
                    g_string_append_printf(contents, "Entry info:\n%s\n",
                                           pcurr->info[i]);

                free(pcurr->entries[i]);
                free(pcurr->info[i]);
            }
        }
        /* free the list of entries */
        free(pcurr->entries);
        free(pcurr->info);

        /* set the list to the next item */
        alert_list = pcurr->next;
        /* free the item */
        free(pcurr);
        /* next item */
        pcurr = alert_list;
    }

    /* reset alert count */
    alert_count = 0;

    /* all alerts has been released, we can put the lock */
    if (release_mutex_asap)
        V(alert_mutex);

    /* send the mail and/or write the alert in alert file */
    if (!EMPTY_STRING(log_config.alert_mail))
        SendMail(log_config.alert_mail, title, contents->str);

    if (!EMPTY_STRING(log_config.alert_file)) {
        if (alert.log_type == RBH_LOG_SYSLOG) {
            /* we need to split the content after each '\n' */
            char *curr = contents->str;
            char *next = NULL;
            display_line_log_(&alert, "ALERT", "=== ALERT REPORT ===");
            do {
                next = strchr(curr, '\n');
                if (next != NULL) {
                    next[0] = '\0';
                    next++;
                }
                display_line_log_(&alert, "ALERT", curr);
                curr = next;
            } while (curr != NULL);
            display_line_log_(&alert, "ALERT", "=== END OF ALERT REPORT ===");
        } else {
            display_line_log_(&alert, "ALERT", "=== ALERT REPORT ===\n%s",
                              contents->str);
            display_line_log_(&alert, "ALERT", "=== END OF ALERT REPORT ===");
        }

        /* always flush alerts, because we don't want to lose events */
        flush_log_descr(&alert);
    }

    g_string_free(contents, TRUE);
    /* mutex already released, can go out now */

}   /*  Flush alerts */
コード例 #29
0
ファイル: rbh_rebind.c プロジェクト: cea-hpc/robinhood
static inline int rebind_helper(const char *old_bk_id,
                                const char *new_bk_id,
                                const char *new_path,
                                const char *new_fid_str)
{
    int rc;
    attr_set_t old_attrs = ATTR_SET_INIT;
    attr_set_t new_attrs = ATTR_SET_INIT;
    entry_id_t new_fid;
    entry_id_t old_fid;
    bool old_fid_set = false;
    char *tmp;

    /* full path required */
    tmp = realpath(new_path, NULL);
    if (tmp == NULL) {
        rc = -errno;
        DisplayLog(LVL_CRIT, LOGTAG, "Error in realpath(%s): %s",
                   new_path, strerror(-rc));
        return rc;
    }
    if (strlen(tmp) >= RBH_PATH_MAX) {
        DisplayLog(LVL_CRIT, LOGTAG, "Path length is too long!");
        return -ENAMETOOLONG;
    }
    /* safe because of previous check */
    strcpy(ATTR(&new_attrs, fullpath), tmp);
    ATTR_MASK_SET(&new_attrs, fullpath);
    strcpy(ATTR(&old_attrs, fullpath), tmp);
    ATTR_MASK_SET(&old_attrs, fullpath);
    /* now we can free tmp path */
    free(tmp);

    if ((new_fid_str != NULL) && !EMPTY_STRING(new_fid_str))
        rc = read_fid(new_fid_str, &new_fid);
    else
        /* get fid for the given file */
        rc = Path2Id(new_path, &new_fid);

    if (rc)
        return rc;

    printf("Rebinding '%s' (" DFID ") from '%s' to '%s'...\n", new_path,
           PFID(&new_fid), old_bk_id, new_bk_id);

    /* parse old/new bk ids and set attr accordingly */
    if (parse_bk_id(&old_attrs, old_bk_id, &old_fid, &old_fid_set))
        return -EINVAL;
    if (parse_bk_id(&new_attrs, new_bk_id, &new_fid, NULL))
        return -EINVAL;

    /* rebind is like undelete with 'already recovered = true' */
    rc = smi->sm->undelete_func(smi, old_fid_set ? &old_fid : NULL,
                                &old_attrs, &new_fid, &new_attrs,
                                true);
    fprintf(stderr, "Rebind status for '%s': %s\n", ATTR(&new_attrs, fullpath),
            recov_status2str(rc));
    if (rc == RS_NOBACKUP || rc == RS_ERROR)
        return -1;
    return 0;
}
コード例 #30
0
ファイル: lustre_tools.c プロジェクト: seagate-ssg/robinhood
/**
 * build LOVEA buffer from stripe information
 * @return size of significant information in buffer.
 */
ssize_t BuildLovEA(const entry_id_t * p_id, const attr_set_t * p_attrs, void * buff, size_t buf_sz)
{
    int i;
    size_t len = 0;

    if (!ATTR_MASK_TEST(p_attrs, stripe_info)) /* no stripe info */
        return 0;

    /* check inconsistent values */
    if (!ATTR_MASK_TEST(p_attrs, stripe_items) ||
        (ATTR(p_attrs, stripe_items).count != ATTR(p_attrs, stripe_info).stripe_count))
    {
        DisplayLog(LVL_MAJOR, "BuildLovEA", "ERROR: inconsistent stripe info for "DFID, PFID(p_id));
        return -1;
    }

    /* is there a pool? */
    if (EMPTY_STRING(ATTR(p_attrs, stripe_info).pool_name))
    {
        /* no => build lov_user_md_v1 */
        struct lov_user_md_v1 * p_lum = (struct lov_user_md_v1 *) buff;
        len = sizeof(struct lov_user_md_v1) +
            ATTR(p_attrs, stripe_info).stripe_count * sizeof(struct lov_user_ost_data_v1);

        /* check buffer size */
        if (buf_sz < len)
            return -1;

        p_lum->lmm_magic = LOV_USER_MAGIC_V1;
        p_lum->lmm_pattern = LOV_PATTERN_RAID0; /* the only supported for now */
#ifdef _HAVE_FID
        p_lum->lmm_object_id = p_id->f_oid;
        p_lum->lmm_object_seq = p_id->f_seq;
#else /* lmm_object_gr for Lustre 1.x */
        p_lum->lmm_object_id = p_id->inode;
        p_lum->lmm_object_gr = 0;
#endif
        p_lum->lmm_stripe_size = ATTR(p_attrs, stripe_info).stripe_size;
        p_lum->lmm_stripe_count = ATTR(p_attrs, stripe_info).stripe_count;
        p_lum->lmm_stripe_offset = 0;

        /* set stripe items */
        for ( i = 0; i < ATTR(p_attrs, stripe_items).count; i++ )
        {
            p_lum->lmm_objects[i].l_ost_idx = ATTR(p_attrs, stripe_items).stripe[i].ost_idx;
            p_lum->lmm_objects[i].l_ost_gen = ATTR(p_attrs, stripe_items).stripe[i].ost_gen;
#ifdef HAVE_OBJ_ID
            p_lum->lmm_objects[i].l_object_id = ATTR(p_attrs, stripe_items).stripe[i].obj_id;
#ifdef HAVE_OBJ_SEQ
            p_lum->lmm_objects[i].l_object_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#else
            p_lum->lmm_objects[i].l_object_gr = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#endif
#else /* new structure (union of fid and id/seq) */
            p_lum->lmm_objects[i].l_ost_oi.oi.oi_id = ATTR(p_attrs, stripe_items).obj_id;
            p_lum->lmm_objects[i].l_ost_oi.oi.oi_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#endif
        }
        return len;
    }
    else
    {
        /* yes => build lov_user_md_v3 */
        struct lov_user_md_v3 * p_lum = (struct lov_user_md_v3 *) buff;
        len = sizeof(struct lov_user_md_v3) +
            ATTR(p_attrs, stripe_info).stripe_count * sizeof(struct lov_user_ost_data_v1);

        /* check buffer size */
        if (buf_sz < len)
            return (size_t)-1;

        p_lum->lmm_magic = LOV_USER_MAGIC_V3;
        p_lum->lmm_pattern = LOV_PATTERN_RAID0; /* the only supported for now */
#ifdef _HAVE_FID
        p_lum->lmm_object_id = p_id->f_oid;
        p_lum->lmm_object_seq = p_id->f_seq;
#else /* lmm_object_gr for Lustre 1.x */
        p_lum->lmm_object_id = p_id->inode;
        p_lum->lmm_object_gr = 0;
#endif
        p_lum->lmm_stripe_size = ATTR(p_attrs, stripe_info).stripe_size;
        p_lum->lmm_stripe_count = ATTR(p_attrs, stripe_info).stripe_count;
        p_lum->lmm_stripe_offset = 0;
        /* pool name */
        rh_strncpy(p_lum->lmm_pool_name, ATTR(p_attrs, stripe_info).pool_name, LOV_MAXPOOLNAME);

        /* set stripe items */
        for ( i = 0; i < ATTR(p_attrs, stripe_items).count; i++ )
        {
            p_lum->lmm_objects[i].l_ost_idx = ATTR(p_attrs, stripe_items).stripe[i].ost_idx;
            p_lum->lmm_objects[i].l_ost_gen = ATTR(p_attrs, stripe_items).stripe[i].ost_gen;
#ifdef HAVE_OBJ_ID
            p_lum->lmm_objects[i].l_object_id = ATTR(p_attrs, stripe_items).stripe[i].obj_id;
#ifdef HAVE_OBJ_SEQ
            p_lum->lmm_objects[i].l_object_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#else
            p_lum->lmm_objects[i].l_object_gr = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#endif
#else /* new structure (union of fid and id/seq) */
            p_lum->lmm_objects[i].l_ost_oi.oi.oi_id = ATTR(p_attrs, stripe_items).obj_id;
            p_lum->lmm_objects[i].l_ost_oi.oi.oi_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq;
#endif
        }
        return len;
    }
}